1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655 |
- /*!
- * wavesurfer.js 6.1.0 (2022-03-31)
- * https://wavesurfer-js.org
- * @license BSD-3-Clause
- */
- (function webpackUniversalModuleDefinition(root, factory) {
- if(typeof exports === 'object' && typeof module === 'object')
- module.exports = factory();
- else if(typeof define === 'function' && define.amd)
- define("WaveSurfer", [], factory);
- else if(typeof exports === 'object')
- exports["WaveSurfer"] = factory();
- else
- root["WaveSurfer"] = factory();
- })(self, function() {
- return /******/ (() => { // webpackBootstrap
- /******/ var __webpack_modules__ = ({
- /***/ "./src/drawer.canvasentry.js":
- /*!***********************************!*\
- !*** ./src/drawer.canvasentry.js ***!
- \***********************************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- var _style = _interopRequireDefault(__webpack_require__(/*! ./util/style */ "./src/util/style.js"));
- var _getId = _interopRequireDefault(__webpack_require__(/*! ./util/get-id */ "./src/util/get-id.js"));
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- /**
- * The `CanvasEntry` class represents an element consisting of a wave `canvas`
- * and an (optional) progress wave `canvas`.
- *
- * The `MultiCanvas` renderer uses one or more `CanvasEntry` instances to
- * render a waveform, depending on the zoom level.
- */
- var CanvasEntry = /*#__PURE__*/function () {
- function CanvasEntry() {
- _classCallCheck(this, CanvasEntry);
- /**
- * The wave node
- *
- * @type {HTMLCanvasElement}
- */
- this.wave = null;
- /**
- * The wave canvas rendering context
- *
- * @type {CanvasRenderingContext2D}
- */
- this.waveCtx = null;
- /**
- * The (optional) progress wave node
- *
- * @type {HTMLCanvasElement}
- */
- this.progress = null;
- /**
- * The (optional) progress wave canvas rendering context
- *
- * @type {CanvasRenderingContext2D}
- */
- this.progressCtx = null;
- /**
- * Start of the area the canvas should render, between 0 and 1
- *
- * @type {number}
- */
- this.start = 0;
- /**
- * End of the area the canvas should render, between 0 and 1
- *
- * @type {number}
- */
- this.end = 1;
- /**
- * Unique identifier for this entry
- *
- * @type {string}
- */
- this.id = (0, _getId.default)(typeof this.constructor.name !== 'undefined' ? this.constructor.name.toLowerCase() + '_' : 'canvasentry_');
- /**
- * Canvas 2d context attributes
- *
- * @type {object}
- */
- this.canvasContextAttributes = {};
- }
- /**
- * Store the wave canvas element and create the 2D rendering context
- *
- * @param {HTMLCanvasElement} element The wave `canvas` element.
- */
- _createClass(CanvasEntry, [{
- key: "initWave",
- value: function initWave(element) {
- this.wave = element;
- this.waveCtx = this.wave.getContext('2d', this.canvasContextAttributes);
- }
- /**
- * Store the progress wave canvas element and create the 2D rendering
- * context
- *
- * @param {HTMLCanvasElement} element The progress wave `canvas` element.
- */
- }, {
- key: "initProgress",
- value: function initProgress(element) {
- this.progress = element;
- this.progressCtx = this.progress.getContext('2d', this.canvasContextAttributes);
- }
- /**
- * Update the dimensions
- *
- * @param {number} elementWidth Width of the entry
- * @param {number} totalWidth Total width of the multi canvas renderer
- * @param {number} width The new width of the element
- * @param {number} height The new height of the element
- */
- }, {
- key: "updateDimensions",
- value: function updateDimensions(elementWidth, totalWidth, width, height) {
- // where the canvas starts and ends in the waveform, represented as a
- // decimal between 0 and 1
- this.start = this.wave.offsetLeft / totalWidth || 0;
- this.end = this.start + elementWidth / totalWidth; // set wave canvas dimensions
- this.wave.width = width;
- this.wave.height = height;
- var elementSize = {
- width: elementWidth + 'px'
- };
- (0, _style.default)(this.wave, elementSize);
- if (this.hasProgressCanvas) {
- // set progress canvas dimensions
- this.progress.width = width;
- this.progress.height = height;
- (0, _style.default)(this.progress, elementSize);
- }
- }
- /**
- * Clear the wave and progress rendering contexts
- */
- }, {
- key: "clearWave",
- value: function clearWave() {
- // wave
- this.waveCtx.clearRect(0, 0, this.waveCtx.canvas.width, this.waveCtx.canvas.height); // progress
- if (this.hasProgressCanvas) {
- this.progressCtx.clearRect(0, 0, this.progressCtx.canvas.width, this.progressCtx.canvas.height);
- }
- }
- /**
- * Set the fill styles for wave and progress
- * @param {string|string[]} waveColor Fill color for the wave canvas,
- * or an array of colors to apply as a gradient
- * @param {?string|string[]} progressColor Fill color for the progress canvas,
- * or an array of colors to apply as a gradient
- */
- }, {
- key: "setFillStyles",
- value: function setFillStyles(waveColor, progressColor) {
- this.waveCtx.fillStyle = this.getFillStyle(this.waveCtx, waveColor);
- if (this.hasProgressCanvas) {
- this.progressCtx.fillStyle = this.getFillStyle(this.progressCtx, progressColor);
- }
- }
- /**
- * Utility function to handle wave color arguments
- *
- * When the color argument type is a string or CanvasGradient instance,
- * it will be returned as is. Otherwise, it will be treated as an array,
- * and a new CanvasGradient will be returned
- *
- * @since 6.0.0
- * @param {CanvasRenderingContext2D} ctx Rendering context of target canvas
- * @param {string|string[]|CanvasGradient} color Either a single fill color
- * for the wave canvas, an existing CanvasGradient instance, or an array
- * of colors to apply as a gradient
- * @returns {string|CanvasGradient} Returns a string fillstyle value, or a
- * canvas gradient
- */
- }, {
- key: "getFillStyle",
- value: function getFillStyle(ctx, color) {
- if (typeof color == 'string' || color instanceof CanvasGradient) {
- return color;
- }
- var waveGradient = ctx.createLinearGradient(0, 0, 0, ctx.canvas.height);
- color.forEach(function (value, index) {
- return waveGradient.addColorStop(index / color.length, value);
- });
- return waveGradient;
- }
- /**
- * Set the canvas transforms for wave and progress
- *
- * @param {boolean} vertical Whether to render vertically
- */
- }, {
- key: "applyCanvasTransforms",
- value: function applyCanvasTransforms(vertical) {
- if (vertical) {
- // Reflect the waveform across the line y = -x
- this.waveCtx.setTransform(0, 1, 1, 0, 0, 0);
- if (this.hasProgressCanvas) {
- this.progressCtx.setTransform(0, 1, 1, 0, 0, 0);
- }
- }
- }
- /**
- * Draw a rectangle for wave and progress
- *
- * @param {number} x X start position
- * @param {number} y Y start position
- * @param {number} width Width of the rectangle
- * @param {number} height Height of the rectangle
- * @param {number} radius Radius of the rectangle
- */
- }, {
- key: "fillRects",
- value: function fillRects(x, y, width, height, radius) {
- this.fillRectToContext(this.waveCtx, x, y, width, height, radius);
- if (this.hasProgressCanvas) {
- this.fillRectToContext(this.progressCtx, x, y, width, height, radius);
- }
- }
- /**
- * Draw the actual rectangle on a `canvas` element
- *
- * @param {CanvasRenderingContext2D} ctx Rendering context of target canvas
- * @param {number} x X start position
- * @param {number} y Y start position
- * @param {number} width Width of the rectangle
- * @param {number} height Height of the rectangle
- * @param {number} radius Radius of the rectangle
- */
- }, {
- key: "fillRectToContext",
- value: function fillRectToContext(ctx, x, y, width, height, radius) {
- if (!ctx) {
- return;
- }
- if (radius) {
- this.drawRoundedRect(ctx, x, y, width, height, radius);
- } else {
- ctx.fillRect(x, y, width, height);
- }
- }
- /**
- * Draw a rounded rectangle on Canvas
- *
- * @param {CanvasRenderingContext2D} ctx Canvas context
- * @param {number} x X-position of the rectangle
- * @param {number} y Y-position of the rectangle
- * @param {number} width Width of the rectangle
- * @param {number} height Height of the rectangle
- * @param {number} radius Radius of the rectangle
- *
- * @return {void}
- * @example drawRoundedRect(ctx, 50, 50, 5, 10, 3)
- */
- }, {
- key: "drawRoundedRect",
- value: function drawRoundedRect(ctx, x, y, width, height, radius) {
- if (height === 0) {
- return;
- } // peaks are float values from -1 to 1. Use absolute height values in
- // order to correctly calculate rounded rectangle coordinates
- if (height < 0) {
- height *= -1;
- y -= height;
- }
- ctx.beginPath();
- ctx.moveTo(x + radius, y);
- ctx.lineTo(x + width - radius, y);
- ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
- ctx.lineTo(x + width, y + height - radius);
- ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
- ctx.lineTo(x + radius, y + height);
- ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
- ctx.lineTo(x, y + radius);
- ctx.quadraticCurveTo(x, y, x + radius, y);
- ctx.closePath();
- ctx.fill();
- }
- /**
- * Render the actual wave and progress lines
- *
- * @param {number[]} peaks Array with peaks data
- * @param {number} absmax Maximum peak value (absolute)
- * @param {number} halfH Half the height of the waveform
- * @param {number} offsetY Offset to the top
- * @param {number} start The x-offset of the beginning of the area that
- * should be rendered
- * @param {number} end The x-offset of the end of the area that
- * should be rendered
- */
- }, {
- key: "drawLines",
- value: function drawLines(peaks, absmax, halfH, offsetY, start, end) {
- this.drawLineToContext(this.waveCtx, peaks, absmax, halfH, offsetY, start, end);
- if (this.hasProgressCanvas) {
- this.drawLineToContext(this.progressCtx, peaks, absmax, halfH, offsetY, start, end);
- }
- }
- /**
- * Render the actual waveform line on a `canvas` element
- *
- * @param {CanvasRenderingContext2D} ctx Rendering context of target canvas
- * @param {number[]} peaks Array with peaks data
- * @param {number} absmax Maximum peak value (absolute)
- * @param {number} halfH Half the height of the waveform
- * @param {number} offsetY Offset to the top
- * @param {number} start The x-offset of the beginning of the area that
- * should be rendered
- * @param {number} end The x-offset of the end of the area that
- * should be rendered
- */
- }, {
- key: "drawLineToContext",
- value: function drawLineToContext(ctx, peaks, absmax, halfH, offsetY, start, end) {
- if (!ctx) {
- return;
- }
- var length = peaks.length / 2;
- var first = Math.round(length * this.start); // use one more peak value to make sure we join peaks at ends -- unless,
- // of course, this is the last canvas
- var last = Math.round(length * this.end) + 1;
- var canvasStart = first;
- var canvasEnd = last;
- var scale = this.wave.width / (canvasEnd - canvasStart - 1); // optimization
- var halfOffset = halfH + offsetY;
- var absmaxHalf = absmax / halfH;
- ctx.beginPath();
- ctx.moveTo((canvasStart - first) * scale, halfOffset);
- ctx.lineTo((canvasStart - first) * scale, halfOffset - Math.round((peaks[2 * canvasStart] || 0) / absmaxHalf));
- var i, peak, h;
- for (i = canvasStart; i < canvasEnd; i++) {
- peak = peaks[2 * i] || 0;
- h = Math.round(peak / absmaxHalf);
- ctx.lineTo((i - first) * scale + this.halfPixel, halfOffset - h);
- } // draw the bottom edge going backwards, to make a single
- // closed hull to fill
- var j = canvasEnd - 1;
- for (j; j >= canvasStart; j--) {
- peak = peaks[2 * j + 1] || 0;
- h = Math.round(peak / absmaxHalf);
- ctx.lineTo((j - first) * scale + this.halfPixel, halfOffset - h);
- }
- ctx.lineTo((canvasStart - first) * scale, halfOffset - Math.round((peaks[2 * canvasStart + 1] || 0) / absmaxHalf));
- ctx.closePath();
- ctx.fill();
- }
- /**
- * Destroys this entry
- */
- }, {
- key: "destroy",
- value: function destroy() {
- this.waveCtx = null;
- this.wave = null;
- this.progressCtx = null;
- this.progress = null;
- }
- /**
- * Return image data of the wave `canvas` element
- *
- * When using a `type` of `'blob'`, this will return a `Promise` that
- * resolves with a `Blob` instance.
- *
- * @param {string} format='image/png' An optional value of a format type.
- * @param {number} quality=0.92 An optional value between 0 and 1.
- * @param {string} type='dataURL' Either 'dataURL' or 'blob'.
- * @return {string|Promise} When using the default `'dataURL'` `type` this
- * returns a data URL. When using the `'blob'` `type` this returns a
- * `Promise` that resolves with a `Blob` instance.
- */
- }, {
- key: "getImage",
- value: function getImage(format, quality, type) {
- var _this = this;
- if (type === 'blob') {
- return new Promise(function (resolve) {
- _this.wave.toBlob(resolve, format, quality);
- });
- } else if (type === 'dataURL') {
- return this.wave.toDataURL(format, quality);
- }
- }
- }]);
- return CanvasEntry;
- }();
- exports["default"] = CanvasEntry;
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/drawer.js":
- /*!***********************!*\
- !*** ./src/drawer.js ***!
- \***********************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
- /**
- * Parent class for renderers
- *
- * @extends {Observer}
- */
- var Drawer = /*#__PURE__*/function (_util$Observer) {
- _inherits(Drawer, _util$Observer);
- var _super = _createSuper(Drawer);
- /**
- * @param {HTMLElement} container The container node of the wavesurfer instance
- * @param {WavesurferParams} params The wavesurfer initialisation options
- */
- function Drawer(container, params) {
- var _this;
- _classCallCheck(this, Drawer);
- _this = _super.call(this);
- _this.container = util.withOrientation(container, params.vertical);
- /**
- * @type {WavesurferParams}
- */
- _this.params = params;
- /**
- * The width of the renderer
- * @type {number}
- */
- _this.width = 0;
- /**
- * The height of the renderer
- * @type {number}
- */
- _this.height = params.height * _this.params.pixelRatio;
- _this.lastPos = 0;
- /**
- * The `<wave>` element which is added to the container
- * @type {HTMLElement}
- */
- _this.wrapper = null;
- return _this;
- }
- /**
- * Alias of `util.style`
- *
- * @param {HTMLElement} el The element that the styles will be applied to
- * @param {Object} styles The map of propName: attribute, both are used as-is
- * @return {HTMLElement} el
- */
- _createClass(Drawer, [{
- key: "style",
- value: function style(el, styles) {
- return util.style(el, styles);
- }
- /**
- * Create the wrapper `<wave>` element, style it and set up the events for
- * interaction
- */
- }, {
- key: "createWrapper",
- value: function createWrapper() {
- this.wrapper = util.withOrientation(this.container.appendChild(document.createElement('wave')), this.params.vertical);
- this.style(this.wrapper, {
- display: 'block',
- position: 'relative',
- userSelect: 'none',
- webkitUserSelect: 'none',
- height: this.params.height + 'px'
- });
- if (this.params.fillParent || this.params.scrollParent) {
- this.style(this.wrapper, {
- width: '100%',
- cursor: this.params.hideCursor ? 'none' : 'auto',
- overflowX: this.params.hideScrollbar ? 'hidden' : 'auto',
- overflowY: 'hidden'
- });
- }
- this.setupWrapperEvents();
- }
- /**
- * Handle click event
- *
- * @param {Event} e Click event
- * @param {?boolean} noPrevent Set to true to not call `e.preventDefault()`
- * @return {number} Playback position from 0 to 1
- */
- }, {
- key: "handleEvent",
- value: function handleEvent(e, noPrevent) {
- !noPrevent && e.preventDefault();
- var clientX = util.withOrientation(e.targetTouches ? e.targetTouches[0] : e, this.params.vertical).clientX;
- var bbox = this.wrapper.getBoundingClientRect();
- var nominalWidth = this.width;
- var parentWidth = this.getWidth();
- var progressPixels = this.getProgressPixels(bbox, clientX);
- var progress;
- if (!this.params.fillParent && nominalWidth < parentWidth) {
- progress = progressPixels * (this.params.pixelRatio / nominalWidth) || 0;
- } else {
- progress = (progressPixels + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0;
- }
- return util.clamp(progress, 0, 1);
- }
- }, {
- key: "getProgressPixels",
- value: function getProgressPixels(wrapperBbox, clientX) {
- if (this.params.rtl) {
- return wrapperBbox.right - clientX;
- } else {
- return clientX - wrapperBbox.left;
- }
- }
- }, {
- key: "setupWrapperEvents",
- value: function setupWrapperEvents() {
- var _this2 = this;
- this.wrapper.addEventListener('click', function (e) {
- var orientedEvent = util.withOrientation(e, _this2.params.vertical);
- var scrollbarHeight = _this2.wrapper.offsetHeight - _this2.wrapper.clientHeight;
- if (scrollbarHeight !== 0) {
- // scrollbar is visible. Check if click was on it
- var bbox = _this2.wrapper.getBoundingClientRect();
- if (orientedEvent.clientY >= bbox.bottom - scrollbarHeight) {
- // ignore mousedown as it was on the scrollbar
- return;
- }
- }
- if (_this2.params.interact) {
- _this2.fireEvent('click', e, _this2.handleEvent(e));
- }
- });
- this.wrapper.addEventListener('dblclick', function (e) {
- if (_this2.params.interact) {
- _this2.fireEvent('dblclick', e, _this2.handleEvent(e));
- }
- });
- this.wrapper.addEventListener('scroll', function (e) {
- return _this2.fireEvent('scroll', e);
- });
- }
- /**
- * Draw peaks on the canvas
- *
- * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
- * for split channel rendering
- * @param {number} length The width of the area that should be drawn
- * @param {number} start The x-offset of the beginning of the area that
- * should be rendered
- * @param {number} end The x-offset of the end of the area that should be
- * rendered
- */
- }, {
- key: "drawPeaks",
- value: function drawPeaks(peaks, length, start, end) {
- if (!this.setWidth(length)) {
- this.clearWave();
- }
- this.params.barWidth ? this.drawBars(peaks, 0, start, end) : this.drawWave(peaks, 0, start, end);
- }
- /**
- * Scroll to the beginning
- */
- }, {
- key: "resetScroll",
- value: function resetScroll() {
- if (this.wrapper !== null) {
- this.wrapper.scrollLeft = 0;
- }
- }
- /**
- * Recenter the view-port at a certain percent of the waveform
- *
- * @param {number} percent Value from 0 to 1 on the waveform
- */
- }, {
- key: "recenter",
- value: function recenter(percent) {
- var position = this.wrapper.scrollWidth * percent;
- this.recenterOnPosition(position, true);
- }
- /**
- * Recenter the view-port on a position, either scroll there immediately or
- * in steps of 5 pixels
- *
- * @param {number} position X-offset in pixels
- * @param {boolean} immediate Set to true to immediately scroll somewhere
- */
- }, {
- key: "recenterOnPosition",
- value: function recenterOnPosition(position, immediate) {
- var scrollLeft = this.wrapper.scrollLeft;
- var half = ~~(this.wrapper.clientWidth / 2);
- var maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;
- var target = position - half;
- var offset = target - scrollLeft;
- if (maxScroll == 0) {
- // no need to continue if scrollbar is not there
- return;
- } // if the cursor is currently visible...
- if (!immediate && -half <= offset && offset < half) {
- // set rate at which waveform is centered
- var rate = this.params.autoCenterRate; // make rate depend on width of view and length of waveform
- rate /= half;
- rate *= maxScroll;
- offset = Math.max(-rate, Math.min(rate, offset));
- target = scrollLeft + offset;
- } // limit target to valid range (0 to maxScroll)
- target = Math.max(0, Math.min(maxScroll, target)); // no use attempting to scroll if we're not moving
- if (target != scrollLeft) {
- this.wrapper.scrollLeft = target;
- }
- }
- /**
- * Get the current scroll position in pixels
- *
- * @return {number} Horizontal scroll position in pixels
- */
- }, {
- key: "getScrollX",
- value: function getScrollX() {
- var x = 0;
- if (this.wrapper) {
- var pixelRatio = this.params.pixelRatio;
- x = Math.round(this.wrapper.scrollLeft * pixelRatio); // In cases of elastic scroll (safari with mouse wheel) you can
- // scroll beyond the limits of the container
- // Calculate and floor the scrollable extent to make sure an out
- // of bounds value is not returned
- // Ticket #1312
- if (this.params.scrollParent) {
- var maxScroll = ~~(this.wrapper.scrollWidth * pixelRatio - this.getWidth());
- x = Math.min(maxScroll, Math.max(0, x));
- }
- }
- return x;
- }
- /**
- * Get the width of the container
- *
- * @return {number} The width of the container
- */
- }, {
- key: "getWidth",
- value: function getWidth() {
- return Math.round(this.container.clientWidth * this.params.pixelRatio);
- }
- /**
- * Set the width of the container
- *
- * @param {number} width The new width of the container
- * @return {boolean} Whether the width of the container was updated or not
- */
- }, {
- key: "setWidth",
- value: function setWidth(width) {
- if (this.width == width) {
- return false;
- }
- this.width = width;
- if (this.params.fillParent || this.params.scrollParent) {
- this.style(this.wrapper, {
- width: ''
- });
- } else {
- var newWidth = ~~(this.width / this.params.pixelRatio) + 'px';
- this.style(this.wrapper, {
- width: newWidth
- });
- }
- this.updateSize();
- return true;
- }
- /**
- * Set the height of the container
- *
- * @param {number} height The new height of the container.
- * @return {boolean} Whether the height of the container was updated or not
- */
- }, {
- key: "setHeight",
- value: function setHeight(height) {
- if (height == this.height) {
- return false;
- }
- this.height = height;
- this.style(this.wrapper, {
- height: ~~(this.height / this.params.pixelRatio) + 'px'
- });
- this.updateSize();
- return true;
- }
- /**
- * Called by wavesurfer when progress should be rendered
- *
- * @param {number} progress From 0 to 1
- */
- }, {
- key: "progress",
- value: function progress(_progress) {
- var minPxDelta = 1 / this.params.pixelRatio;
- var pos = Math.round(_progress * this.width) * minPxDelta;
- if (pos < this.lastPos || pos - this.lastPos >= minPxDelta) {
- this.lastPos = pos;
- if (this.params.scrollParent && this.params.autoCenter) {
- var newPos = ~~(this.wrapper.scrollWidth * _progress);
- this.recenterOnPosition(newPos, this.params.autoCenterImmediately);
- }
- this.updateProgress(pos);
- }
- }
- /**
- * This is called when wavesurfer is destroyed
- */
- }, {
- key: "destroy",
- value: function destroy() {
- this.unAll();
- if (this.wrapper) {
- if (this.wrapper.parentNode == this.container.domElement) {
- this.container.removeChild(this.wrapper.domElement);
- }
- this.wrapper = null;
- }
- }
- /* Renderer-specific methods */
- /**
- * Called after cursor related params have changed.
- *
- * @abstract
- */
- }, {
- key: "updateCursor",
- value: function updateCursor() {}
- /**
- * Called when the size of the container changes so the renderer can adjust
- *
- * @abstract
- */
- }, {
- key: "updateSize",
- value: function updateSize() {}
- /**
- * Draw a waveform with bars
- *
- * @abstract
- * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for split channel
- * rendering
- * @param {number} channelIndex The index of the current channel. Normally
- * should be 0
- * @param {number} start The x-offset of the beginning of the area that
- * should be rendered
- * @param {number} end The x-offset of the end of the area that should be
- * rendered
- */
- }, {
- key: "drawBars",
- value: function drawBars(peaks, channelIndex, start, end) {}
- /**
- * Draw a waveform
- *
- * @abstract
- * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for split channel
- * rendering
- * @param {number} channelIndex The index of the current channel. Normally
- * should be 0
- * @param {number} start The x-offset of the beginning of the area that
- * should be rendered
- * @param {number} end The x-offset of the end of the area that should be
- * rendered
- */
- }, {
- key: "drawWave",
- value: function drawWave(peaks, channelIndex, start, end) {}
- /**
- * Clear the waveform
- *
- * @abstract
- */
- }, {
- key: "clearWave",
- value: function clearWave() {}
- /**
- * Render the new progress
- *
- * @abstract
- * @param {number} position X-Offset of progress position in pixels
- */
- }, {
- key: "updateProgress",
- value: function updateProgress(position) {}
- }]);
- return Drawer;
- }(util.Observer);
- exports["default"] = Drawer;
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/drawer.multicanvas.js":
- /*!***********************************!*\
- !*** ./src/drawer.multicanvas.js ***!
- \***********************************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- var _drawer = _interopRequireDefault(__webpack_require__(/*! ./drawer */ "./src/drawer.js"));
- var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
- var _drawer2 = _interopRequireDefault(__webpack_require__(/*! ./drawer.canvasentry */ "./src/drawer.canvasentry.js"));
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
- /**
- * MultiCanvas renderer for wavesurfer. Is currently the default and sole
- * builtin renderer.
- *
- * A `MultiCanvas` consists of one or more `CanvasEntry` instances, depending
- * on the zoom level.
- */
- var MultiCanvas = /*#__PURE__*/function (_Drawer) {
- _inherits(MultiCanvas, _Drawer);
- var _super = _createSuper(MultiCanvas);
- /**
- * @param {HTMLElement} container The container node of the wavesurfer instance
- * @param {WavesurferParams} params The wavesurfer initialisation options
- */
- function MultiCanvas(container, params) {
- var _this;
- _classCallCheck(this, MultiCanvas);
- _this = _super.call(this, container, params);
- /**
- * @type {number}
- */
- _this.maxCanvasWidth = params.maxCanvasWidth;
- /**
- * @type {number}
- */
- _this.maxCanvasElementWidth = Math.round(params.maxCanvasWidth / params.pixelRatio);
- /**
- * Whether or not the progress wave is rendered. If the `waveColor`
- * and `progressColor` are the same color it is not.
- *
- * @type {boolean}
- */
- _this.hasProgressCanvas = params.waveColor != params.progressColor;
- /**
- * @type {number}
- */
- _this.halfPixel = 0.5 / params.pixelRatio;
- /**
- * List of `CanvasEntry` instances.
- *
- * @type {Array}
- */
- _this.canvases = [];
- /**
- * @type {HTMLElement}
- */
- _this.progressWave = null;
- /**
- * Class used to generate entries.
- *
- * @type {function}
- */
- _this.EntryClass = _drawer2.default;
- /**
- * Canvas 2d context attributes.
- *
- * @type {object}
- */
- _this.canvasContextAttributes = params.drawingContextAttributes;
- /**
- * Overlap added between entries to prevent vertical white stripes
- * between `canvas` elements.
- *
- * @type {number}
- */
- _this.overlap = 2 * Math.ceil(params.pixelRatio / 2);
- /**
- * The radius of the wave bars. Makes bars rounded
- *
- * @type {number}
- */
- _this.barRadius = params.barRadius || 0;
- /**
- * Whether to render the waveform vertically. Defaults to false.
- *
- * @type {boolean}
- */
- _this.vertical = params.vertical;
- return _this;
- }
- /**
- * Initialize the drawer
- */
- _createClass(MultiCanvas, [{
- key: "init",
- value: function init() {
- this.createWrapper();
- this.createElements();
- }
- /**
- * Create the canvas elements and style them
- *
- */
- }, {
- key: "createElements",
- value: function createElements() {
- this.progressWave = util.withOrientation(this.wrapper.appendChild(document.createElement('wave')), this.params.vertical);
- this.style(this.progressWave, {
- position: 'absolute',
- zIndex: 3,
- left: 0,
- top: 0,
- bottom: 0,
- overflow: 'hidden',
- width: '0',
- display: 'none',
- boxSizing: 'border-box',
- borderRightStyle: 'solid',
- pointerEvents: 'none'
- });
- this.addCanvas();
- this.updateCursor();
- }
- /**
- * Update cursor style
- */
- }, {
- key: "updateCursor",
- value: function updateCursor() {
- this.style(this.progressWave, {
- borderRightWidth: this.params.cursorWidth + 'px',
- borderRightColor: this.params.cursorColor
- });
- }
- /**
- * Adjust to the updated size by adding or removing canvases
- */
- }, {
- key: "updateSize",
- value: function updateSize() {
- var _this2 = this;
- var totalWidth = Math.round(this.width / this.params.pixelRatio);
- var requiredCanvases = Math.ceil(totalWidth / (this.maxCanvasElementWidth + this.overlap)); // add required canvases
- while (this.canvases.length < requiredCanvases) {
- this.addCanvas();
- } // remove older existing canvases, if any
- while (this.canvases.length > requiredCanvases) {
- this.removeCanvas();
- }
- var canvasWidth = this.maxCanvasWidth + this.overlap;
- var lastCanvas = this.canvases.length - 1;
- this.canvases.forEach(function (entry, i) {
- if (i == lastCanvas) {
- canvasWidth = _this2.width - _this2.maxCanvasWidth * lastCanvas;
- }
- _this2.updateDimensions(entry, canvasWidth, _this2.height);
- entry.clearWave();
- });
- }
- /**
- * Add a canvas to the canvas list
- *
- */
- }, {
- key: "addCanvas",
- value: function addCanvas() {
- var entry = new this.EntryClass();
- entry.canvasContextAttributes = this.canvasContextAttributes;
- entry.hasProgressCanvas = this.hasProgressCanvas;
- entry.halfPixel = this.halfPixel;
- var leftOffset = this.maxCanvasElementWidth * this.canvases.length; // wave
- var wave = util.withOrientation(this.wrapper.appendChild(document.createElement('canvas')), this.params.vertical);
- this.style(wave, {
- position: 'absolute',
- zIndex: 2,
- left: leftOffset + 'px',
- top: 0,
- bottom: 0,
- height: '100%',
- pointerEvents: 'none'
- });
- entry.initWave(wave); // progress
- if (this.hasProgressCanvas) {
- var progress = util.withOrientation(this.progressWave.appendChild(document.createElement('canvas')), this.params.vertical);
- this.style(progress, {
- position: 'absolute',
- left: leftOffset + 'px',
- top: 0,
- bottom: 0,
- height: '100%'
- });
- entry.initProgress(progress);
- }
- this.canvases.push(entry);
- }
- /**
- * Pop single canvas from the list
- *
- */
- }, {
- key: "removeCanvas",
- value: function removeCanvas() {
- var lastEntry = this.canvases[this.canvases.length - 1]; // wave
- lastEntry.wave.parentElement.removeChild(lastEntry.wave.domElement); // progress
- if (this.hasProgressCanvas) {
- lastEntry.progress.parentElement.removeChild(lastEntry.progress.domElement);
- } // cleanup
- if (lastEntry) {
- lastEntry.destroy();
- lastEntry = null;
- }
- this.canvases.pop();
- }
- /**
- * Update the dimensions of a canvas element
- *
- * @param {CanvasEntry} entry Target entry
- * @param {number} width The new width of the element
- * @param {number} height The new height of the element
- */
- }, {
- key: "updateDimensions",
- value: function updateDimensions(entry, width, height) {
- var elementWidth = Math.round(width / this.params.pixelRatio);
- var totalWidth = Math.round(this.width / this.params.pixelRatio); // update canvas dimensions
- entry.updateDimensions(elementWidth, totalWidth, width, height); // style element
- this.style(this.progressWave, {
- display: 'block'
- });
- }
- /**
- * Clear the whole multi-canvas
- */
- }, {
- key: "clearWave",
- value: function clearWave() {
- var _this3 = this;
- util.frame(function () {
- _this3.canvases.forEach(function (entry) {
- return entry.clearWave();
- });
- })();
- }
- /**
- * Draw a waveform with bars
- *
- * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
- * for split channel rendering
- * @param {number} channelIndex The index of the current channel. Normally
- * should be 0. Must be an integer.
- * @param {number} start The x-offset of the beginning of the area that
- * should be rendered
- * @param {number} end The x-offset of the end of the area that should be
- * rendered
- * @returns {void}
- */
- }, {
- key: "drawBars",
- value: function drawBars(peaks, channelIndex, start, end) {
- var _this4 = this;
- return this.prepareDraw(peaks, channelIndex, start, end, function (_ref) {
- var absmax = _ref.absmax,
- hasMinVals = _ref.hasMinVals,
- height = _ref.height,
- offsetY = _ref.offsetY,
- halfH = _ref.halfH,
- peaks = _ref.peaks,
- ch = _ref.channelIndex;
- // if drawBars was called within ws.empty we don't pass a start and
- // don't want anything to happen
- if (start === undefined) {
- return;
- } // Skip every other value if there are negatives.
- var peakIndexScale = hasMinVals ? 2 : 1;
- var length = peaks.length / peakIndexScale;
- var bar = _this4.params.barWidth * _this4.params.pixelRatio;
- var gap = _this4.params.barGap === null ? Math.max(_this4.params.pixelRatio, ~~(bar / 2)) : Math.max(_this4.params.pixelRatio, _this4.params.barGap * _this4.params.pixelRatio);
- var step = bar + gap;
- var scale = length / _this4.width;
- var first = start;
- var last = end;
- var peakIndex = first;
- for (peakIndex; peakIndex < last; peakIndex += step) {
- // search for the highest peak in the range this bar falls into
- var peak = 0;
- var peakIndexRange = Math.floor(peakIndex * scale) * peakIndexScale; // start index
- var peakIndexEnd = Math.floor((peakIndex + step) * scale) * peakIndexScale;
- do {
- // do..while makes sure at least one peak is always evaluated
- var newPeak = Math.abs(peaks[peakIndexRange]); // for arrays starting with negative values
- if (newPeak > peak) {
- peak = newPeak; // higher
- }
- peakIndexRange += peakIndexScale; // skip every other value for negatives
- } while (peakIndexRange < peakIndexEnd); // calculate the height of this bar according to the highest peak found
- var h = Math.round(peak / absmax * halfH); // in case of silences, allow the user to specify that we
- // always draw *something* (normally a 1px high bar)
- if (h == 0 && _this4.params.barMinHeight) {
- h = _this4.params.barMinHeight;
- }
- _this4.fillRect(peakIndex + _this4.halfPixel, halfH - h + offsetY, bar + _this4.halfPixel, h * 2, _this4.barRadius, ch);
- }
- });
- }
- /**
- * Draw a waveform
- *
- * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays
- * for split channel rendering
- * @param {number} channelIndex The index of the current channel. Normally
- * should be 0
- * @param {number?} start The x-offset of the beginning of the area that
- * should be rendered (If this isn't set only a flat line is rendered)
- * @param {number?} end The x-offset of the end of the area that should be
- * rendered
- * @returns {void}
- */
- }, {
- key: "drawWave",
- value: function drawWave(peaks, channelIndex, start, end) {
- var _this5 = this;
- return this.prepareDraw(peaks, channelIndex, start, end, function (_ref2) {
- var absmax = _ref2.absmax,
- hasMinVals = _ref2.hasMinVals,
- height = _ref2.height,
- offsetY = _ref2.offsetY,
- halfH = _ref2.halfH,
- peaks = _ref2.peaks,
- channelIndex = _ref2.channelIndex;
- if (!hasMinVals) {
- var reflectedPeaks = [];
- var len = peaks.length;
- var i = 0;
- for (i; i < len; i++) {
- reflectedPeaks[2 * i] = peaks[i];
- reflectedPeaks[2 * i + 1] = -peaks[i];
- }
- peaks = reflectedPeaks;
- } // if drawWave was called within ws.empty we don't pass a start and
- // end and simply want a flat line
- if (start !== undefined) {
- _this5.drawLine(peaks, absmax, halfH, offsetY, start, end, channelIndex);
- } // always draw a median line
- _this5.fillRect(0, halfH + offsetY - _this5.halfPixel, _this5.width, _this5.halfPixel, _this5.barRadius, channelIndex);
- });
- }
- /**
- * Tell the canvas entries to render their portion of the waveform
- *
- * @param {number[]} peaks Peaks data
- * @param {number} absmax Maximum peak value (absolute)
- * @param {number} halfH Half the height of the waveform
- * @param {number} offsetY Offset to the top
- * @param {number} start The x-offset of the beginning of the area that
- * should be rendered
- * @param {number} end The x-offset of the end of the area that
- * should be rendered
- * @param {channelIndex} channelIndex The channel index of the line drawn
- */
- }, {
- key: "drawLine",
- value: function drawLine(peaks, absmax, halfH, offsetY, start, end, channelIndex) {
- var _this6 = this;
- var _ref3 = this.params.splitChannelsOptions.channelColors[channelIndex] || {},
- waveColor = _ref3.waveColor,
- progressColor = _ref3.progressColor;
- this.canvases.forEach(function (entry, i) {
- _this6.setFillStyles(entry, waveColor, progressColor);
- _this6.applyCanvasTransforms(entry, _this6.params.vertical);
- entry.drawLines(peaks, absmax, halfH, offsetY, start, end);
- });
- }
- /**
- * Draw a rectangle on the multi-canvas
- *
- * @param {number} x X-position of the rectangle
- * @param {number} y Y-position of the rectangle
- * @param {number} width Width of the rectangle
- * @param {number} height Height of the rectangle
- * @param {number} radius Radius of the rectangle
- * @param {channelIndex} channelIndex The channel index of the bar drawn
- */
- }, {
- key: "fillRect",
- value: function fillRect(x, y, width, height, radius, channelIndex) {
- var startCanvas = Math.floor(x / this.maxCanvasWidth);
- var endCanvas = Math.min(Math.ceil((x + width) / this.maxCanvasWidth) + 1, this.canvases.length);
- var i = startCanvas;
- for (i; i < endCanvas; i++) {
- var entry = this.canvases[i];
- var leftOffset = i * this.maxCanvasWidth;
- var intersection = {
- x1: Math.max(x, i * this.maxCanvasWidth),
- y1: y,
- x2: Math.min(x + width, i * this.maxCanvasWidth + entry.wave.width),
- y2: y + height
- };
- if (intersection.x1 < intersection.x2) {
- var _ref4 = this.params.splitChannelsOptions.channelColors[channelIndex] || {},
- waveColor = _ref4.waveColor,
- progressColor = _ref4.progressColor;
- this.setFillStyles(entry, waveColor, progressColor);
- this.applyCanvasTransforms(entry, this.params.vertical);
- entry.fillRects(intersection.x1 - leftOffset, intersection.y1, intersection.x2 - intersection.x1, intersection.y2 - intersection.y1, radius);
- }
- }
- }
- /**
- * Returns whether to hide the channel from being drawn based on params.
- *
- * @param {number} channelIndex The index of the current channel.
- * @returns {bool} True to hide the channel, false to draw.
- */
- }, {
- key: "hideChannel",
- value: function hideChannel(channelIndex) {
- return this.params.splitChannels && this.params.splitChannelsOptions.filterChannels.includes(channelIndex);
- }
- /**
- * Performs preparation tasks and calculations which are shared by `drawBars`
- * and `drawWave`
- *
- * @param {number[]|Number.<Array[]>} peaks Can also be an array of arrays for
- * split channel rendering
- * @param {number} channelIndex The index of the current channel. Normally
- * should be 0
- * @param {number?} start The x-offset of the beginning of the area that
- * should be rendered. If this isn't set only a flat line is rendered
- * @param {number?} end The x-offset of the end of the area that should be
- * rendered
- * @param {function} fn The render function to call, e.g. `drawWave`
- * @param {number} drawIndex The index of the current channel after filtering.
- * @param {number?} normalizedMax Maximum modulation value across channels for use with relativeNormalization. Ignored when undefined
- * @returns {void}
- */
- }, {
- key: "prepareDraw",
- value: function prepareDraw(peaks, channelIndex, start, end, fn, drawIndex, normalizedMax) {
- var _this7 = this;
- return util.frame(function () {
- // Split channels and call this function with the channelIndex set
- if (peaks[0] instanceof Array) {
- var channels = peaks;
- if (_this7.params.splitChannels) {
- var filteredChannels = channels.filter(function (c, i) {
- return !_this7.hideChannel(i);
- });
- if (!_this7.params.splitChannelsOptions.overlay) {
- _this7.setHeight(Math.max(filteredChannels.length, 1) * _this7.params.height * _this7.params.pixelRatio);
- }
- var overallAbsMax;
- if (_this7.params.splitChannelsOptions && _this7.params.splitChannelsOptions.relativeNormalization) {
- // calculate maximum peak across channels to use for normalization
- overallAbsMax = util.max(channels.map(function (channelPeaks) {
- return util.absMax(channelPeaks);
- }));
- }
- return channels.forEach(function (channelPeaks, i) {
- return _this7.prepareDraw(channelPeaks, i, start, end, fn, filteredChannels.indexOf(channelPeaks), overallAbsMax);
- });
- }
- peaks = channels[0];
- } // Return and do not draw channel peaks if hidden.
- if (_this7.hideChannel(channelIndex)) {
- return;
- } // calculate maximum modulation value, either from the barHeight
- // parameter or if normalize=true from the largest value in the peak
- // set
- var absmax = 1 / _this7.params.barHeight;
- if (_this7.params.normalize) {
- absmax = normalizedMax === undefined ? util.absMax(peaks) : normalizedMax;
- } // Bar wave draws the bottom only as a reflection of the top,
- // so we don't need negative values
- var hasMinVals = [].some.call(peaks, function (val) {
- return val < 0;
- });
- var height = _this7.params.height * _this7.params.pixelRatio;
- var halfH = height / 2;
- var offsetY = height * drawIndex || 0; // Override offsetY if overlay is true
- if (_this7.params.splitChannelsOptions && _this7.params.splitChannelsOptions.overlay) {
- offsetY = 0;
- }
- return fn({
- absmax: absmax,
- hasMinVals: hasMinVals,
- height: height,
- offsetY: offsetY,
- halfH: halfH,
- peaks: peaks,
- channelIndex: channelIndex
- });
- })();
- }
- /**
- * Set the fill styles for a certain entry (wave and progress)
- *
- * @param {CanvasEntry} entry Target entry
- * @param {string} waveColor Wave color to draw this entry
- * @param {string} progressColor Progress color to draw this entry
- */
- }, {
- key: "setFillStyles",
- value: function setFillStyles(entry) {
- var waveColor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.params.waveColor;
- var progressColor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.params.progressColor;
- entry.setFillStyles(waveColor, progressColor);
- }
- /**
- * Set the canvas transforms for a certain entry (wave and progress)
- *
- * @param {CanvasEntry} entry Target entry
- * @param {boolean} vertical Whether to render the waveform vertically
- */
- }, {
- key: "applyCanvasTransforms",
- value: function applyCanvasTransforms(entry) {
- var vertical = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- entry.applyCanvasTransforms(vertical);
- }
- /**
- * Return image data of the multi-canvas
- *
- * When using a `type` of `'blob'`, this will return a `Promise`.
- *
- * @param {string} format='image/png' An optional value of a format type.
- * @param {number} quality=0.92 An optional value between 0 and 1.
- * @param {string} type='dataURL' Either 'dataURL' or 'blob'.
- * @return {string|string[]|Promise} When using the default `'dataURL'`
- * `type` this returns a single data URL or an array of data URLs,
- * one for each canvas. When using the `'blob'` `type` this returns a
- * `Promise` that resolves with an array of `Blob` instances, one for each
- * canvas.
- */
- }, {
- key: "getImage",
- value: function getImage(format, quality, type) {
- if (type === 'blob') {
- return Promise.all(this.canvases.map(function (entry) {
- return entry.getImage(format, quality, type);
- }));
- } else if (type === 'dataURL') {
- var images = this.canvases.map(function (entry) {
- return entry.getImage(format, quality, type);
- });
- return images.length > 1 ? images : images[0];
- }
- }
- /**
- * Render the new progress
- *
- * @param {number} position X-offset of progress position in pixels
- */
- }, {
- key: "updateProgress",
- value: function updateProgress(position) {
- this.style(this.progressWave, {
- width: position + 'px'
- });
- }
- }]);
- return MultiCanvas;
- }(_drawer.default);
- exports["default"] = MultiCanvas;
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/mediaelement-webaudio.js":
- /*!**************************************!*\
- !*** ./src/mediaelement-webaudio.js ***!
- \**************************************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- var _mediaelement = _interopRequireDefault(__webpack_require__(/*! ./mediaelement */ "./src/mediaelement.js"));
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }
- function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
- /**
- * MediaElementWebAudio backend: load audio via an HTML5 audio tag, but playback with the WebAudio API.
- * The advantage here is that the html5 <audio> tag can perform range requests on the server and not
- * buffer the entire file in one request, and you still get the filtering and scripting functionality
- * of the webaudio API.
- * Note that in order to use range requests and prevent buffering, you must provide peak data.
- *
- * @since 3.2.0
- */
- var MediaElementWebAudio = /*#__PURE__*/function (_MediaElement) {
- _inherits(MediaElementWebAudio, _MediaElement);
- var _super = _createSuper(MediaElementWebAudio);
- /**
- * Construct the backend
- *
- * @param {WavesurferParams} params Wavesurfer parameters
- */
- function MediaElementWebAudio(params) {
- var _this;
- _classCallCheck(this, MediaElementWebAudio);
- _this = _super.call(this, params);
- /** @private */
- _this.params = params;
- /** @private */
- _this.sourceMediaElement = null;
- return _this;
- }
- /**
- * Initialise the backend, called in `wavesurfer.createBackend()`
- */
- _createClass(MediaElementWebAudio, [{
- key: "init",
- value: function init() {
- this.setPlaybackRate(this.params.audioRate);
- this.createTimer();
- this.createVolumeNode();
- this.createScriptNode();
- this.createAnalyserNode();
- }
- /**
- * Private method called by both `load` (from url)
- * and `loadElt` (existing media element) methods.
- *
- * @param {HTMLMediaElement} media HTML5 Audio or Video element
- * @param {number[]|Number.<Array[]>} peaks Array of peak data
- * @param {string} preload HTML 5 preload attribute value
- * @private
- */
- }, {
- key: "_load",
- value: function _load(media, peaks, preload) {
- _get(_getPrototypeOf(MediaElementWebAudio.prototype), "_load", this).call(this, media, peaks, preload);
- this.createMediaElementSource(media);
- }
- /**
- * Create MediaElementSource node
- *
- * @since 3.2.0
- * @param {HTMLMediaElement} mediaElement HTML5 Audio to load
- */
- }, {
- key: "createMediaElementSource",
- value: function createMediaElementSource(mediaElement) {
- this.sourceMediaElement = this.ac.createMediaElementSource(mediaElement);
- this.sourceMediaElement.connect(this.analyser);
- }
- }, {
- key: "play",
- value: function play(start, end) {
- this.resumeAudioContext();
- return _get(_getPrototypeOf(MediaElementWebAudio.prototype), "play", this).call(this, start, end);
- }
- /**
- * This is called when wavesurfer is destroyed
- *
- */
- }, {
- key: "destroy",
- value: function destroy() {
- _get(_getPrototypeOf(MediaElementWebAudio.prototype), "destroy", this).call(this);
- this.destroyWebAudio();
- }
- }]);
- return MediaElementWebAudio;
- }(_mediaelement.default);
- exports["default"] = MediaElementWebAudio;
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/mediaelement.js":
- /*!*****************************!*\
- !*** ./src/mediaelement.js ***!
- \*****************************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- var _webaudio = _interopRequireDefault(__webpack_require__(/*! ./webaudio */ "./src/webaudio.js"));
- var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }
- function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
- /**
- * MediaElement backend
- */
- var MediaElement = /*#__PURE__*/function (_WebAudio) {
- _inherits(MediaElement, _WebAudio);
- var _super = _createSuper(MediaElement);
- /**
- * Construct the backend
- *
- * @param {WavesurferParams} params Wavesurfer parameters
- */
- function MediaElement(params) {
- var _this;
- _classCallCheck(this, MediaElement);
- _this = _super.call(this, params);
- /** @private */
- _this.params = params;
- /**
- * Initially a dummy media element to catch errors. Once `_load` is
- * called, this will contain the actual `HTMLMediaElement`.
- * @private
- */
- _this.media = {
- currentTime: 0,
- duration: 0,
- paused: true,
- playbackRate: 1,
- play: function play() {},
- pause: function pause() {},
- volume: 0
- };
- /** @private */
- _this.mediaType = params.mediaType.toLowerCase();
- /** @private */
- _this.elementPosition = params.elementPosition;
- /** @private */
- _this.peaks = null;
- /** @private */
- _this.playbackRate = 1;
- /** @private */
- _this.volume = 1;
- /** @private */
- _this.isMuted = false;
- /** @private */
- _this.buffer = null;
- /** @private */
- _this.onPlayEnd = null;
- /** @private */
- _this.mediaListeners = {};
- return _this;
- }
- /**
- * Initialise the backend, called in `wavesurfer.createBackend()`
- */
- _createClass(MediaElement, [{
- key: "init",
- value: function init() {
- this.setPlaybackRate(this.params.audioRate);
- this.createTimer();
- }
- /**
- * Attach event listeners to media element.
- */
- }, {
- key: "_setupMediaListeners",
- value: function _setupMediaListeners() {
- var _this2 = this;
- this.mediaListeners.error = function () {
- _this2.fireEvent('error', 'Error loading media element');
- };
- this.mediaListeners.canplay = function () {
- _this2.fireEvent('canplay');
- };
- this.mediaListeners.ended = function () {
- _this2.fireEvent('finish');
- }; // listen to and relay play, pause and seeked events to enable
- // playback control from the external media element
- this.mediaListeners.play = function () {
- _this2.fireEvent('play');
- };
- this.mediaListeners.pause = function () {
- _this2.fireEvent('pause');
- };
- this.mediaListeners.seeked = function (event) {
- _this2.fireEvent('seek');
- };
- this.mediaListeners.volumechange = function (event) {
- _this2.isMuted = _this2.media.muted;
- if (_this2.isMuted) {
- _this2.volume = 0;
- } else {
- _this2.volume = _this2.media.volume;
- }
- _this2.fireEvent('volume');
- }; // reset event listeners
- Object.keys(this.mediaListeners).forEach(function (id) {
- _this2.media.removeEventListener(id, _this2.mediaListeners[id]);
- _this2.media.addEventListener(id, _this2.mediaListeners[id]);
- });
- }
- /**
- * Create a timer to provide a more precise `audioprocess` event.
- */
- }, {
- key: "createTimer",
- value: function createTimer() {
- var _this3 = this;
- var onAudioProcess = function onAudioProcess() {
- if (_this3.isPaused()) {
- return;
- }
- _this3.fireEvent('audioprocess', _this3.getCurrentTime()); // Call again in the next frame
- util.frame(onAudioProcess)();
- };
- this.on('play', onAudioProcess); // Update the progress one more time to prevent it from being stuck in
- // case of lower framerates
- this.on('pause', function () {
- _this3.fireEvent('audioprocess', _this3.getCurrentTime());
- });
- }
- /**
- * Create media element with url as its source,
- * and append to container element.
- *
- * @param {string} url Path to media file
- * @param {HTMLElement} container HTML element
- * @param {number[]|Number.<Array[]>} peaks Array of peak data
- * @param {string} preload HTML 5 preload attribute value
- * @throws Will throw an error if the `url` argument is not a valid media
- * element.
- */
- }, {
- key: "load",
- value: function load(url, container, peaks, preload) {
- var media = document.createElement(this.mediaType);
- media.controls = this.params.mediaControls;
- media.autoplay = this.params.autoplay || false;
- media.preload = preload == null ? 'auto' : preload;
- media.src = url;
- media.style.width = '100%';
- var prevMedia = container.querySelector(this.mediaType);
- if (prevMedia) {
- container.removeChild(prevMedia);
- }
- container.appendChild(media);
- this._load(media, peaks, preload);
- }
- /**
- * Load existing media element.
- *
- * @param {HTMLMediaElement} elt HTML5 Audio or Video element
- * @param {number[]|Number.<Array[]>} peaks Array of peak data
- */
- }, {
- key: "loadElt",
- value: function loadElt(elt, peaks) {
- elt.controls = this.params.mediaControls;
- elt.autoplay = this.params.autoplay || false;
- this._load(elt, peaks, elt.preload);
- }
- /**
- * Method called by both `load` (from url)
- * and `loadElt` (existing media element) methods.
- *
- * @param {HTMLMediaElement} media HTML5 Audio or Video element
- * @param {number[]|Number.<Array[]>} peaks Array of peak data
- * @param {string} preload HTML 5 preload attribute value
- * @throws Will throw an error if the `media` argument is not a valid media
- * element.
- * @private
- */
- }, {
- key: "_load",
- value: function _load(media, peaks, preload) {
- // verify media element is valid
- if (!(media instanceof HTMLMediaElement) || typeof media.addEventListener === 'undefined') {
- throw new Error('media parameter is not a valid media element');
- } // load must be called manually on iOS, otherwise peaks won't draw
- // until a user interaction triggers load --> 'ready' event
- //
- // note that we avoid calling media.load here when given peaks and preload == 'none'
- // as this almost always triggers some browser fetch of the media.
- if (typeof media.load == 'function' && !(peaks && preload == 'none')) {
- // Resets the media element and restarts the media resource. Any
- // pending events are discarded. How much media data is fetched is
- // still affected by the preload attribute.
- media.load();
- }
- this.media = media;
- this._setupMediaListeners();
- this.peaks = peaks;
- this.onPlayEnd = null;
- this.buffer = null;
- this.isMuted = media.muted;
- this.setPlaybackRate(this.playbackRate);
- this.setVolume(this.volume);
- }
- /**
- * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`
- *
- * @return {boolean} Media paused or not
- */
- }, {
- key: "isPaused",
- value: function isPaused() {
- return !this.media || this.media.paused;
- }
- /**
- * Used by `wavesurfer.getDuration()`
- *
- * @return {number} Duration
- */
- }, {
- key: "getDuration",
- value: function getDuration() {
- if (this.explicitDuration) {
- return this.explicitDuration;
- }
- var duration = (this.buffer || this.media).duration;
- if (duration >= Infinity) {
- // streaming audio
- duration = this.media.seekable.end(0);
- }
- return duration;
- }
- /**
- * Returns the current time in seconds relative to the audio-clip's
- * duration.
- *
- * @return {number} Current time
- */
- }, {
- key: "getCurrentTime",
- value: function getCurrentTime() {
- return this.media && this.media.currentTime;
- }
- /**
- * Get the position from 0 to 1
- *
- * @return {number} Current position
- */
- }, {
- key: "getPlayedPercents",
- value: function getPlayedPercents() {
- return this.getCurrentTime() / this.getDuration() || 0;
- }
- /**
- * Get the audio source playback rate.
- *
- * @return {number} Playback rate
- */
- }, {
- key: "getPlaybackRate",
- value: function getPlaybackRate() {
- return this.playbackRate || this.media.playbackRate;
- }
- /**
- * Set the audio source playback rate.
- *
- * @param {number} value Playback rate
- */
- }, {
- key: "setPlaybackRate",
- value: function setPlaybackRate(value) {
- this.playbackRate = value || 1;
- this.media.playbackRate = this.playbackRate;
- }
- /**
- * Used by `wavesurfer.seekTo()`
- *
- * @param {number} start Position to start at in seconds
- */
- }, {
- key: "seekTo",
- value: function seekTo(start) {
- if (start != null && !isNaN(start)) {
- this.media.currentTime = start;
- }
- this.clearPlayEnd();
- }
- /**
- * Plays the loaded audio region.
- *
- * @param {number} start Start offset in seconds, relative to the beginning
- * of a clip.
- * @param {number} end When to stop, relative to the beginning of a clip.
- * @emits MediaElement#play
- * @return {Promise} Result
- */
- }, {
- key: "play",
- value: function play(start, end) {
- this.seekTo(start);
- var promise = this.media.play();
- end && this.setPlayEnd(end);
- return promise;
- }
- /**
- * Pauses the loaded audio.
- *
- * @emits MediaElement#pause
- * @return {Promise} Result
- */
- }, {
- key: "pause",
- value: function pause() {
- var promise;
- if (this.media) {
- promise = this.media.pause();
- }
- this.clearPlayEnd();
- return promise;
- }
- /**
- * Set the play end
- *
- * @param {number} end Where to end
- */
- }, {
- key: "setPlayEnd",
- value: function setPlayEnd(end) {
- var _this4 = this;
- this.clearPlayEnd();
- this._onPlayEnd = function (time) {
- if (time >= end) {
- _this4.pause();
- _this4.seekTo(end);
- }
- };
- this.on('audioprocess', this._onPlayEnd);
- }
- /** @private */
- }, {
- key: "clearPlayEnd",
- value: function clearPlayEnd() {
- if (this._onPlayEnd) {
- this.un('audioprocess', this._onPlayEnd);
- this._onPlayEnd = null;
- }
- }
- /**
- * Compute the max and min value of the waveform when broken into
- * <length> subranges.
- *
- * @param {number} length How many subranges to break the waveform into.
- * @param {number} first First sample in the required range.
- * @param {number} last Last sample in the required range.
- * @return {number[]|Number.<Array[]>} Array of 2*<length> peaks or array of
- * arrays of peaks consisting of (max, min) values for each subrange.
- */
- }, {
- key: "getPeaks",
- value: function getPeaks(length, first, last) {
- if (this.buffer) {
- return _get(_getPrototypeOf(MediaElement.prototype), "getPeaks", this).call(this, length, first, last);
- }
- return this.peaks || [];
- }
- /**
- * Set the sink id for the media player
- *
- * @param {string} deviceId String value representing audio device id.
- * @returns {Promise} A Promise that resolves to `undefined` when there
- * are no errors.
- */
- }, {
- key: "setSinkId",
- value: function setSinkId(deviceId) {
- if (deviceId) {
- if (!this.media.setSinkId) {
- return Promise.reject(new Error('setSinkId is not supported in your browser'));
- }
- return this.media.setSinkId(deviceId);
- }
- return Promise.reject(new Error('Invalid deviceId: ' + deviceId));
- }
- /**
- * Get the current volume
- *
- * @return {number} value A floating point value between 0 and 1.
- */
- }, {
- key: "getVolume",
- value: function getVolume() {
- return this.volume;
- }
- /**
- * Set the audio volume
- *
- * @param {number} value A floating point value between 0 and 1.
- */
- }, {
- key: "setVolume",
- value: function setVolume(value) {
- this.volume = value; // no need to change when it's already at that volume
- if (this.media.volume !== this.volume) {
- this.media.volume = this.volume;
- }
- }
- /**
- * Enable or disable muted audio
- *
- * @since 4.0.0
- * @param {boolean} muted Specify `true` to mute audio.
- */
- }, {
- key: "setMute",
- value: function setMute(muted) {
- // This causes a volume change to be emitted too through the
- // volumechange event listener.
- this.isMuted = this.media.muted = muted;
- }
- /**
- * This is called when wavesurfer is destroyed
- *
- */
- }, {
- key: "destroy",
- value: function destroy() {
- var _this5 = this;
- this.pause();
- this.unAll();
- this.destroyed = true; // cleanup media event listeners
- Object.keys(this.mediaListeners).forEach(function (id) {
- if (_this5.media) {
- _this5.media.removeEventListener(id, _this5.mediaListeners[id]);
- }
- });
- if (this.params.removeMediaElementOnDestroy && this.media && this.media.parentNode) {
- this.media.parentNode.removeChild(this.media);
- }
- this.media = null;
- }
- }]);
- return MediaElement;
- }(_webaudio.default);
- exports["default"] = MediaElement;
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/peakcache.js":
- /*!**************************!*\
- !*** ./src/peakcache.js ***!
- \**************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- /**
- * Caches the decoded peaks data to improve rendering speed for large audio
- *
- * Is used if the option parameter `partialRender` is set to `true`
- */
- var PeakCache = /*#__PURE__*/function () {
- /**
- * Instantiate cache
- */
- function PeakCache() {
- _classCallCheck(this, PeakCache);
- this.clearPeakCache();
- }
- /**
- * Empty the cache
- */
- _createClass(PeakCache, [{
- key: "clearPeakCache",
- value: function clearPeakCache() {
- /**
- * Flat array with entries that are always in pairs to mark the
- * beginning and end of each subrange. This is a convenience so we can
- * iterate over the pairs for easy set difference operations.
- * @private
- */
- this.peakCacheRanges = [];
- /**
- * Length of the entire cachable region, used for resetting the cache
- * when this changes (zoom events, for instance).
- * @private
- */
- this.peakCacheLength = -1;
- }
- /**
- * Add a range of peaks to the cache
- *
- * @param {number} length The length of the range
- * @param {number} start The x offset of the start of the range
- * @param {number} end The x offset of the end of the range
- * @return {Number.<Array[]>} Array with arrays of numbers
- */
- }, {
- key: "addRangeToPeakCache",
- value: function addRangeToPeakCache(length, start, end) {
- if (length != this.peakCacheLength) {
- this.clearPeakCache();
- this.peakCacheLength = length;
- } // Return ranges that weren't in the cache before the call.
- var uncachedRanges = [];
- var i = 0; // Skip ranges before the current start.
- while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] < start) {
- i++;
- } // If |i| is even, |start| falls after an existing range. Otherwise,
- // |start| falls between an existing range, and the uncached region
- // starts when we encounter the next node in |peakCacheRanges| or
- // |end|, whichever comes first.
- if (i % 2 == 0) {
- uncachedRanges.push(start);
- }
- while (i < this.peakCacheRanges.length && this.peakCacheRanges[i] <= end) {
- uncachedRanges.push(this.peakCacheRanges[i]);
- i++;
- } // If |i| is even, |end| is after all existing ranges.
- if (i % 2 == 0) {
- uncachedRanges.push(end);
- } // Filter out the 0-length ranges.
- uncachedRanges = uncachedRanges.filter(function (item, pos, arr) {
- if (pos == 0) {
- return item != arr[pos + 1];
- } else if (pos == arr.length - 1) {
- return item != arr[pos - 1];
- }
- return item != arr[pos - 1] && item != arr[pos + 1];
- }); // Merge the two ranges together, uncachedRanges will either contain
- // wholly new points, or duplicates of points in peakCacheRanges. If
- // duplicates are detected, remove both and extend the range.
- this.peakCacheRanges = this.peakCacheRanges.concat(uncachedRanges);
- this.peakCacheRanges = this.peakCacheRanges.sort(function (a, b) {
- return a - b;
- }).filter(function (item, pos, arr) {
- if (pos == 0) {
- return item != arr[pos + 1];
- } else if (pos == arr.length - 1) {
- return item != arr[pos - 1];
- }
- return item != arr[pos - 1] && item != arr[pos + 1];
- }); // Push the uncached ranges into an array of arrays for ease of
- // iteration in the functions that call this.
- var uncachedRangePairs = [];
- for (i = 0; i < uncachedRanges.length; i += 2) {
- uncachedRangePairs.push([uncachedRanges[i], uncachedRanges[i + 1]]);
- }
- return uncachedRangePairs;
- }
- /**
- * For testing
- *
- * @return {Number.<Array[]>} Array with arrays of numbers
- */
- }, {
- key: "getCacheRanges",
- value: function getCacheRanges() {
- var peakCacheRangePairs = [];
- var i;
- for (i = 0; i < this.peakCacheRanges.length; i += 2) {
- peakCacheRangePairs.push([this.peakCacheRanges[i], this.peakCacheRanges[i + 1]]);
- }
- return peakCacheRangePairs;
- }
- }]);
- return PeakCache;
- }();
- exports["default"] = PeakCache;
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/absMax.js":
- /*!****************************!*\
- !*** ./src/util/absMax.js ***!
- \****************************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = absMax;
- var _max = _interopRequireDefault(__webpack_require__(/*! ./max */ "./src/util/max.js"));
- var _min = _interopRequireDefault(__webpack_require__(/*! ./min */ "./src/util/min.js"));
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- /**
- * Get the largest absolute value in an array
- *
- * @param {Array} values Array of numbers
- * @returns {Number} Largest number found
- * @example console.log(max([-3, 2, 1]), max([-3, 2, 4])); // logs 3 4
- * @since 4.3.0
- */
- function absMax(values) {
- var max = (0, _max.default)(values);
- var min = (0, _min.default)(values);
- return -min > max ? -min : max;
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/clamp.js":
- /*!***************************!*\
- !*** ./src/util/clamp.js ***!
- \***************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = clamp;
- /**
- * Returns a number limited to the given range.
- *
- * @param {number} val The number to be limited to a range
- * @param {number} min The lower boundary of the limit range
- * @param {number} max The upper boundary of the limit range
- * @returns {number} A number in the range [min, max]
- */
- function clamp(val, min, max) {
- return Math.min(Math.max(min, val), max);
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/fetch.js":
- /*!***************************!*\
- !*** ./src/util/fetch.js ***!
- \***************************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = fetchFile;
- var _observer = _interopRequireDefault(__webpack_require__(/*! ./observer */ "./src/util/observer.js"));
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- var ProgressHandler = /*#__PURE__*/function () {
- /**
- * Instantiate ProgressHandler
- *
- * @param {Observer} instance The `fetchFile` observer instance.
- * @param {Number} contentLength Content length.
- * @param {Response} response Response object.
- */
- function ProgressHandler(instance, contentLength, response) {
- _classCallCheck(this, ProgressHandler);
- this.instance = instance;
- this.instance._reader = response.body.getReader();
- this.total = parseInt(contentLength, 10);
- this.loaded = 0;
- }
- /**
- * A method that is called once, immediately after the `ReadableStream``
- * is constructed.
- *
- * @param {ReadableStreamDefaultController} controller Controller instance
- * used to control the stream.
- */
- _createClass(ProgressHandler, [{
- key: "start",
- value: function start(controller) {
- var _this = this;
- var read = function read() {
- // instance._reader.read() returns a promise that resolves
- // when a value has been received
- _this.instance._reader.read().then(function (_ref) {
- var done = _ref.done,
- value = _ref.value;
- // result objects contain two properties:
- // done - true if the stream has already given you all its data.
- // value - some data. Always undefined when done is true.
- if (done) {
- // ensure onProgress called when content-length=0
- if (_this.total === 0) {
- _this.instance.onProgress.call(_this.instance, {
- loaded: _this.loaded,
- total: _this.total,
- lengthComputable: false
- });
- } // no more data needs to be consumed, close the stream
- controller.close();
- return;
- }
- _this.loaded += value.byteLength;
- _this.instance.onProgress.call(_this.instance, {
- loaded: _this.loaded,
- total: _this.total,
- lengthComputable: !(_this.total === 0)
- }); // enqueue the next data chunk into our target stream
- controller.enqueue(value);
- read();
- }).catch(function (error) {
- controller.error(error);
- });
- };
- read();
- }
- }]);
- return ProgressHandler;
- }();
- /**
- * Load a file using `fetch`.
- *
- * @param {object} options Request options to use. See example below.
- * @returns {Observer} Observer instance
- * @example
- * // default options
- * let options = {
- * url: undefined,
- * method: 'GET',
- * mode: 'cors',
- * credentials: 'same-origin',
- * cache: 'default',
- * responseType: 'json',
- * requestHeaders: [],
- * redirect: 'follow',
- * referrer: 'client'
- * };
- *
- * // override some options
- * options.url = '../media/demo.wav';
- * // available types: 'arraybuffer', 'blob', 'json' or 'text'
- * options.responseType = 'arraybuffer';
- *
- * // make fetch call
- * let request = util.fetchFile(options);
- *
- * // listen for events
- * request.on('progress', e => {
- * console.log('progress', e);
- * });
- *
- * request.on('success', data => {
- * console.log('success!', data);
- * });
- *
- * request.on('error', e => {
- * console.warn('fetchFile error: ', e);
- * });
- */
- function fetchFile(options) {
- if (!options) {
- throw new Error('fetch options missing');
- } else if (!options.url) {
- throw new Error('fetch url missing');
- }
- var instance = new _observer.default();
- var fetchHeaders = new Headers();
- var fetchRequest = new Request(options.url); // add ability to abort
- instance.controller = new AbortController(); // check if headers have to be added
- if (options && options.requestHeaders) {
- // add custom request headers
- options.requestHeaders.forEach(function (header) {
- fetchHeaders.append(header.key, header.value);
- });
- } // parse fetch options
- var responseType = options.responseType || 'json';
- var fetchOptions = {
- method: options.method || 'GET',
- headers: fetchHeaders,
- mode: options.mode || 'cors',
- credentials: options.credentials || 'same-origin',
- cache: options.cache || 'default',
- redirect: options.redirect || 'follow',
- referrer: options.referrer || 'client',
- signal: instance.controller.signal
- };
- fetch(fetchRequest, fetchOptions).then(function (response) {
- // store response reference
- instance.response = response;
- var progressAvailable = true;
- if (!response.body) {
- // ReadableStream is not yet supported in this browser
- // see https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream
- progressAvailable = false;
- } // Server must send CORS header "Access-Control-Expose-Headers: content-length"
- var contentLength = response.headers.get('content-length');
- if (contentLength === null) {
- // Content-Length server response header missing.
- // Don't evaluate download progress if we can't compare against a total size
- // see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Access-Control-Expose-Headers
- progressAvailable = false;
- }
- if (!progressAvailable) {
- // not able to check download progress so skip it
- return response;
- } // fire progress event when during load
- instance.onProgress = function (e) {
- instance.fireEvent('progress', e);
- };
- return new Response(new ReadableStream(new ProgressHandler(instance, contentLength, response)), fetchOptions);
- }).then(function (response) {
- var errMsg;
- if (response.ok) {
- switch (responseType) {
- case 'arraybuffer':
- return response.arrayBuffer();
- case 'json':
- return response.json();
- case 'blob':
- return response.blob();
- case 'text':
- return response.text();
- default:
- errMsg = 'Unknown responseType: ' + responseType;
- break;
- }
- }
- if (!errMsg) {
- errMsg = 'HTTP error status: ' + response.status;
- }
- throw new Error(errMsg);
- }).then(function (response) {
- instance.fireEvent('success', response);
- }).catch(function (error) {
- instance.fireEvent('error', error);
- }); // return the fetch request
- instance.fetchRequest = fetchRequest;
- return instance;
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/frame.js":
- /*!***************************!*\
- !*** ./src/util/frame.js ***!
- \***************************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = frame;
- var _requestAnimationFrame = _interopRequireDefault(__webpack_require__(/*! ./request-animation-frame */ "./src/util/request-animation-frame.js"));
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- /**
- * Create a function which will be called at the next requestAnimationFrame
- * cycle
- *
- * @param {function} func The function to call
- *
- * @return {func} The function wrapped within a requestAnimationFrame
- */
- function frame(func) {
- return function () {
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
- return (0, _requestAnimationFrame.default)(function () {
- return func.apply(void 0, args);
- });
- };
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/get-id.js":
- /*!****************************!*\
- !*** ./src/util/get-id.js ***!
- \****************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = getId;
- /**
- * Get a random prefixed ID
- *
- * @param {String} prefix Prefix to use. Default is `'wavesurfer_'`.
- * @returns {String} Random prefixed ID
- * @example
- * console.log(getId()); // logs 'wavesurfer_b5pors4ru6g'
- *
- * let prefix = 'foo-';
- * console.log(getId(prefix)); // logs 'foo-b5pors4ru6g'
- */
- function getId(prefix) {
- if (prefix === undefined) {
- prefix = 'wavesurfer_';
- }
- return prefix + Math.random().toString(32).substring(2);
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/index.js":
- /*!***************************!*\
- !*** ./src/util/index.js ***!
- \***************************/
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- Object.defineProperty(exports, "Observer", ({
- enumerable: true,
- get: function get() {
- return _observer.default;
- }
- }));
- Object.defineProperty(exports, "absMax", ({
- enumerable: true,
- get: function get() {
- return _absMax.default;
- }
- }));
- Object.defineProperty(exports, "clamp", ({
- enumerable: true,
- get: function get() {
- return _clamp.default;
- }
- }));
- Object.defineProperty(exports, "debounce", ({
- enumerable: true,
- get: function get() {
- return _debounce.default;
- }
- }));
- Object.defineProperty(exports, "fetchFile", ({
- enumerable: true,
- get: function get() {
- return _fetch.default;
- }
- }));
- Object.defineProperty(exports, "frame", ({
- enumerable: true,
- get: function get() {
- return _frame.default;
- }
- }));
- Object.defineProperty(exports, "getId", ({
- enumerable: true,
- get: function get() {
- return _getId.default;
- }
- }));
- Object.defineProperty(exports, "ignoreSilenceMode", ({
- enumerable: true,
- get: function get() {
- return _silenceMode.default;
- }
- }));
- Object.defineProperty(exports, "max", ({
- enumerable: true,
- get: function get() {
- return _max.default;
- }
- }));
- Object.defineProperty(exports, "min", ({
- enumerable: true,
- get: function get() {
- return _min.default;
- }
- }));
- Object.defineProperty(exports, "preventClick", ({
- enumerable: true,
- get: function get() {
- return _preventClick.default;
- }
- }));
- Object.defineProperty(exports, "requestAnimationFrame", ({
- enumerable: true,
- get: function get() {
- return _requestAnimationFrame.default;
- }
- }));
- Object.defineProperty(exports, "style", ({
- enumerable: true,
- get: function get() {
- return _style.default;
- }
- }));
- Object.defineProperty(exports, "withOrientation", ({
- enumerable: true,
- get: function get() {
- return _orientation.default;
- }
- }));
- var _getId = _interopRequireDefault(__webpack_require__(/*! ./get-id */ "./src/util/get-id.js"));
- var _max = _interopRequireDefault(__webpack_require__(/*! ./max */ "./src/util/max.js"));
- var _min = _interopRequireDefault(__webpack_require__(/*! ./min */ "./src/util/min.js"));
- var _absMax = _interopRequireDefault(__webpack_require__(/*! ./absMax */ "./src/util/absMax.js"));
- var _observer = _interopRequireDefault(__webpack_require__(/*! ./observer */ "./src/util/observer.js"));
- var _style = _interopRequireDefault(__webpack_require__(/*! ./style */ "./src/util/style.js"));
- var _requestAnimationFrame = _interopRequireDefault(__webpack_require__(/*! ./request-animation-frame */ "./src/util/request-animation-frame.js"));
- var _frame = _interopRequireDefault(__webpack_require__(/*! ./frame */ "./src/util/frame.js"));
- var _debounce = _interopRequireDefault(__webpack_require__(/*! debounce */ "./node_modules/debounce/index.js"));
- var _preventClick = _interopRequireDefault(__webpack_require__(/*! ./prevent-click */ "./src/util/prevent-click.js"));
- var _fetch = _interopRequireDefault(__webpack_require__(/*! ./fetch */ "./src/util/fetch.js"));
- var _clamp = _interopRequireDefault(__webpack_require__(/*! ./clamp */ "./src/util/clamp.js"));
- var _orientation = _interopRequireDefault(__webpack_require__(/*! ./orientation */ "./src/util/orientation.js"));
- var _silenceMode = _interopRequireDefault(__webpack_require__(/*! ./silence-mode */ "./src/util/silence-mode.js"));
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- /***/ }),
- /***/ "./src/util/max.js":
- /*!*************************!*\
- !*** ./src/util/max.js ***!
- \*************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = max;
- /**
- * Get the largest value
- *
- * @param {Array} values Array of numbers
- * @returns {Number} Largest number found
- * @example console.log(max([1, 2, 3])); // logs 3
- */
- function max(values) {
- var largest = -Infinity;
- Object.keys(values).forEach(function (i) {
- if (values[i] > largest) {
- largest = values[i];
- }
- });
- return largest;
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/min.js":
- /*!*************************!*\
- !*** ./src/util/min.js ***!
- \*************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = min;
- /**
- * Get the smallest value
- *
- * @param {Array} values Array of numbers
- * @returns {Number} Smallest number found
- * @example console.log(min([1, 2, 3])); // logs 1
- */
- function min(values) {
- var smallest = Number(Infinity);
- Object.keys(values).forEach(function (i) {
- if (values[i] < smallest) {
- smallest = values[i];
- }
- });
- return smallest;
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/observer.js":
- /*!******************************!*\
- !*** ./src/util/observer.js ***!
- \******************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- /**
- * @typedef {Object} ListenerDescriptor
- * @property {string} name The name of the event
- * @property {function} callback The callback
- * @property {function} un The function to call to remove the listener
- */
- /**
- * Observer class
- */
- var Observer = /*#__PURE__*/function () {
- /**
- * Instantiate Observer
- */
- function Observer() {
- _classCallCheck(this, Observer);
- /**
- * @private
- * @todo Initialise the handlers here already and remove the conditional
- * assignment in `on()`
- */
- this._disabledEventEmissions = [];
- this.handlers = null;
- }
- /**
- * Attach a handler function for an event.
- *
- * @param {string} event Name of the event to listen to
- * @param {function} fn The callback to trigger when the event is fired
- * @return {ListenerDescriptor} The event descriptor
- */
- _createClass(Observer, [{
- key: "on",
- value: function on(event, fn) {
- var _this = this;
- if (!this.handlers) {
- this.handlers = {};
- }
- var handlers = this.handlers[event];
- if (!handlers) {
- handlers = this.handlers[event] = [];
- }
- handlers.push(fn); // Return an event descriptor
- return {
- name: event,
- callback: fn,
- un: function un(e, fn) {
- return _this.un(e, fn);
- }
- };
- }
- /**
- * Remove an event handler.
- *
- * @param {string} event Name of the event the listener that should be
- * removed listens to
- * @param {function} fn The callback that should be removed
- */
- }, {
- key: "un",
- value: function un(event, fn) {
- if (!this.handlers) {
- return;
- }
- var handlers = this.handlers[event];
- var i;
- if (handlers) {
- if (fn) {
- for (i = handlers.length - 1; i >= 0; i--) {
- if (handlers[i] == fn) {
- handlers.splice(i, 1);
- }
- }
- } else {
- handlers.length = 0;
- }
- }
- }
- /**
- * Remove all event handlers.
- */
- }, {
- key: "unAll",
- value: function unAll() {
- this.handlers = null;
- }
- /**
- * Attach a handler to an event. The handler is executed at most once per
- * event type.
- *
- * @param {string} event The event to listen to
- * @param {function} handler The callback that is only to be called once
- * @return {ListenerDescriptor} The event descriptor
- */
- }, {
- key: "once",
- value: function once(event, handler) {
- var _this2 = this;
- var fn = function fn() {
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
- /* eslint-disable no-invalid-this */
- handler.apply(_this2, args);
- /* eslint-enable no-invalid-this */
- setTimeout(function () {
- _this2.un(event, fn);
- }, 0);
- };
- return this.on(event, fn);
- }
- /**
- * Disable firing a list of events by name. When specified, event handlers for any event type
- * passed in here will not be called.
- *
- * @since 4.0.0
- * @param {string[]} eventNames an array of event names to disable emissions for
- * @example
- * // disable seek and interaction events
- * wavesurfer.setDisabledEventEmissions(['seek', 'interaction']);
- */
- }, {
- key: "setDisabledEventEmissions",
- value: function setDisabledEventEmissions(eventNames) {
- this._disabledEventEmissions = eventNames;
- }
- /**
- * plugins borrow part of this class without calling the constructor,
- * so we have to be careful about _disabledEventEmissions
- */
- }, {
- key: "_isDisabledEventEmission",
- value: function _isDisabledEventEmission(event) {
- return this._disabledEventEmissions && this._disabledEventEmissions.includes(event);
- }
- /**
- * Manually fire an event
- *
- * @param {string} event The event to fire manually
- * @param {...any} args The arguments with which to call the listeners
- */
- }, {
- key: "fireEvent",
- value: function fireEvent(event) {
- for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
- args[_key2 - 1] = arguments[_key2];
- }
- if (!this.handlers || this._isDisabledEventEmission(event)) {
- return;
- }
- var handlers = this.handlers[event];
- handlers && handlers.forEach(function (fn) {
- fn.apply(void 0, args);
- });
- }
- }]);
- return Observer;
- }();
- exports["default"] = Observer;
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/orientation.js":
- /*!*********************************!*\
- !*** ./src/util/orientation.js ***!
- \*********************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = withOrientation;
- var verticalPropMap = {
- width: 'height',
- height: 'width',
- overflowX: 'overflowY',
- overflowY: 'overflowX',
- clientWidth: 'clientHeight',
- clientHeight: 'clientWidth',
- clientX: 'clientY',
- clientY: 'clientX',
- scrollWidth: 'scrollHeight',
- scrollLeft: 'scrollTop',
- offsetLeft: 'offsetTop',
- offsetTop: 'offsetLeft',
- offsetHeight: 'offsetWidth',
- offsetWidth: 'offsetHeight',
- left: 'top',
- right: 'bottom',
- top: 'left',
- bottom: 'right',
- borderRightStyle: 'borderBottomStyle',
- borderRightWidth: 'borderBottomWidth',
- borderRightColor: 'borderBottomColor'
- };
- /**
- * Convert a horizontally-oriented property name to a vertical one.
- *
- * @param {string} prop A property name
- * @param {bool} vertical Whether the element is oriented vertically
- * @returns {string} prop, converted appropriately
- */
- function mapProp(prop, vertical) {
- if (Object.prototype.hasOwnProperty.call(verticalPropMap, prop)) {
- return vertical ? verticalPropMap[prop] : prop;
- } else {
- return prop;
- }
- }
- var isProxy = Symbol("isProxy");
- /**
- * Returns an appropriately oriented object based on vertical.
- * If vertical is true, attribute getting and setting will be mapped through
- * verticalPropMap, so that e.g. getting the object's .width will give its
- * .height instead.
- * Certain methods of an oriented object will return oriented objects as well.
- * Oriented objects can't be added to the DOM directly since they are Proxy objects
- * and thus fail typechecks. Use domElement to get the actual element for this.
- *
- * @param {object} target The object to be wrapped and oriented
- * @param {bool} vertical Whether the element is oriented vertically
- * @returns {Proxy} An oriented object with attr translation via verticalAttrMap
- * @since 5.0.0
- */
- function withOrientation(target, vertical) {
- if (target[isProxy]) {
- return target;
- } else {
- return new Proxy(target, {
- get: function get(obj, prop, receiver) {
- if (prop === isProxy) {
- return true;
- } else if (prop === 'domElement') {
- return obj;
- } else if (prop === 'style') {
- return withOrientation(obj.style, vertical);
- } else if (prop === 'canvas') {
- return withOrientation(obj.canvas, vertical);
- } else if (prop === 'getBoundingClientRect') {
- return function () {
- return withOrientation(obj.getBoundingClientRect.apply(obj, arguments), vertical);
- };
- } else if (prop === 'getContext') {
- return function () {
- return withOrientation(obj.getContext.apply(obj, arguments), vertical);
- };
- } else {
- var value = obj[mapProp(prop, vertical)];
- return typeof value == 'function' ? value.bind(obj) : value;
- }
- },
- set: function set(obj, prop, value) {
- obj[mapProp(prop, vertical)] = value;
- return true;
- }
- });
- }
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/prevent-click.js":
- /*!***********************************!*\
- !*** ./src/util/prevent-click.js ***!
- \***********************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = preventClick;
- /**
- * Stops propagation of click event and removes event listener
- *
- * @private
- * @param {object} event The click event
- */
- function preventClickHandler(event) {
- event.stopPropagation();
- document.body.removeEventListener('click', preventClickHandler, true);
- }
- /**
- * Starts listening for click event and prevent propagation
- *
- * @param {object} values Values
- */
- function preventClick(values) {
- document.body.addEventListener('click', preventClickHandler, true);
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/request-animation-frame.js":
- /*!*********************************************!*\
- !*** ./src/util/request-animation-frame.js ***!
- \*********************************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- /* eslint-disable valid-jsdoc */
- /**
- * Returns the `requestAnimationFrame` function for the browser, or a shim with
- * `setTimeout` if the function is not found
- *
- * @return {function} Available `requestAnimationFrame` function for the browser
- */
- var _default = (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) {
- return setTimeout(callback, 1000 / 60);
- }).bind(window);
- exports["default"] = _default;
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/silence-mode.js":
- /*!**********************************!*\
- !*** ./src/util/silence-mode.js ***!
- \**********************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = ignoreSilenceMode;
- /**
- * Ignores device silence mode when using the `WebAudio` backend.
- *
- * Many mobile devices contain a hardware button to mute the ringtone for incoming
- * calls and messages. Unfortunately, on some platforms like iOS, this also mutes
- * wavesurfer's audio when using the `WebAudio` backend. This function creates a
- * temporary `<audio>` element that makes sure the WebAudio backend keeps playing
- * when muting the device ringer.
- *
- * @since 5.2.0
- */
- function ignoreSilenceMode() {
- // Set the src to a short bit of url encoded as a silent mp3
- // NOTE The silence MP3 must be high quality, when web audio sounds are played
- // in parallel the web audio sound is mixed to match the bitrate of the html sound
- // 0.01 seconds of silence VBR220-260 Joint Stereo 859B
- var audioData = "data:audio/mpeg;base64,//uQxAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAACcQCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA//////////////////////////////////////////////////////////////////8AAABhTEFNRTMuMTAwA8MAAAAAAAAAABQgJAUHQQAB9AAAAnGMHkkIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//sQxAADgnABGiAAQBCqgCRMAAgEAH///////////////7+n/9FTuQsQH//////2NG0jWUGlio5gLQTOtIoeR2WX////X4s9Atb/JRVCbBUpeRUq//////////////////9RUi0f2jn/+xDECgPCjAEQAABN4AAANIAAAAQVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ=="; // disable iOS Airplay (setting the attribute in js doesn't work)
- var tmp = document.createElement("div");
- tmp.innerHTML = '<audio x-webkit-airplay="deny"></audio>';
- var audioSilentMode = tmp.children.item(0);
- audioSilentMode.src = audioData;
- audioSilentMode.preload = "auto";
- audioSilentMode.type = "audio/mpeg";
- audioSilentMode.disableRemotePlayback = true; // play
- audioSilentMode.play(); // cleanup
- audioSilentMode.remove();
- tmp.remove();
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/util/style.js":
- /*!***************************!*\
- !*** ./src/util/style.js ***!
- \***************************/
- /***/ ((module, exports) => {
- "use strict";
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = style;
- /**
- * Apply a map of styles to an element
- *
- * @param {HTMLElement} el The element that the styles will be applied to
- * @param {Object} styles The map of propName: attribute, both are used as-is
- *
- * @return {HTMLElement} el
- */
- function style(el, styles) {
- Object.keys(styles).forEach(function (prop) {
- if (el.style[prop] !== styles[prop]) {
- el.style[prop] = styles[prop];
- }
- });
- return el;
- }
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/wavesurfer.js":
- /*!***************************!*\
- !*** ./src/wavesurfer.js ***!
- \***************************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
- var _drawer = _interopRequireDefault(__webpack_require__(/*! ./drawer.multicanvas */ "./src/drawer.multicanvas.js"));
- var _webaudio = _interopRequireDefault(__webpack_require__(/*! ./webaudio */ "./src/webaudio.js"));
- var _mediaelement = _interopRequireDefault(__webpack_require__(/*! ./mediaelement */ "./src/mediaelement.js"));
- var _peakcache = _interopRequireDefault(__webpack_require__(/*! ./peakcache */ "./src/peakcache.js"));
- var _mediaelementWebaudio = _interopRequireDefault(__webpack_require__(/*! ./mediaelement-webaudio */ "./src/mediaelement-webaudio.js"));
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- /*
- * This work is licensed under a BSD-3-Clause License.
- */
- /** @external {HTMLElement} https://developer.mozilla.org/en/docs/Web/API/HTMLElement */
- /** @external {OfflineAudioContext} https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext */
- /** @external {File} https://developer.mozilla.org/en-US/docs/Web/API/File */
- /** @external {Blob} https://developer.mozilla.org/en-US/docs/Web/API/Blob */
- /** @external {CanvasRenderingContext2D} https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D */
- /** @external {MediaStreamConstraints} https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints */
- /** @external {AudioNode} https://developer.mozilla.org/de/docs/Web/API/AudioNode */
- /**
- * @typedef {Object} WavesurferParams
- * @property {AudioContext} audioContext=null Use your own previously
- * initialized AudioContext or leave blank.
- * @property {number} audioRate=1 Speed at which to play audio. Lower number is
- * slower.
- * @property {ScriptProcessorNode} audioScriptProcessor=null Use your own previously
- * initialized ScriptProcessorNode or leave blank.
- * @property {boolean} autoCenter=true If a scrollbar is present, center the
- * waveform on current progress
- * @property {number} autoCenterRate=5 If autoCenter is active, rate at which the
- * waveform is centered
- * @property {boolean} autoCenterImmediately=false If autoCenter is active, immediately
- * center waveform on current progress
- * @property {string} backend='WebAudio' `'WebAudio'|'MediaElement'|'MediaElementWebAudio'` In most cases
- * you don't have to set this manually. MediaElement is a fallback for unsupported browsers.
- * MediaElementWebAudio allows to use WebAudio API also with big audio files, loading audio like with
- * MediaElement backend (HTML5 audio tag). You have to use the same methods of MediaElement backend for loading and
- * playback, giving also peaks, so the audio data are not decoded. In this way you can use WebAudio features, like filters,
- * also with audio with big duration. For example:
- * ` wavesurfer.load(url | HTMLMediaElement, peaks, preload, duration);
- * wavesurfer.play();
- * wavesurfer.setFilter(customFilter);
- * `
- * @property {string} backgroundColor=null Change background color of the
- * waveform container.
- * @property {number} barHeight=1 The height of the wave bars.
- * @property {number} barRadius=0 The radius of the wave bars. Makes bars rounded
- * @property {number} barGap=null The optional spacing between bars of the wave,
- * if not provided will be calculated in legacy format.
- * @property {number} barWidth=null Draw the waveform using bars.
- * @property {number} barMinHeight=null If specified, draw at least a bar of this height,
- * eliminating waveform gaps
- * @property {boolean} closeAudioContext=false Close and nullify all audio
- * contexts when the destroy method is called.
- * @property {!string|HTMLElement} container CSS selector or HTML element where
- * the waveform should be drawn. This is the only required parameter.
- * @property {string} cursorColor='#333' The fill color of the cursor indicating
- * the playhead position.
- * @property {number} cursorWidth=1 Measured in pixels.
- * @property {object} drawingContextAttributes={desynchronized: false} Drawing context
- * attributes.
- * @property {number} duration=null Optional audio length so pre-rendered peaks
- * can be display immediately for example.
- * @property {boolean} fillParent=true Whether to fill the entire container or
- * draw only according to `minPxPerSec`.
- * @property {boolean} forceDecode=false Force decoding of audio using web audio
- * when zooming to get a more detailed waveform.
- * @property {number} height=128 The height of the waveform. Measured in
- * pixels.
- * @property {boolean} hideScrollbar=false Whether to hide the horizontal
- * scrollbar when one would normally be shown.
- * @property {boolean} hideCursor=false Whether to hide the mouse cursor
- * when one would normally be shown by default.
- * @property {boolean} ignoreSilenceMode=false If true, ignores device silence mode
- * when using the `WebAudio` backend.
- * @property {boolean} interact=true Whether the mouse interaction will be
- * enabled at initialization. You can switch this parameter at any time later
- * on.
- * @property {boolean} loopSelection=true (Use with regions plugin) Enable
- * looping of selected regions
- * @property {number} maxCanvasWidth=4000 Maximum width of a single canvas in
- * pixels, excluding a small overlap (2 * `pixelRatio`, rounded up to the next
- * even integer). If the waveform is longer than this value, additional canvases
- * will be used to render the waveform, which is useful for very large waveforms
- * that may be too wide for browsers to draw on a single canvas.
- * @property {boolean} mediaControls=false (Use with backend `MediaElement` or `MediaElementWebAudio`)
- * this enables the native controls for the media element
- * @property {string} mediaType='audio' (Use with backend `MediaElement` or `MediaElementWebAudio`)
- * `'audio'|'video'` ('video' only for `MediaElement`)
- * @property {number} minPxPerSec=20 Minimum number of pixels per second of
- * audio.
- * @property {boolean} normalize=false If true, normalize by the maximum peak
- * instead of 1.0.
- * @property {boolean} partialRender=false Use the PeakCache to improve
- * rendering speed of large waveforms
- * @property {number} pixelRatio=window.devicePixelRatio The pixel ratio used to
- * calculate display
- * @property {PluginDefinition[]} plugins=[] An array of plugin definitions to
- * register during instantiation, they will be directly initialised unless they
- * are added with the `deferInit` property set to true.
- * @property {string} progressColor='#555' The fill color of the part of the
- * waveform behind the cursor. When `progressColor` and `waveColor` are the same
- * the progress wave is not rendered at all.
- * @property {boolean} removeMediaElementOnDestroy=true Set to false to keep the
- * media element in the DOM when the player is destroyed. This is useful when
- * reusing an existing media element via the `loadMediaElement` method.
- * @property {Object} renderer=MultiCanvas Can be used to inject a custom
- * renderer.
- * @property {boolean|number} responsive=false If set to `true` resize the
- * waveform, when the window is resized. This is debounced with a `100ms`
- * timeout by default. If this parameter is a number it represents that timeout.
- * @property {boolean} rtl=false If set to `true`, renders waveform from
- * right-to-left.
- * @property {boolean} scrollParent=false Whether to scroll the container with a
- * lengthy waveform. Otherwise the waveform is shrunk to the container width
- * (see fillParent).
- * @property {number} skipLength=2 Number of seconds to skip with the
- * skipForward() and skipBackward() methods.
- * @property {boolean} splitChannels=false Render with separate waveforms for
- * the channels of the audio
- * @property {SplitChannelOptions} splitChannelsOptions={} Options for splitChannel rendering
- * @property {boolean} vertical=false Render the waveform vertically instead of horizontally.
- * @property {string} waveColor='#999' The fill color of the waveform after the
- * cursor.
- * @property {object} xhr={} XHR options. For example:
- * `let xhr = {
- * cache: 'default',
- * mode: 'cors',
- * method: 'GET',
- * credentials: 'same-origin',
- * redirect: 'follow',
- * referrer: 'client',
- * requestHeaders: [
- * {
- * key: 'Authorization',
- * value: 'my-token'
- * }
- * ]
- * };`
- */
- /**
- * @typedef {Object} PluginDefinition
- * @desc The Object used to describe a plugin
- * @example wavesurfer.addPlugin(pluginDefinition);
- * @property {string} name The name of the plugin, the plugin instance will be
- * added as a property to the wavesurfer instance under this name
- * @property {?Object} staticProps The properties that should be added to the
- * wavesurfer instance as static properties
- * @property {?boolean} deferInit Don't initialise plugin
- * automatically
- * @property {Object} params={} The plugin parameters, they are the first parameter
- * passed to the plugin class constructor function
- * @property {PluginClass} instance The plugin instance factory, is called with
- * the dependency specified in extends. Returns the plugin class.
- */
- /**
- * @typedef {Object} SplitChannelOptions
- * @desc parameters applied when splitChannels option is true
- * @property {boolean} overlay=false determines whether channels are rendered on top of each other or on separate tracks
- * @property {object} channelColors={} object describing color for each channel. Example:
- * {
- * 0: {
- * progressColor: 'green',
- * waveColor: 'pink'
- * },
- * 1: {
- * progressColor: 'orange',
- * waveColor: 'purple'
- * }
- * }
- * @property {number[]} filterChannels=[] indexes of channels to be hidden from rendering
- * @property {boolean} relativeNormalization=false determines whether
- * normalization is done per channel or maintains proportionality between
- * channels. Only applied when normalize and splitChannels are both true.
- * @since 4.3.0
- */
- /**
- * @interface PluginClass
- *
- * @desc This is the interface which is implemented by all plugin classes. Note
- * that this only turns into an observer after being passed through
- * `wavesurfer.addPlugin`.
- *
- * @extends {Observer}
- */
- var PluginClass = /*#__PURE__*/function () {
- /**
- * Construct the plugin
- *
- * @param {Object} params={} The plugin params (specific to the plugin)
- * @param {Object} ws The wavesurfer instance
- */
- function PluginClass(params, ws) {
- _classCallCheck(this, PluginClass);
- }
- /**
- * Initialise the plugin
- *
- * Start doing something. This is called by
- * `wavesurfer.initPlugin(pluginName)`
- */
- _createClass(PluginClass, [{
- key: "create",
- value:
- /**
- * Plugin definition factory
- *
- * This function must be used to create a plugin definition which can be
- * used by wavesurfer to correctly instantiate the plugin.
- *
- * It returns a `PluginDefinition` object representing the plugin.
- *
- * @param {Object} params={} The plugin params (specific to the plugin)
- */
- function create(params) {}
- }, {
- key: "init",
- value: function init() {}
- /**
- * Destroy the plugin instance
- *
- * Stop doing something. This is called by
- * `wavesurfer.destroyPlugin(pluginName)`
- */
- }, {
- key: "destroy",
- value: function destroy() {}
- }]);
- return PluginClass;
- }();
- /**
- * WaveSurfer core library class
- *
- * @extends {Observer}
- * @example
- * const params = {
- * container: '#waveform',
- * waveColor: 'violet',
- * progressColor: 'purple'
- * };
- *
- * // initialise like this
- * const wavesurfer = WaveSurfer.create(params);
- *
- * // or like this ...
- * const wavesurfer = new WaveSurfer(params);
- * wavesurfer.init();
- *
- * // load audio file
- * wavesurfer.load('example/media/demo.wav');
- */
- var WaveSurfer = /*#__PURE__*/function (_util$Observer) {
- _inherits(WaveSurfer, _util$Observer);
- var _super = _createSuper(WaveSurfer);
- /**
- * Initialise wavesurfer instance
- *
- * @param {WavesurferParams} params Instantiation options for wavesurfer
- * @example
- * const wavesurfer = new WaveSurfer(params);
- * @returns {this} Wavesurfer instance
- */
- function WaveSurfer(params) {
- var _this;
- _classCallCheck(this, WaveSurfer);
- _this = _super.call(this);
- /**
- * Extract relevant parameters (or defaults)
- * @private
- */
- _defineProperty(_assertThisInitialized(_this), "defaultParams", {
- audioContext: null,
- audioScriptProcessor: null,
- audioRate: 1,
- autoCenter: true,
- autoCenterRate: 5,
- autoCenterImmediately: false,
- backend: 'WebAudio',
- backgroundColor: null,
- barHeight: 1,
- barRadius: 0,
- barGap: null,
- barMinHeight: null,
- container: null,
- cursorColor: '#333',
- cursorWidth: 1,
- dragSelection: true,
- drawingContextAttributes: {
- // Boolean that hints the user agent to reduce the latency
- // by desynchronizing the canvas paint cycle from the event
- // loop
- desynchronized: false
- },
- duration: null,
- fillParent: true,
- forceDecode: false,
- height: 128,
- hideScrollbar: false,
- hideCursor: false,
- ignoreSilenceMode: false,
- interact: true,
- loopSelection: true,
- maxCanvasWidth: 4000,
- mediaContainer: null,
- mediaControls: false,
- mediaType: 'audio',
- minPxPerSec: 20,
- normalize: false,
- partialRender: false,
- pixelRatio: window.devicePixelRatio || screen.deviceXDPI / screen.logicalXDPI,
- plugins: [],
- progressColor: '#555',
- removeMediaElementOnDestroy: true,
- renderer: _drawer.default,
- responsive: false,
- rtl: false,
- scrollParent: false,
- skipLength: 2,
- splitChannels: false,
- splitChannelsOptions: {
- overlay: false,
- channelColors: {},
- filterChannels: [],
- relativeNormalization: false
- },
- vertical: false,
- waveColor: '#999',
- xhr: {}
- });
- _defineProperty(_assertThisInitialized(_this), "backends", {
- MediaElement: _mediaelement.default,
- WebAudio: _webaudio.default,
- MediaElementWebAudio: _mediaelementWebaudio.default
- });
- _defineProperty(_assertThisInitialized(_this), "util", util);
- _this.params = Object.assign({}, _this.defaultParams, params);
- _this.params.splitChannelsOptions = Object.assign({}, _this.defaultParams.splitChannelsOptions, params.splitChannelsOptions);
- /** @private */
- _this.container = 'string' == typeof params.container ? document.querySelector(_this.params.container) : _this.params.container;
- if (!_this.container) {
- throw new Error('Container element not found');
- }
- if (_this.params.mediaContainer == null) {
- /** @private */
- _this.mediaContainer = _this.container;
- } else if (typeof _this.params.mediaContainer == 'string') {
- /** @private */
- _this.mediaContainer = document.querySelector(_this.params.mediaContainer);
- } else {
- /** @private */
- _this.mediaContainer = _this.params.mediaContainer;
- }
- if (!_this.mediaContainer) {
- throw new Error('Media Container element not found');
- }
- if (_this.params.maxCanvasWidth <= 1) {
- throw new Error('maxCanvasWidth must be greater than 1');
- } else if (_this.params.maxCanvasWidth % 2 == 1) {
- throw new Error('maxCanvasWidth must be an even number');
- }
- if (_this.params.rtl === true) {
- if (_this.params.vertical === true) {
- util.style(_this.container, {
- transform: 'rotateX(180deg)'
- });
- } else {
- util.style(_this.container, {
- transform: 'rotateY(180deg)'
- });
- }
- }
- if (_this.params.backgroundColor) {
- _this.setBackgroundColor(_this.params.backgroundColor);
- }
- /**
- * @private Used to save the current volume when muting so we can
- * restore once unmuted
- * @type {number}
- */
- _this.savedVolume = 0;
- /**
- * @private The current muted state
- * @type {boolean}
- */
- _this.isMuted = false;
- /**
- * @private Will hold a list of event descriptors that need to be
- * canceled on subsequent loads of audio
- * @type {Object[]}
- */
- _this.tmpEvents = [];
- /**
- * @private Holds any running audio downloads
- * @type {Observer}
- */
- _this.currentRequest = null;
- /** @private */
- _this.arraybuffer = null;
- /** @private */
- _this.drawer = null;
- /** @private */
- _this.backend = null;
- /** @private */
- _this.peakCache = null; // cache constructor objects
- if (typeof _this.params.renderer !== 'function') {
- throw new Error('Renderer parameter is invalid');
- }
- /**
- * @private The uninitialised Drawer class
- */
- _this.Drawer = _this.params.renderer;
- /**
- * @private The uninitialised Backend class
- */
- // Back compat
- if (_this.params.backend == 'AudioElement') {
- _this.params.backend = 'MediaElement';
- }
- if ((_this.params.backend == 'WebAudio' || _this.params.backend === 'MediaElementWebAudio') && !_webaudio.default.prototype.supportsWebAudio.call(null)) {
- _this.params.backend = 'MediaElement';
- }
- _this.Backend = _this.backends[_this.params.backend];
- /**
- * @private map of plugin names that are currently initialised
- */
- _this.initialisedPluginList = {};
- /** @private */
- _this.isDestroyed = false;
- /**
- * Get the current ready status.
- *
- * @example const isReady = wavesurfer.isReady;
- * @return {boolean}
- */
- _this.isReady = false; // responsive debounced event listener. If this.params.responsive is not
- // set, this is never called. Use 100ms or this.params.responsive as
- // timeout for the debounce function.
- var prevWidth = 0;
- _this._onResize = util.debounce(function () {
- if (prevWidth != _this.drawer.wrapper.clientWidth && !_this.params.scrollParent) {
- prevWidth = _this.drawer.wrapper.clientWidth;
- if (prevWidth) {
- // redraw only if waveform container is rendered and has a width
- _this.drawer.fireEvent('redraw');
- }
- }
- }, typeof _this.params.responsive === 'number' ? _this.params.responsive : 100);
- return _possibleConstructorReturn(_this, _assertThisInitialized(_this));
- }
- /**
- * Initialise the wave
- *
- * @example
- * var wavesurfer = new WaveSurfer(params);
- * wavesurfer.init();
- * @return {this} The wavesurfer instance
- */
- _createClass(WaveSurfer, [{
- key: "init",
- value: function init() {
- this.registerPlugins(this.params.plugins);
- this.createDrawer();
- this.createBackend();
- this.createPeakCache();
- return this;
- }
- /**
- * Add and initialise array of plugins (if `plugin.deferInit` is falsey),
- * this function is called in the init function of wavesurfer
- *
- * @param {PluginDefinition[]} plugins An array of plugin definitions
- * @emits {WaveSurfer#plugins-registered} Called with the array of plugin definitions
- * @return {this} The wavesurfer instance
- */
- }, {
- key: "registerPlugins",
- value: function registerPlugins(plugins) {
- var _this2 = this;
- // first instantiate all the plugins
- plugins.forEach(function (plugin) {
- return _this2.addPlugin(plugin);
- }); // now run the init functions
- plugins.forEach(function (plugin) {
- // call init function of the plugin if deferInit is falsey
- // in that case you would manually use initPlugins()
- if (!plugin.deferInit) {
- _this2.initPlugin(plugin.name);
- }
- });
- this.fireEvent('plugins-registered', plugins);
- return this;
- }
- /**
- * Get a map of plugin names that are currently initialised
- *
- * @example wavesurfer.getPlugins();
- * @return {Object} Object with plugin names
- */
- }, {
- key: "getActivePlugins",
- value: function getActivePlugins() {
- return this.initialisedPluginList;
- }
- /**
- * Add a plugin object to wavesurfer
- *
- * @param {PluginDefinition} plugin A plugin definition
- * @emits {WaveSurfer#plugin-added} Called with the name of the plugin that was added
- * @example wavesurfer.addPlugin(WaveSurfer.minimap());
- * @return {this} The wavesurfer instance
- */
- }, {
- key: "addPlugin",
- value: function addPlugin(plugin) {
- var _this3 = this;
- if (!plugin.name) {
- throw new Error('Plugin does not have a name!');
- }
- if (!plugin.instance) {
- throw new Error("Plugin ".concat(plugin.name, " does not have an instance property!"));
- } // staticProps properties are applied to wavesurfer instance
- if (plugin.staticProps) {
- Object.keys(plugin.staticProps).forEach(function (pluginStaticProp) {
- /**
- * Properties defined in a plugin definition's `staticProps` property are added as
- * staticProps properties of the WaveSurfer instance
- */
- _this3[pluginStaticProp] = plugin.staticProps[pluginStaticProp];
- });
- }
- var Instance = plugin.instance; // turn the plugin instance into an observer
- var observerPrototypeKeys = Object.getOwnPropertyNames(util.Observer.prototype);
- observerPrototypeKeys.forEach(function (key) {
- Instance.prototype[key] = util.Observer.prototype[key];
- });
- /**
- * Instantiated plugin classes are added as a property of the wavesurfer
- * instance
- * @type {Object}
- */
- this[plugin.name] = new Instance(plugin.params || {}, this);
- this.fireEvent('plugin-added', plugin.name);
- return this;
- }
- /**
- * Initialise a plugin
- *
- * @param {string} name A plugin name
- * @emits WaveSurfer#plugin-initialised
- * @example wavesurfer.initPlugin('minimap');
- * @return {this} The wavesurfer instance
- */
- }, {
- key: "initPlugin",
- value: function initPlugin(name) {
- if (!this[name]) {
- throw new Error("Plugin ".concat(name, " has not been added yet!"));
- }
- if (this.initialisedPluginList[name]) {
- // destroy any already initialised plugins
- this.destroyPlugin(name);
- }
- this[name].init();
- this.initialisedPluginList[name] = true;
- this.fireEvent('plugin-initialised', name);
- return this;
- }
- /**
- * Destroy a plugin
- *
- * @param {string} name A plugin name
- * @emits WaveSurfer#plugin-destroyed
- * @example wavesurfer.destroyPlugin('minimap');
- * @returns {this} The wavesurfer instance
- */
- }, {
- key: "destroyPlugin",
- value: function destroyPlugin(name) {
- if (!this[name]) {
- throw new Error("Plugin ".concat(name, " has not been added yet and cannot be destroyed!"));
- }
- if (!this.initialisedPluginList[name]) {
- throw new Error("Plugin ".concat(name, " is not active and cannot be destroyed!"));
- }
- if (typeof this[name].destroy !== 'function') {
- throw new Error("Plugin ".concat(name, " does not have a destroy function!"));
- }
- this[name].destroy();
- delete this.initialisedPluginList[name];
- this.fireEvent('plugin-destroyed', name);
- return this;
- }
- /**
- * Destroy all initialised plugins. Convenience function to use when
- * wavesurfer is removed
- *
- * @private
- */
- }, {
- key: "destroyAllPlugins",
- value: function destroyAllPlugins() {
- var _this4 = this;
- Object.keys(this.initialisedPluginList).forEach(function (name) {
- return _this4.destroyPlugin(name);
- });
- }
- /**
- * Create the drawer and draw the waveform
- *
- * @private
- * @emits WaveSurfer#drawer-created
- */
- }, {
- key: "createDrawer",
- value: function createDrawer() {
- var _this5 = this;
- this.drawer = new this.Drawer(this.container, this.params);
- this.drawer.init();
- this.fireEvent('drawer-created', this.drawer);
- if (this.params.responsive !== false) {
- window.addEventListener('resize', this._onResize, true);
- window.addEventListener('orientationchange', this._onResize, true);
- }
- this.drawer.on('redraw', function () {
- _this5.drawBuffer();
- _this5.drawer.progress(_this5.backend.getPlayedPercents());
- }); // Click-to-seek
- this.drawer.on('click', function (e, progress) {
- setTimeout(function () {
- return _this5.seekTo(progress);
- }, 0);
- }); // Relay the scroll event from the drawer
- this.drawer.on('scroll', function (e) {
- if (_this5.params.partialRender) {
- _this5.drawBuffer();
- }
- _this5.fireEvent('scroll', e);
- });
- }
- /**
- * Create the backend
- *
- * @private
- * @emits WaveSurfer#backend-created
- */
- }, {
- key: "createBackend",
- value: function createBackend() {
- var _this6 = this;
- if (this.backend) {
- this.backend.destroy();
- }
- this.backend = new this.Backend(this.params);
- this.backend.init();
- this.fireEvent('backend-created', this.backend);
- this.backend.on('finish', function () {
- _this6.drawer.progress(_this6.backend.getPlayedPercents());
- _this6.fireEvent('finish');
- });
- this.backend.on('play', function () {
- return _this6.fireEvent('play');
- });
- this.backend.on('pause', function () {
- return _this6.fireEvent('pause');
- });
- this.backend.on('audioprocess', function (time) {
- _this6.drawer.progress(_this6.backend.getPlayedPercents());
- _this6.fireEvent('audioprocess', time);
- }); // only needed for MediaElement and MediaElementWebAudio backend
- if (this.params.backend === 'MediaElement' || this.params.backend === 'MediaElementWebAudio') {
- this.backend.on('seek', function () {
- _this6.drawer.progress(_this6.backend.getPlayedPercents());
- });
- this.backend.on('volume', function () {
- var newVolume = _this6.getVolume();
- _this6.fireEvent('volume', newVolume);
- if (_this6.backend.isMuted !== _this6.isMuted) {
- _this6.isMuted = _this6.backend.isMuted;
- _this6.fireEvent('mute', _this6.isMuted);
- }
- });
- }
- }
- /**
- * Create the peak cache
- *
- * @private
- */
- }, {
- key: "createPeakCache",
- value: function createPeakCache() {
- if (this.params.partialRender) {
- this.peakCache = new _peakcache.default();
- }
- }
- /**
- * Get the duration of the audio clip
- *
- * @example const duration = wavesurfer.getDuration();
- * @return {number} Duration in seconds
- */
- }, {
- key: "getDuration",
- value: function getDuration() {
- return this.backend.getDuration();
- }
- /**
- * Get the current playback position
- *
- * @example const currentTime = wavesurfer.getCurrentTime();
- * @return {number} Playback position in seconds
- */
- }, {
- key: "getCurrentTime",
- value: function getCurrentTime() {
- return this.backend.getCurrentTime();
- }
- /**
- * Set the current play time in seconds.
- *
- * @param {number} seconds A positive number in seconds. E.g. 10 means 10
- * seconds, 60 means 1 minute
- */
- }, {
- key: "setCurrentTime",
- value: function setCurrentTime(seconds) {
- if (seconds >= this.getDuration()) {
- this.seekTo(1);
- } else {
- this.seekTo(seconds / this.getDuration());
- }
- }
- /**
- * Starts playback from the current position. Optional start and end
- * measured in seconds can be used to set the range of audio to play.
- *
- * @param {?number} start Position to start at
- * @param {?number} end Position to end at
- * @emits WaveSurfer#interaction
- * @return {Promise} Result of the backend play method
- * @example
- * // play from second 1 to 5
- * wavesurfer.play(1, 5);
- */
- }, {
- key: "play",
- value: function play(start, end) {
- var _this7 = this;
- if (this.params.ignoreSilenceMode) {
- // ignores device hardware silence mode
- util.ignoreSilenceMode();
- }
- this.fireEvent('interaction', function () {
- return _this7.play(start, end);
- });
- return this.backend.play(start, end);
- }
- /**
- * Set a point in seconds for playback to stop at.
- *
- * @param {number} position Position (in seconds) to stop at
- * @version 3.3.0
- */
- }, {
- key: "setPlayEnd",
- value: function setPlayEnd(position) {
- this.backend.setPlayEnd(position);
- }
- /**
- * Stops and pauses playback
- *
- * @example wavesurfer.pause();
- * @return {Promise} Result of the backend pause method
- */
- }, {
- key: "pause",
- value: function pause() {
- if (!this.backend.isPaused()) {
- return this.backend.pause();
- }
- }
- /**
- * Toggle playback
- *
- * @example wavesurfer.playPause();
- * @return {Promise} Result of the backend play or pause method
- */
- }, {
- key: "playPause",
- value: function playPause() {
- return this.backend.isPaused() ? this.play() : this.pause();
- }
- /**
- * Get the current playback state
- *
- * @example const isPlaying = wavesurfer.isPlaying();
- * @return {boolean} False if paused, true if playing
- */
- }, {
- key: "isPlaying",
- value: function isPlaying() {
- return !this.backend.isPaused();
- }
- /**
- * Skip backward
- *
- * @param {?number} seconds Amount to skip back, if not specified `skipLength`
- * is used
- * @example wavesurfer.skipBackward();
- */
- }, {
- key: "skipBackward",
- value: function skipBackward(seconds) {
- this.skip(-seconds || -this.params.skipLength);
- }
- /**
- * Skip forward
- *
- * @param {?number} seconds Amount to skip back, if not specified `skipLength`
- * is used
- * @example wavesurfer.skipForward();
- */
- }, {
- key: "skipForward",
- value: function skipForward(seconds) {
- this.skip(seconds || this.params.skipLength);
- }
- /**
- * Skip a number of seconds from the current position (use a negative value
- * to go backwards).
- *
- * @param {number} offset Amount to skip back or forwards
- * @example
- * // go back 2 seconds
- * wavesurfer.skip(-2);
- */
- }, {
- key: "skip",
- value: function skip(offset) {
- var duration = this.getDuration() || 1;
- var position = this.getCurrentTime() || 0;
- position = Math.max(0, Math.min(duration, position + (offset || 0)));
- this.seekAndCenter(position / duration);
- }
- /**
- * Seeks to a position and centers the view
- *
- * @param {number} progress Between 0 (=beginning) and 1 (=end)
- * @example
- * // seek and go to the middle of the audio
- * wavesurfer.seekTo(0.5);
- */
- }, {
- key: "seekAndCenter",
- value: function seekAndCenter(progress) {
- this.seekTo(progress);
- this.drawer.recenter(progress);
- }
- /**
- * Seeks to a position
- *
- * @param {number} progress Between 0 (=beginning) and 1 (=end)
- * @emits WaveSurfer#interaction
- * @emits WaveSurfer#seek
- * @example
- * // seek to the middle of the audio
- * wavesurfer.seekTo(0.5);
- */
- }, {
- key: "seekTo",
- value: function seekTo(progress) {
- var _this8 = this;
- // return an error if progress is not a number between 0 and 1
- if (typeof progress !== 'number' || !isFinite(progress) || progress < 0 || progress > 1) {
- throw new Error('Error calling wavesurfer.seekTo, parameter must be a number between 0 and 1!');
- }
- this.fireEvent('interaction', function () {
- return _this8.seekTo(progress);
- });
- var isWebAudioBackend = this.params.backend === 'WebAudio';
- var paused = this.backend.isPaused();
- if (isWebAudioBackend && !paused) {
- this.backend.pause();
- } // avoid small scrolls while paused seeking
- var oldScrollParent = this.params.scrollParent;
- this.params.scrollParent = false;
- this.backend.seekTo(progress * this.getDuration());
- this.drawer.progress(progress);
- if (isWebAudioBackend && !paused) {
- this.backend.play();
- }
- this.params.scrollParent = oldScrollParent;
- this.fireEvent('seek', progress);
- }
- /**
- * Stops and goes to the beginning.
- *
- * @example wavesurfer.stop();
- */
- }, {
- key: "stop",
- value: function stop() {
- this.pause();
- this.seekTo(0);
- this.drawer.progress(0);
- }
- /**
- * Sets the ID of the audio device to use for output and returns a Promise.
- *
- * @param {string} deviceId String value representing underlying output
- * device
- * @returns {Promise} `Promise` that resolves to `undefined` when there are
- * no errors detected.
- */
- }, {
- key: "setSinkId",
- value: function setSinkId(deviceId) {
- return this.backend.setSinkId(deviceId);
- }
- /**
- * Set the playback volume.
- *
- * @param {number} newVolume A value between 0 and 1, 0 being no
- * volume and 1 being full volume.
- * @emits WaveSurfer#volume
- */
- }, {
- key: "setVolume",
- value: function setVolume(newVolume) {
- this.backend.setVolume(newVolume);
- this.fireEvent('volume', newVolume);
- }
- /**
- * Get the playback volume.
- *
- * @return {number} A value between 0 and 1, 0 being no
- * volume and 1 being full volume.
- */
- }, {
- key: "getVolume",
- value: function getVolume() {
- return this.backend.getVolume();
- }
- /**
- * Set the playback rate.
- *
- * @param {number} rate A positive number. E.g. 0.5 means half the normal
- * speed, 2 means double speed and so on.
- * @example wavesurfer.setPlaybackRate(2);
- */
- }, {
- key: "setPlaybackRate",
- value: function setPlaybackRate(rate) {
- this.backend.setPlaybackRate(rate);
- }
- /**
- * Get the playback rate.
- *
- * @return {number} The current playback rate.
- */
- }, {
- key: "getPlaybackRate",
- value: function getPlaybackRate() {
- return this.backend.getPlaybackRate();
- }
- /**
- * Toggle the volume on and off. If not currently muted it will save the
- * current volume value and turn the volume off. If currently muted then it
- * will restore the volume to the saved value, and then rest the saved
- * value.
- *
- * @example wavesurfer.toggleMute();
- */
- }, {
- key: "toggleMute",
- value: function toggleMute() {
- this.setMute(!this.isMuted);
- }
- /**
- * Enable or disable muted audio
- *
- * @param {boolean} mute Specify `true` to mute audio.
- * @emits WaveSurfer#volume
- * @emits WaveSurfer#mute
- * @example
- * // unmute
- * wavesurfer.setMute(false);
- * console.log(wavesurfer.getMute()) // logs false
- */
- }, {
- key: "setMute",
- value: function setMute(mute) {
- // ignore all muting requests if the audio is already in that state
- if (mute === this.isMuted) {
- this.fireEvent('mute', this.isMuted);
- return;
- }
- if (this.backend.setMute) {
- // Backends such as the MediaElement backend have their own handling
- // of mute, let them handle it.
- this.backend.setMute(mute);
- this.isMuted = mute;
- } else {
- if (mute) {
- // If currently not muted then save current volume,
- // turn off the volume and update the mute properties
- this.savedVolume = this.backend.getVolume();
- this.backend.setVolume(0);
- this.isMuted = true;
- this.fireEvent('volume', 0);
- } else {
- // If currently muted then restore to the saved volume
- // and update the mute properties
- this.backend.setVolume(this.savedVolume);
- this.isMuted = false;
- this.fireEvent('volume', this.savedVolume);
- }
- }
- this.fireEvent('mute', this.isMuted);
- }
- /**
- * Get the current mute status.
- *
- * @example const isMuted = wavesurfer.getMute();
- * @return {boolean} Current mute status
- */
- }, {
- key: "getMute",
- value: function getMute() {
- return this.isMuted;
- }
- /**
- * Get the list of current set filters as an array.
- *
- * Filters must be set with setFilters method first
- *
- * @return {array} List of enabled filters
- */
- }, {
- key: "getFilters",
- value: function getFilters() {
- return this.backend.filters || [];
- }
- /**
- * Toggles `scrollParent` and redraws
- *
- * @example wavesurfer.toggleScroll();
- */
- }, {
- key: "toggleScroll",
- value: function toggleScroll() {
- this.params.scrollParent = !this.params.scrollParent;
- this.drawBuffer();
- }
- /**
- * Toggle mouse interaction
- *
- * @example wavesurfer.toggleInteraction();
- */
- }, {
- key: "toggleInteraction",
- value: function toggleInteraction() {
- this.params.interact = !this.params.interact;
- }
- /**
- * Get the fill color of the waveform after the cursor.
- *
- * @param {?number} channelIdx Optional index of the channel to get its wave color if splitChannels is true
- * @return {string|object} A CSS color string, or an array of CSS color strings.
- */
- }, {
- key: "getWaveColor",
- value: function getWaveColor() {
- var channelIdx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
- if (this.params.splitChannelsOptions.channelColors[channelIdx]) {
- return this.params.splitChannelsOptions.channelColors[channelIdx].waveColor;
- }
- return this.params.waveColor;
- }
- /**
- * Set the fill color of the waveform after the cursor.
- *
- * @param {string|object} color A CSS color string, or an array of CSS color strings.
- * @param {?number} channelIdx Optional index of the channel to set its wave color if splitChannels is true
- * @example wavesurfer.setWaveColor('#ddd');
- */
- }, {
- key: "setWaveColor",
- value: function setWaveColor(color) {
- var channelIdx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
- if (this.params.splitChannelsOptions.channelColors[channelIdx]) {
- this.params.splitChannelsOptions.channelColors[channelIdx].waveColor = color;
- } else {
- this.params.waveColor = color;
- }
- this.drawBuffer();
- }
- /**
- * Get the fill color of the waveform behind the cursor.
- *
- * @param {?number} channelIdx Optional index of the channel to get its progress color if splitChannels is true
- * @return {string|object} A CSS color string, or an array of CSS color strings.
- */
- }, {
- key: "getProgressColor",
- value: function getProgressColor() {
- var channelIdx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
- if (this.params.splitChannelsOptions.channelColors[channelIdx]) {
- return this.params.splitChannelsOptions.channelColors[channelIdx].progressColor;
- }
- return this.params.progressColor;
- }
- /**
- * Set the fill color of the waveform behind the cursor.
- *
- * @param {string|object} color A CSS color string, or an array of CSS color strings.
- * @param {?number} channelIdx Optional index of the channel to set its progress color if splitChannels is true
- * @example wavesurfer.setProgressColor('#400');
- */
- }, {
- key: "setProgressColor",
- value: function setProgressColor(color, channelIdx) {
- if (this.params.splitChannelsOptions.channelColors[channelIdx]) {
- this.params.splitChannelsOptions.channelColors[channelIdx].progressColor = color;
- } else {
- this.params.progressColor = color;
- }
- this.drawBuffer();
- }
- /**
- * Get the background color of the waveform container.
- *
- * @return {string} A CSS color string.
- */
- }, {
- key: "getBackgroundColor",
- value: function getBackgroundColor() {
- return this.params.backgroundColor;
- }
- /**
- * Set the background color of the waveform container.
- *
- * @param {string} color A CSS color string.
- * @example wavesurfer.setBackgroundColor('#FF00FF');
- */
- }, {
- key: "setBackgroundColor",
- value: function setBackgroundColor(color) {
- this.params.backgroundColor = color;
- util.style(this.container, {
- background: this.params.backgroundColor
- });
- }
- /**
- * Get the fill color of the cursor indicating the playhead
- * position.
- *
- * @return {string} A CSS color string.
- */
- }, {
- key: "getCursorColor",
- value: function getCursorColor() {
- return this.params.cursorColor;
- }
- /**
- * Set the fill color of the cursor indicating the playhead
- * position.
- *
- * @param {string} color A CSS color string.
- * @example wavesurfer.setCursorColor('#222');
- */
- }, {
- key: "setCursorColor",
- value: function setCursorColor(color) {
- this.params.cursorColor = color;
- this.drawer.updateCursor();
- }
- /**
- * Get the height of the waveform.
- *
- * @return {number} Height measured in pixels.
- */
- }, {
- key: "getHeight",
- value: function getHeight() {
- return this.params.height;
- }
- /**
- * Set the height of the waveform.
- *
- * @param {number} height Height measured in pixels.
- * @example wavesurfer.setHeight(200);
- */
- }, {
- key: "setHeight",
- value: function setHeight(height) {
- this.params.height = height;
- this.drawer.setHeight(height * this.params.pixelRatio);
- this.drawBuffer();
- }
- /**
- * Hide channels from being drawn on the waveform if splitting channels.
- *
- * For example, if we want to draw only the peaks for the right stereo channel:
- *
- * const wavesurfer = new WaveSurfer.create({...splitChannels: true});
- * wavesurfer.load('stereo_audio.mp3');
- *
- * wavesurfer.setFilteredChannel([0]); <-- hide left channel peaks.
- *
- * @param {array} channelIndices Channels to be filtered out from drawing.
- * @version 4.0.0
- */
- }, {
- key: "setFilteredChannels",
- value: function setFilteredChannels(channelIndices) {
- this.params.splitChannelsOptions.filterChannels = channelIndices;
- this.drawBuffer();
- }
- /**
- * Get the correct peaks for current wave view-port and render wave
- *
- * @private
- * @emits WaveSurfer#redraw
- */
- }, {
- key: "drawBuffer",
- value: function drawBuffer() {
- var nominalWidth = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio);
- var parentWidth = this.drawer.getWidth();
- var width = nominalWidth; // always start at 0 after zooming for scrolling : issue redraw left part
- var start = 0;
- var end = Math.max(start + parentWidth, width); // Fill container
- if (this.params.fillParent && (!this.params.scrollParent || nominalWidth < parentWidth)) {
- width = parentWidth;
- start = 0;
- end = width;
- }
- var peaks;
- if (this.params.partialRender) {
- var newRanges = this.peakCache.addRangeToPeakCache(width, start, end);
- var i;
- for (i = 0; i < newRanges.length; i++) {
- peaks = this.backend.getPeaks(width, newRanges[i][0], newRanges[i][1]);
- this.drawer.drawPeaks(peaks, width, newRanges[i][0], newRanges[i][1]);
- }
- } else {
- peaks = this.backend.getPeaks(width, start, end);
- this.drawer.drawPeaks(peaks, width, start, end);
- }
- this.fireEvent('redraw', peaks, width);
- }
- /**
- * Horizontally zooms the waveform in and out. It also changes the parameter
- * `minPxPerSec` and enables the `scrollParent` option. Calling the function
- * with a falsey parameter will reset the zoom state.
- *
- * @param {?number} pxPerSec Number of horizontal pixels per second of
- * audio, if none is set the waveform returns to unzoomed state
- * @emits WaveSurfer#zoom
- * @example wavesurfer.zoom(20);
- */
- }, {
- key: "zoom",
- value: function zoom(pxPerSec) {
- if (!pxPerSec) {
- this.params.minPxPerSec = this.defaultParams.minPxPerSec;
- this.params.scrollParent = false;
- } else {
- this.params.minPxPerSec = pxPerSec;
- this.params.scrollParent = true;
- }
- this.drawBuffer();
- this.drawer.progress(this.backend.getPlayedPercents());
- this.drawer.recenter(this.getCurrentTime() / this.getDuration());
- this.fireEvent('zoom', pxPerSec);
- }
- /**
- * Decode buffer and load
- *
- * @private
- * @param {ArrayBuffer} arraybuffer Buffer to process
- */
- }, {
- key: "loadArrayBuffer",
- value: function loadArrayBuffer(arraybuffer) {
- var _this9 = this;
- this.decodeArrayBuffer(arraybuffer, function (data) {
- if (!_this9.isDestroyed) {
- _this9.loadDecodedBuffer(data);
- }
- });
- }
- /**
- * Directly load an externally decoded AudioBuffer
- *
- * @private
- * @param {AudioBuffer} buffer Buffer to process
- * @emits WaveSurfer#ready
- */
- }, {
- key: "loadDecodedBuffer",
- value: function loadDecodedBuffer(buffer) {
- this.backend.load(buffer);
- this.drawBuffer();
- this.isReady = true;
- this.fireEvent('ready');
- }
- /**
- * Loads audio data from a Blob or File object
- *
- * @param {Blob|File} blob Audio data
- * @example
- */
- }, {
- key: "loadBlob",
- value: function loadBlob(blob) {
- var _this10 = this;
- // Create file reader
- var reader = new FileReader();
- reader.addEventListener('progress', function (e) {
- return _this10.onProgress(e);
- });
- reader.addEventListener('load', function (e) {
- return _this10.loadArrayBuffer(e.target.result);
- });
- reader.addEventListener('error', function () {
- return _this10.fireEvent('error', 'Error reading file');
- });
- reader.readAsArrayBuffer(blob);
- this.empty();
- }
- /**
- * Loads audio and re-renders the waveform.
- *
- * @param {string|HTMLMediaElement} url The url of the audio file or the
- * audio element with the audio
- * @param {number[]|Number.<Array[]>} peaks Wavesurfer does not have to decode
- * the audio to render the waveform if this is specified
- * @param {?string} preload (Use with backend `MediaElement` and `MediaElementWebAudio`)
- * `'none'|'metadata'|'auto'` Preload attribute for the media element
- * @param {?number} duration The duration of the audio. This is used to
- * render the peaks data in the correct size for the audio duration (as
- * befits the current `minPxPerSec` and zoom value) without having to decode
- * the audio.
- * @returns {void}
- * @throws Will throw an error if the `url` argument is empty.
- * @example
- * // uses fetch or media element to load file (depending on backend)
- * wavesurfer.load('http://example.com/demo.wav');
- *
- * // setting preload attribute with media element backend and supplying
- * // peaks
- * wavesurfer.load(
- * 'http://example.com/demo.wav',
- * [0.0218, 0.0183, 0.0165, 0.0198, 0.2137, 0.2888],
- * true
- * );
- */
- }, {
- key: "load",
- value: function load(url, peaks, preload, duration) {
- if (!url) {
- throw new Error('url parameter cannot be empty');
- }
- this.empty();
- if (preload) {
- // check whether the preload attribute will be usable and if not log
- // a warning listing the reasons why not and nullify the variable
- var preloadIgnoreReasons = {
- "Preload is not 'auto', 'none' or 'metadata'": ['auto', 'metadata', 'none'].indexOf(preload) === -1,
- 'Peaks are not provided': !peaks,
- "Backend is not of type 'MediaElement' or 'MediaElementWebAudio'": ['MediaElement', 'MediaElementWebAudio'].indexOf(this.params.backend) === -1,
- 'Url is not of type string': typeof url !== 'string'
- };
- var activeReasons = Object.keys(preloadIgnoreReasons).filter(function (reason) {
- return preloadIgnoreReasons[reason];
- });
- if (activeReasons.length) {
- // eslint-disable-next-line no-console
- console.warn('Preload parameter of wavesurfer.load will be ignored because:\n\t- ' + activeReasons.join('\n\t- ')); // stop invalid values from being used
- preload = null;
- }
- } // loadBuffer(url, peaks, duration) requires that url is a string
- // but users can pass in a HTMLMediaElement to WaveSurfer
- if (this.params.backend === 'WebAudio' && url instanceof HTMLMediaElement) {
- url = url.src;
- }
- switch (this.params.backend) {
- case 'WebAudio':
- return this.loadBuffer(url, peaks, duration);
- case 'MediaElement':
- case 'MediaElementWebAudio':
- return this.loadMediaElement(url, peaks, preload, duration);
- }
- }
- /**
- * Loads audio using Web Audio buffer backend.
- *
- * @private
- * @emits WaveSurfer#waveform-ready
- * @param {string} url URL of audio file
- * @param {number[]|Number.<Array[]>} peaks Peaks data
- * @param {?number} duration Optional duration of audio file
- * @returns {void}
- */
- }, {
- key: "loadBuffer",
- value: function loadBuffer(url, peaks, duration) {
- var _this11 = this;
- var load = function load(action) {
- if (action) {
- _this11.tmpEvents.push(_this11.once('ready', action));
- }
- return _this11.getArrayBuffer(url, function (data) {
- return _this11.loadArrayBuffer(data);
- });
- };
- if (peaks) {
- this.backend.setPeaks(peaks, duration);
- this.drawBuffer();
- this.fireEvent('waveform-ready');
- this.tmpEvents.push(this.once('interaction', load));
- } else {
- return load();
- }
- }
- /**
- * Either create a media element, or load an existing media element.
- *
- * @private
- * @emits WaveSurfer#waveform-ready
- * @param {string|HTMLMediaElement} urlOrElt Either a path to a media file, or an
- * existing HTML5 Audio/Video Element
- * @param {number[]|Number.<Array[]>} peaks Array of peaks. Required to bypass web audio
- * dependency
- * @param {?boolean} preload Set to true if the preload attribute of the
- * audio element should be enabled
- * @param {?number} duration Optional duration of audio file
- */
- }, {
- key: "loadMediaElement",
- value: function loadMediaElement(urlOrElt, peaks, preload, duration) {
- var _this12 = this;
- var url = urlOrElt;
- if (typeof urlOrElt === 'string') {
- this.backend.load(url, this.mediaContainer, peaks, preload);
- } else {
- var elt = urlOrElt;
- this.backend.loadElt(elt, peaks); // If peaks are not provided,
- // url = element.src so we can get peaks with web audio
- url = elt.src;
- }
- this.tmpEvents.push(this.backend.once('canplay', function () {
- // ignore when backend was already destroyed
- if (!_this12.backend.destroyed) {
- _this12.drawBuffer();
- _this12.isReady = true;
- _this12.fireEvent('ready');
- }
- }), this.backend.once('error', function (err) {
- return _this12.fireEvent('error', err);
- })); // If peaks are provided, render them and fire the `waveform-ready` event.
- if (peaks) {
- this.backend.setPeaks(peaks, duration);
- this.drawBuffer();
- this.fireEvent('waveform-ready');
- } // If no pre-decoded peaks are provided, or are provided with
- // forceDecode flag, attempt to download the audio file and decode it
- // with Web Audio.
- if ((!peaks || this.params.forceDecode) && this.backend.supportsWebAudio()) {
- this.getArrayBuffer(url, function (arraybuffer) {
- _this12.decodeArrayBuffer(arraybuffer, function (buffer) {
- _this12.backend.buffer = buffer;
- _this12.backend.setPeaks(null);
- _this12.drawBuffer();
- _this12.fireEvent('waveform-ready');
- });
- });
- }
- }
- /**
- * Decode an array buffer and pass data to a callback
- *
- * @private
- * @param {Object} arraybuffer The array buffer to decode
- * @param {function} callback The function to call on complete
- */
- }, {
- key: "decodeArrayBuffer",
- value: function decodeArrayBuffer(arraybuffer, callback) {
- var _this13 = this;
- if (!this.isDestroyed) {
- this.arraybuffer = arraybuffer;
- this.backend.decodeArrayBuffer(arraybuffer, function (data) {
- // Only use the decoded data if we haven't been destroyed or
- // another decode started in the meantime
- if (!_this13.isDestroyed && _this13.arraybuffer == arraybuffer) {
- callback(data);
- _this13.arraybuffer = null;
- }
- }, function () {
- return _this13.fireEvent('error', 'Error decoding audiobuffer');
- });
- }
- }
- /**
- * Load an array buffer using fetch and pass the result to a callback
- *
- * @param {string} url The URL of the file object
- * @param {function} callback The function to call on complete
- * @returns {util.fetchFile} fetch call
- * @private
- */
- }, {
- key: "getArrayBuffer",
- value: function getArrayBuffer(url, callback) {
- var _this14 = this;
- var options = Object.assign({
- url: url,
- responseType: 'arraybuffer'
- }, this.params.xhr);
- var request = util.fetchFile(options);
- this.currentRequest = request;
- this.tmpEvents.push(request.on('progress', function (e) {
- _this14.onProgress(e);
- }), request.on('success', function (data) {
- callback(data);
- _this14.currentRequest = null;
- }), request.on('error', function (e) {
- _this14.fireEvent('error', e);
- _this14.currentRequest = null;
- }));
- return request;
- }
- /**
- * Called while the audio file is loading
- *
- * @private
- * @param {Event} e Progress event
- * @emits WaveSurfer#loading
- */
- }, {
- key: "onProgress",
- value: function onProgress(e) {
- var percentComplete;
- if (e.lengthComputable) {
- percentComplete = e.loaded / e.total;
- } else {
- // Approximate progress with an asymptotic
- // function, and assume downloads in the 1-3 MB range.
- percentComplete = e.loaded / (e.loaded + 1000000);
- }
- this.fireEvent('loading', Math.round(percentComplete * 100), e.target);
- }
- /**
- * Exports PCM data into a JSON array and optionally opens in a new window
- * as valid JSON Blob instance.
- *
- * @param {number} length=1024 The scale in which to export the peaks
- * @param {number} accuracy=10000
- * @param {?boolean} noWindow Set to true to disable opening a new
- * window with the JSON
- * @param {number} start Start index
- * @param {number} end End index
- * @return {Promise} Promise that resolves with array of peaks
- */
- }, {
- key: "exportPCM",
- value: function exportPCM(length, accuracy, noWindow, start, end) {
- length = length || 1024;
- start = start || 0;
- accuracy = accuracy || 10000;
- noWindow = noWindow || false;
- var peaks = this.backend.getPeaks(length, start, end);
- var arr = [].map.call(peaks, function (val) {
- return Math.round(val * accuracy) / accuracy;
- });
- return new Promise(function (resolve, reject) {
- if (!noWindow) {
- var blobJSON = new Blob([JSON.stringify(arr)], {
- type: 'application/json;charset=utf-8'
- });
- var objURL = URL.createObjectURL(blobJSON);
- window.open(objURL);
- URL.revokeObjectURL(objURL);
- }
- resolve(arr);
- });
- }
- /**
- * Save waveform image as data URI.
- *
- * The default format is `'image/png'`. Other supported types are
- * `'image/jpeg'` and `'image/webp'`.
- *
- * @param {string} format='image/png' A string indicating the image format.
- * The default format type is `'image/png'`.
- * @param {number} quality=1 A number between 0 and 1 indicating the image
- * quality to use for image formats that use lossy compression such as
- * `'image/jpeg'`` and `'image/webp'`.
- * @param {string} type Image data type to return. Either 'dataURL' (default)
- * or 'blob'.
- * @return {string|string[]|Promise} When using `'dataURL'` type this returns
- * a single data URL or an array of data URLs, one for each canvas. When using
- * `'blob'` type this returns a `Promise` resolving with an array of `Blob`
- * instances, one for each canvas.
- */
- }, {
- key: "exportImage",
- value: function exportImage(format, quality, type) {
- if (!format) {
- format = 'image/png';
- }
- if (!quality) {
- quality = 1;
- }
- if (!type) {
- type = 'dataURL';
- }
- return this.drawer.getImage(format, quality, type);
- }
- /**
- * Cancel any fetch request currently in progress
- */
- }, {
- key: "cancelAjax",
- value: function cancelAjax() {
- if (this.currentRequest && this.currentRequest.controller) {
- // If the current request has a ProgressHandler, then its ReadableStream might need to be cancelled too
- // See: Wavesurfer issue #2042
- // See Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1583815
- if (this.currentRequest._reader) {
- // Ignoring exceptions thrown by call to cancel()
- this.currentRequest._reader.cancel().catch(function (err) {});
- }
- this.currentRequest.controller.abort();
- this.currentRequest = null;
- }
- }
- /**
- * @private
- */
- }, {
- key: "clearTmpEvents",
- value: function clearTmpEvents() {
- this.tmpEvents.forEach(function (e) {
- return e.un();
- });
- }
- /**
- * Display empty waveform.
- */
- }, {
- key: "empty",
- value: function empty() {
- if (!this.backend.isPaused()) {
- this.stop();
- this.backend.disconnectSource();
- }
- this.isReady = false;
- this.cancelAjax();
- this.clearTmpEvents(); // empty drawer
- this.drawer.progress(0);
- this.drawer.setWidth(0);
- this.drawer.drawPeaks({
- length: this.drawer.getWidth()
- }, 0);
- }
- /**
- * Remove events, elements and disconnect WebAudio nodes.
- *
- * @emits WaveSurfer#destroy
- */
- }, {
- key: "destroy",
- value: function destroy() {
- this.destroyAllPlugins();
- this.fireEvent('destroy');
- this.cancelAjax();
- this.clearTmpEvents();
- this.unAll();
- if (this.params.responsive !== false) {
- window.removeEventListener('resize', this._onResize, true);
- window.removeEventListener('orientationchange', this._onResize, true);
- }
- if (this.backend) {
- this.backend.destroy(); // clears memory usage
- this.backend = null;
- }
- if (this.drawer) {
- this.drawer.destroy();
- }
- this.isDestroyed = true;
- this.isReady = false;
- this.arraybuffer = null;
- }
- }], [{
- key: "create",
- value:
- /** @private */
- /** @private */
- /**
- * Instantiate this class, call its `init` function and returns it
- *
- * @param {WavesurferParams} params The wavesurfer parameters
- * @return {Object} WaveSurfer instance
- * @example const wavesurfer = WaveSurfer.create(params);
- */
- function create(params) {
- var wavesurfer = new WaveSurfer(params);
- return wavesurfer.init();
- }
- /**
- * The library version number is available as a static property of the
- * WaveSurfer class
- *
- * @type {String}
- * @example
- * console.log('Using wavesurfer.js ' + WaveSurfer.VERSION);
- */
- }]);
- return WaveSurfer;
- }(util.Observer);
- exports["default"] = WaveSurfer;
- _defineProperty(WaveSurfer, "VERSION", "6.1.0");
- _defineProperty(WaveSurfer, "util", util);
- module.exports = exports.default;
- /***/ }),
- /***/ "./src/webaudio.js":
- /*!*************************!*\
- !*** ./src/webaudio.js ***!
- \*************************/
- /***/ ((module, exports, __webpack_require__) => {
- "use strict";
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
- Object.defineProperty(exports, "__esModule", ({
- value: true
- }));
- exports["default"] = void 0;
- var util = _interopRequireWildcard(__webpack_require__(/*! ./util */ "./src/util/index.js"));
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- // using constants to prevent someone writing the string wrong
- var PLAYING = 'playing';
- var PAUSED = 'paused';
- var FINISHED = 'finished';
- /**
- * WebAudio backend
- *
- * @extends {Observer}
- */
- var WebAudio = /*#__PURE__*/function (_util$Observer) {
- _inherits(WebAudio, _util$Observer);
- var _super = _createSuper(WebAudio);
- /**
- * Construct the backend
- *
- * @param {WavesurferParams} params Wavesurfer parameters
- */
- function WebAudio(params) {
- var _defineProperty2, _this$states;
- var _this;
- _classCallCheck(this, WebAudio);
- _this = _super.call(this);
- /** @private */
- _defineProperty(_assertThisInitialized(_this), "audioContext", null);
- _defineProperty(_assertThisInitialized(_this), "offlineAudioContext", null);
- _defineProperty(_assertThisInitialized(_this), "stateBehaviors", (_defineProperty2 = {}, _defineProperty(_defineProperty2, PLAYING, {
- init: function init() {
- this.addOnAudioProcess();
- },
- getPlayedPercents: function getPlayedPercents() {
- var duration = this.getDuration();
- return this.getCurrentTime() / duration || 0;
- },
- getCurrentTime: function getCurrentTime() {
- return this.startPosition + this.getPlayedTime();
- }
- }), _defineProperty(_defineProperty2, PAUSED, {
- init: function init() {
- this.removeOnAudioProcess();
- },
- getPlayedPercents: function getPlayedPercents() {
- var duration = this.getDuration();
- return this.getCurrentTime() / duration || 0;
- },
- getCurrentTime: function getCurrentTime() {
- return this.startPosition;
- }
- }), _defineProperty(_defineProperty2, FINISHED, {
- init: function init() {
- this.removeOnAudioProcess();
- this.fireEvent('finish');
- },
- getPlayedPercents: function getPlayedPercents() {
- return 1;
- },
- getCurrentTime: function getCurrentTime() {
- return this.getDuration();
- }
- }), _defineProperty2));
- _this.params = params;
- /** ac: Audio Context instance */
- _this.ac = params.audioContext || (_this.supportsWebAudio() ? _this.getAudioContext() : {});
- /**@private */
- _this.lastPlay = _this.ac.currentTime;
- /** @private */
- _this.startPosition = 0;
- /** @private */
- _this.scheduledPause = null;
- /** @private */
- _this.states = (_this$states = {}, _defineProperty(_this$states, PLAYING, Object.create(_this.stateBehaviors[PLAYING])), _defineProperty(_this$states, PAUSED, Object.create(_this.stateBehaviors[PAUSED])), _defineProperty(_this$states, FINISHED, Object.create(_this.stateBehaviors[FINISHED])), _this$states);
- /** @private */
- _this.buffer = null;
- /** @private */
- _this.filters = [];
- /** gainNode: allows to control audio volume */
- _this.gainNode = null;
- /** @private */
- _this.mergedPeaks = null;
- /** @private */
- _this.offlineAc = null;
- /** @private */
- _this.peaks = null;
- /** @private */
- _this.playbackRate = 1;
- /** analyser: provides audio analysis information */
- _this.analyser = null;
- /** scriptNode: allows processing audio */
- _this.scriptNode = null;
- /** @private */
- _this.source = null;
- /** @private */
- _this.splitPeaks = [];
- /** @private */
- _this.state = null;
- /** @private */
- _this.explicitDuration = params.duration;
- /** @private */
- _this.sinkStreamDestination = null;
- /** @private */
- _this.sinkAudioElement = null;
- /**
- * Boolean indicating if the backend was destroyed.
- */
- _this.destroyed = false;
- return _this;
- }
- /**
- * Initialise the backend, called in `wavesurfer.createBackend()`
- */
- _createClass(WebAudio, [{
- key: "supportsWebAudio",
- value:
- /** scriptBufferSize: size of the processing buffer */
- /** audioContext: allows to process audio with WebAudio API */
- /** @private */
- /** @private */
- /**
- * Does the browser support this backend
- *
- * @return {boolean} Whether or not this browser supports this backend
- */
- function supportsWebAudio() {
- return !!(window.AudioContext || window.webkitAudioContext);
- }
- /**
- * Get the audio context used by this backend or create one
- *
- * @return {AudioContext} Existing audio context, or creates a new one
- */
- }, {
- key: "getAudioContext",
- value: function getAudioContext() {
- if (!window.WaveSurferAudioContext) {
- window.WaveSurferAudioContext = new (window.AudioContext || window.webkitAudioContext)();
- }
- return window.WaveSurferAudioContext;
- }
- /**
- * Get the offline audio context used by this backend or create one
- *
- * @param {number} sampleRate The sample rate to use
- * @return {OfflineAudioContext} Existing offline audio context, or creates
- * a new one
- */
- }, {
- key: "getOfflineAudioContext",
- value: function getOfflineAudioContext(sampleRate) {
- if (!window.WaveSurferOfflineAudioContext) {
- window.WaveSurferOfflineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, sampleRate);
- }
- return window.WaveSurferOfflineAudioContext;
- }
- }, {
- key: "init",
- value: function init() {
- this.createVolumeNode();
- this.createScriptNode();
- this.createAnalyserNode();
- this.setState(PAUSED);
- this.setPlaybackRate(this.params.audioRate);
- this.setLength(0);
- }
- /** @private */
- }, {
- key: "disconnectFilters",
- value: function disconnectFilters() {
- if (this.filters) {
- this.filters.forEach(function (filter) {
- filter && filter.disconnect();
- });
- this.filters = null; // Reconnect direct path
- this.analyser.connect(this.gainNode);
- }
- }
- /**
- * @private
- *
- * @param {string} state The new state
- */
- }, {
- key: "setState",
- value: function setState(state) {
- if (this.state !== this.states[state]) {
- this.state = this.states[state];
- this.state.init.call(this);
- }
- }
- /**
- * Unpacked `setFilters()`
- *
- * @param {...AudioNode} filters One or more filters to set
- */
- }, {
- key: "setFilter",
- value: function setFilter() {
- for (var _len = arguments.length, filters = new Array(_len), _key = 0; _key < _len; _key++) {
- filters[_key] = arguments[_key];
- }
- this.setFilters(filters);
- }
- /**
- * Insert custom Web Audio nodes into the graph
- *
- * @param {AudioNode[]} filters Packed filters array
- * @example
- * const lowpass = wavesurfer.backend.ac.createBiquadFilter();
- * wavesurfer.backend.setFilter(lowpass);
- */
- }, {
- key: "setFilters",
- value: function setFilters(filters) {
- // Remove existing filters
- this.disconnectFilters(); // Insert filters if filter array not empty
- if (filters && filters.length) {
- this.filters = filters; // Disconnect direct path before inserting filters
- this.analyser.disconnect(); // Connect each filter in turn
- filters.reduce(function (prev, curr) {
- prev.connect(curr);
- return curr;
- }, this.analyser).connect(this.gainNode);
- }
- }
- /** Create ScriptProcessorNode to process audio */
- }, {
- key: "createScriptNode",
- value: function createScriptNode() {
- if (this.params.audioScriptProcessor) {
- this.scriptNode = this.params.audioScriptProcessor;
- } else {
- if (this.ac.createScriptProcessor) {
- this.scriptNode = this.ac.createScriptProcessor(WebAudio.scriptBufferSize);
- } else {
- this.scriptNode = this.ac.createJavaScriptNode(WebAudio.scriptBufferSize);
- }
- }
- this.scriptNode.connect(this.ac.destination);
- }
- /** @private */
- }, {
- key: "addOnAudioProcess",
- value: function addOnAudioProcess() {
- var _this2 = this;
- this.scriptNode.onaudioprocess = function () {
- var time = _this2.getCurrentTime();
- if (time >= _this2.getDuration()) {
- _this2.setState(FINISHED);
- _this2.fireEvent('pause');
- } else if (time >= _this2.scheduledPause) {
- _this2.pause();
- } else if (_this2.state === _this2.states[PLAYING]) {
- _this2.fireEvent('audioprocess', time);
- }
- };
- }
- /** @private */
- }, {
- key: "removeOnAudioProcess",
- value: function removeOnAudioProcess() {
- this.scriptNode.onaudioprocess = null;
- }
- /** Create analyser node to perform audio analysis */
- }, {
- key: "createAnalyserNode",
- value: function createAnalyserNode() {
- this.analyser = this.ac.createAnalyser();
- this.analyser.connect(this.gainNode);
- }
- /**
- * Create the gain node needed to control the playback volume.
- *
- */
- }, {
- key: "createVolumeNode",
- value: function createVolumeNode() {
- // Create gain node using the AudioContext
- if (this.ac.createGain) {
- this.gainNode = this.ac.createGain();
- } else {
- this.gainNode = this.ac.createGainNode();
- } // Add the gain node to the graph
- this.gainNode.connect(this.ac.destination);
- }
- /**
- * Set the sink id for the media player
- *
- * @param {string} deviceId String value representing audio device id.
- * @returns {Promise} A Promise that resolves to `undefined` when there
- * are no errors.
- */
- }, {
- key: "setSinkId",
- value: function setSinkId(deviceId) {
- if (deviceId) {
- /**
- * The webaudio API doesn't currently support setting the device
- * output. Here we create an HTMLAudioElement, connect the
- * webaudio stream to that element and setSinkId there.
- */
- if (!this.sinkAudioElement) {
- this.sinkAudioElement = new window.Audio(); // autoplay is necessary since we're not invoking .play()
- this.sinkAudioElement.autoplay = true;
- }
- if (!this.sinkAudioElement.setSinkId) {
- return Promise.reject(new Error('setSinkId is not supported in your browser'));
- }
- if (!this.sinkStreamDestination) {
- this.sinkStreamDestination = this.ac.createMediaStreamDestination();
- }
- this.gainNode.disconnect();
- this.gainNode.connect(this.sinkStreamDestination);
- this.sinkAudioElement.srcObject = this.sinkStreamDestination.stream;
- return this.sinkAudioElement.setSinkId(deviceId);
- } else {
- return Promise.reject(new Error('Invalid deviceId: ' + deviceId));
- }
- }
- /**
- * Set the audio volume
- *
- * @param {number} value A floating point value between 0 and 1.
- */
- }, {
- key: "setVolume",
- value: function setVolume(value) {
- this.gainNode.gain.setValueAtTime(value, this.ac.currentTime);
- }
- /**
- * Get the current volume
- *
- * @return {number} value A floating point value between 0 and 1.
- */
- }, {
- key: "getVolume",
- value: function getVolume() {
- return this.gainNode.gain.value;
- }
- /**
- * Decode an array buffer and pass data to a callback
- *
- * @private
- * @param {ArrayBuffer} arraybuffer The array buffer to decode
- * @param {function} callback The function to call on complete.
- * @param {function} errback The function to call on error.
- */
- }, {
- key: "decodeArrayBuffer",
- value: function decodeArrayBuffer(arraybuffer, callback, errback) {
- if (!this.offlineAc) {
- this.offlineAc = this.getOfflineAudioContext(this.ac && this.ac.sampleRate ? this.ac.sampleRate : 44100);
- }
- if ('webkitAudioContext' in window) {
- // Safari: no support for Promise-based decodeAudioData enabled
- // Enable it in Safari using the Experimental Features > Modern WebAudio API option
- this.offlineAc.decodeAudioData(arraybuffer, function (data) {
- return callback(data);
- }, errback);
- } else {
- this.offlineAc.decodeAudioData(arraybuffer).then(function (data) {
- return callback(data);
- }).catch(function (err) {
- return errback(err);
- });
- }
- }
- /**
- * Set pre-decoded peaks
- *
- * @param {number[]|Number.<Array[]>} peaks Peaks data
- * @param {?number} duration Explicit duration
- */
- }, {
- key: "setPeaks",
- value: function setPeaks(peaks, duration) {
- if (duration != null) {
- this.explicitDuration = duration;
- }
- this.peaks = peaks;
- }
- /**
- * Set the rendered length (different from the length of the audio)
- *
- * @param {number} length The rendered length
- */
- }, {
- key: "setLength",
- value: function setLength(length) {
- // No resize, we can preserve the cached peaks.
- if (this.mergedPeaks && length == 2 * this.mergedPeaks.length - 1 + 2) {
- return;
- }
- this.splitPeaks = [];
- this.mergedPeaks = []; // Set the last element of the sparse array so the peak arrays are
- // appropriately sized for other calculations.
- var channels = this.buffer ? this.buffer.numberOfChannels : 1;
- var c;
- for (c = 0; c < channels; c++) {
- this.splitPeaks[c] = [];
- this.splitPeaks[c][2 * (length - 1)] = 0;
- this.splitPeaks[c][2 * (length - 1) + 1] = 0;
- }
- this.mergedPeaks[2 * (length - 1)] = 0;
- this.mergedPeaks[2 * (length - 1) + 1] = 0;
- }
- /**
- * Compute the max and min value of the waveform when broken into <length> subranges.
- *
- * @param {number} length How many subranges to break the waveform into.
- * @param {number} first First sample in the required range.
- * @param {number} last Last sample in the required range.
- * @return {number[]|Number.<Array[]>} Array of 2*<length> peaks or array of arrays of
- * peaks consisting of (max, min) values for each subrange.
- */
- }, {
- key: "getPeaks",
- value: function getPeaks(length, first, last) {
- if (this.peaks) {
- return this.peaks;
- }
- if (!this.buffer) {
- return [];
- }
- first = first || 0;
- last = last || length - 1;
- this.setLength(length);
- if (!this.buffer) {
- return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;
- }
- /**
- * The following snippet fixes a buffering data issue on the Safari
- * browser which returned undefined It creates the missing buffer based
- * on 1 channel, 4096 samples and the sampleRate from the current
- * webaudio context 4096 samples seemed to be the best fit for rendering
- * will review this code once a stable version of Safari TP is out
- */
- if (!this.buffer.length) {
- var newBuffer = this.createBuffer(1, 4096, this.sampleRate);
- this.buffer = newBuffer.buffer;
- }
- var sampleSize = this.buffer.length / length;
- var sampleStep = ~~(sampleSize / 10) || 1;
- var channels = this.buffer.numberOfChannels;
- var c;
- for (c = 0; c < channels; c++) {
- var peaks = this.splitPeaks[c];
- var chan = this.buffer.getChannelData(c);
- var i = void 0;
- for (i = first; i <= last; i++) {
- var start = ~~(i * sampleSize);
- var end = ~~(start + sampleSize);
- /**
- * Initialize the max and min to the first sample of this
- * subrange, so that even if the samples are entirely
- * on one side of zero, we still return the true max and
- * min values in the subrange.
- */
- var min = chan[start];
- var max = min;
- var j = void 0;
- for (j = start; j < end; j += sampleStep) {
- var value = chan[j];
- if (value > max) {
- max = value;
- }
- if (value < min) {
- min = value;
- }
- }
- peaks[2 * i] = max;
- peaks[2 * i + 1] = min;
- if (c == 0 || max > this.mergedPeaks[2 * i]) {
- this.mergedPeaks[2 * i] = max;
- }
- if (c == 0 || min < this.mergedPeaks[2 * i + 1]) {
- this.mergedPeaks[2 * i + 1] = min;
- }
- }
- }
- return this.params.splitChannels ? this.splitPeaks : this.mergedPeaks;
- }
- /**
- * Get the position from 0 to 1
- *
- * @return {number} Position
- */
- }, {
- key: "getPlayedPercents",
- value: function getPlayedPercents() {
- return this.state.getPlayedPercents.call(this);
- }
- /** @private */
- }, {
- key: "disconnectSource",
- value: function disconnectSource() {
- if (this.source) {
- this.source.disconnect();
- }
- }
- /**
- * Destroy all references with WebAudio, disconnecting audio nodes and closing Audio Context
- */
- }, {
- key: "destroyWebAudio",
- value: function destroyWebAudio() {
- this.disconnectFilters();
- this.disconnectSource();
- this.gainNode.disconnect();
- this.scriptNode.disconnect();
- this.analyser.disconnect(); // close the audioContext if closeAudioContext option is set to true
- if (this.params.closeAudioContext) {
- // check if browser supports AudioContext.close()
- if (typeof this.ac.close === 'function' && this.ac.state != 'closed') {
- this.ac.close();
- } // clear the reference to the audiocontext
- this.ac = null; // clear the actual audiocontext, either passed as param or the
- // global singleton
- if (!this.params.audioContext) {
- window.WaveSurferAudioContext = null;
- } else {
- this.params.audioContext = null;
- } // clear the offlineAudioContext
- window.WaveSurferOfflineAudioContext = null;
- } // disconnect resources used by setSinkId
- if (this.sinkStreamDestination) {
- this.sinkAudioElement.pause();
- this.sinkAudioElement.srcObject = null;
- this.sinkStreamDestination.disconnect();
- this.sinkStreamDestination = null;
- }
- }
- /**
- * This is called when wavesurfer is destroyed
- */
- }, {
- key: "destroy",
- value: function destroy() {
- if (!this.isPaused()) {
- this.pause();
- }
- this.unAll();
- this.buffer = null;
- this.destroyed = true;
- this.destroyWebAudio();
- }
- /**
- * Loaded a decoded audio buffer
- *
- * @param {Object} buffer Decoded audio buffer to load
- */
- }, {
- key: "load",
- value: function load(buffer) {
- this.startPosition = 0;
- this.lastPlay = this.ac.currentTime;
- this.buffer = buffer;
- this.createSource();
- }
- /** @private */
- }, {
- key: "createSource",
- value: function createSource() {
- this.disconnectSource();
- this.source = this.ac.createBufferSource(); // adjust for old browsers
- this.source.start = this.source.start || this.source.noteGrainOn;
- this.source.stop = this.source.stop || this.source.noteOff;
- this.setPlaybackRate(this.playbackRate);
- this.source.buffer = this.buffer;
- this.source.connect(this.analyser);
- }
- /**
- * @private
- *
- * some browsers require an explicit call to #resume before they will play back audio
- */
- }, {
- key: "resumeAudioContext",
- value: function resumeAudioContext() {
- if (this.ac.state == 'suspended') {
- this.ac.resume && this.ac.resume();
- }
- }
- /**
- * Used by `wavesurfer.isPlaying()` and `wavesurfer.playPause()`
- *
- * @return {boolean} Whether or not this backend is currently paused
- */
- }, {
- key: "isPaused",
- value: function isPaused() {
- return this.state !== this.states[PLAYING];
- }
- /**
- * Used by `wavesurfer.getDuration()`
- *
- * @return {number} Duration of loaded buffer
- */
- }, {
- key: "getDuration",
- value: function getDuration() {
- if (this.explicitDuration) {
- return this.explicitDuration;
- }
- if (!this.buffer) {
- return 0;
- }
- return this.buffer.duration;
- }
- /**
- * Used by `wavesurfer.seekTo()`
- *
- * @param {number} start Position to start at in seconds
- * @param {number} end Position to end at in seconds
- * @return {{start: number, end: number}} Object containing start and end
- * positions
- */
- }, {
- key: "seekTo",
- value: function seekTo(start, end) {
- if (!this.buffer) {
- return;
- }
- this.scheduledPause = null;
- if (start == null) {
- start = this.getCurrentTime();
- if (start >= this.getDuration()) {
- start = 0;
- }
- }
- if (end == null) {
- end = this.getDuration();
- }
- this.startPosition = start;
- this.lastPlay = this.ac.currentTime;
- if (this.state === this.states[FINISHED]) {
- this.setState(PAUSED);
- }
- return {
- start: start,
- end: end
- };
- }
- /**
- * Get the playback position in seconds
- *
- * @return {number} The playback position in seconds
- */
- }, {
- key: "getPlayedTime",
- value: function getPlayedTime() {
- return (this.ac.currentTime - this.lastPlay) * this.playbackRate;
- }
- /**
- * Plays the loaded audio region.
- *
- * @param {number} start Start offset in seconds, relative to the beginning
- * of a clip.
- * @param {number} end When to stop relative to the beginning of a clip.
- */
- }, {
- key: "play",
- value: function play(start, end) {
- if (!this.buffer) {
- return;
- } // need to re-create source on each playback
- this.createSource();
- var adjustedTime = this.seekTo(start, end);
- start = adjustedTime.start;
- end = adjustedTime.end;
- this.scheduledPause = end;
- this.source.start(0, start);
- this.resumeAudioContext();
- this.setState(PLAYING);
- this.fireEvent('play');
- }
- /**
- * Pauses the loaded audio.
- */
- }, {
- key: "pause",
- value: function pause() {
- this.scheduledPause = null;
- this.startPosition += this.getPlayedTime();
- try {
- this.source && this.source.stop(0);
- } catch (err) {// Calling stop can throw the following 2 errors:
- // - RangeError (The value specified for when is negative.)
- // - InvalidStateNode (The node has not been started by calling start().)
- // We can safely ignore both errors, because:
- // - The range is surely correct
- // - The node might not have been started yet, in which case we just want to carry on without causing any trouble.
- }
- this.setState(PAUSED);
- this.fireEvent('pause');
- }
- /**
- * Returns the current time in seconds relative to the audio-clip's
- * duration.
- *
- * @return {number} The current time in seconds
- */
- }, {
- key: "getCurrentTime",
- value: function getCurrentTime() {
- return this.state.getCurrentTime.call(this);
- }
- /**
- * Returns the current playback rate. (0=no playback, 1=normal playback)
- *
- * @return {number} The current playback rate
- */
- }, {
- key: "getPlaybackRate",
- value: function getPlaybackRate() {
- return this.playbackRate;
- }
- /**
- * Set the audio source playback rate.
- *
- * @param {number} value The playback rate to use
- */
- }, {
- key: "setPlaybackRate",
- value: function setPlaybackRate(value) {
- this.playbackRate = value || 1;
- this.source && this.source.playbackRate.setValueAtTime(this.playbackRate, this.ac.currentTime);
- }
- /**
- * Set a point in seconds for playback to stop at.
- *
- * @param {number} end Position to end at
- * @version 3.3.0
- */
- }, {
- key: "setPlayEnd",
- value: function setPlayEnd(end) {
- this.scheduledPause = end;
- }
- }]);
- return WebAudio;
- }(util.Observer);
- exports["default"] = WebAudio;
- _defineProperty(WebAudio, "scriptBufferSize", 256);
- module.exports = exports.default;
- /***/ }),
- /***/ "./node_modules/debounce/index.js":
- /*!****************************************!*\
- !*** ./node_modules/debounce/index.js ***!
- \****************************************/
- /***/ ((module) => {
- /**
- * Returns a function, that, as long as it continues to be invoked, will not
- * be triggered. The function will be called after it stops being called for
- * N milliseconds. If `immediate` is passed, trigger the function on the
- * leading edge, instead of the trailing. The function also has a property 'clear'
- * that is a function which will clear the timer to prevent previously scheduled executions.
- *
- * @source underscore.js
- * @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
- * @param {Function} function to wrap
- * @param {Number} timeout in ms (`100`)
- * @param {Boolean} whether to execute at the beginning (`false`)
- * @api public
- */
- function debounce(func, wait, immediate){
- var timeout, args, context, timestamp, result;
- if (null == wait) wait = 100;
- function later() {
- var last = Date.now() - timestamp;
- if (last < wait && last >= 0) {
- timeout = setTimeout(later, wait - last);
- } else {
- timeout = null;
- if (!immediate) {
- result = func.apply(context, args);
- context = args = null;
- }
- }
- };
- var debounced = function(){
- context = this;
- args = arguments;
- timestamp = Date.now();
- var callNow = immediate && !timeout;
- if (!timeout) timeout = setTimeout(later, wait);
- if (callNow) {
- result = func.apply(context, args);
- context = args = null;
- }
- return result;
- };
- debounced.clear = function() {
- if (timeout) {
- clearTimeout(timeout);
- timeout = null;
- }
- };
-
- debounced.flush = function() {
- if (timeout) {
- result = func.apply(context, args);
- context = args = null;
-
- clearTimeout(timeout);
- timeout = null;
- }
- };
- return debounced;
- };
- // Adds compatibility for ES modules
- debounce.debounce = debounce;
- module.exports = debounce;
- /***/ })
- /******/ });
- /************************************************************************/
- /******/ // The module cache
- /******/ var __webpack_module_cache__ = {};
- /******/
- /******/ // The require function
- /******/ function __webpack_require__(moduleId) {
- /******/ // Check if module is in cache
- /******/ var cachedModule = __webpack_module_cache__[moduleId];
- /******/ if (cachedModule !== undefined) {
- /******/ return cachedModule.exports;
- /******/ }
- /******/ // Create a new module (and put it into the cache)
- /******/ var module = __webpack_module_cache__[moduleId] = {
- /******/ // no module.id needed
- /******/ // no module.loaded needed
- /******/ exports: {}
- /******/ };
- /******/
- /******/ // Execute the module function
- /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
- /******/
- /******/ // Return the exports of the module
- /******/ return module.exports;
- /******/ }
- /******/
- /************************************************************************/
- /******/
- /******/ // startup
- /******/ // Load entry module and return exports
- /******/ // This entry module is referenced by other modules so it can't be inlined
- /******/ var __webpack_exports__ = __webpack_require__("./src/wavesurfer.js");
- /******/
- /******/ return __webpack_exports__;
- /******/ })()
- ;
- });
- //# sourceMappingURL=wavesurfer.js.map
|