Is it possible to mix multiple audio files on top of each other preferably with javascript -


i want combine audio clips, layered on top of each other play synchronously , saved in new audio file. appreciated. i've done digging online, couldn't find definitive answer whether or not many of tools available far javascript audio editing librarys go (mix.js example) capable.

yes, possible using offlineaudiocontext() or audiocontext.createchannelmerger() , creating mediastream. see phonegap mixing audio files , web audio api.

you can use fetch() or xmlhttprequest() retrieve audio resource arraybuffer, audiocontext.decodeaudiodata() create audiobuffersourcenode response; offlineaudiocontext() render merged audio, audiocontext, audiocontext.createbuffersource(), audiocontext.createmediastreamdestination() , mediarecorder() record stream; promise.all(), promise() constructor, .then() process asynchronous requests fetch(), audiocontext.decodeaudiodata(), pass resulting mixed audio blob @ stop event of mediarecorder.

connect each audiocontext audiobuffersourcenode offlineaudiocontext.destination, call .start() on each node; call offlineaudiocontext.startrendering(); create new audiocontext node, connect renderedbuffer; call .createmediastreamdestination() on audiocontext create mediastream merged audio buffers, pass .stream mediarecorder(), @ stop event of mediarecorder, create blob url of blob of recorded audio mix url.createobjecturl(), can downloaded using <a> element download attribute , href set blob url.

var sources = ["https://upload.wikimedia.org/wikipedia/commons/b/be/"                 + "hidden_tribe_-_didgeridoo_1_live.ogg"                 , "https://upload.wikimedia.org/wikipedia/commons/6/6e/"                  + "micronesia_national_anthem.ogg"];    var description = "hiddentribeanthem";  var context;  var recorder;  var div = document.queryselector("div");  var duration = 60000;  var chunks = [];  var audio = new audiocontext();  var mixedaudio = audio.createmediastreamdestination();  var player = new audio();  player.controls = "controls";    function get(src) {    return fetch(src)      .then(function(response) {        return response.arraybuffer()      })  }    function stopmix(duration, ...media) {    settimeout(function(media) {      media.foreach(function(node) {        node.stop()      })    }, duration, media)  }    promise.all(sources.map(get)).then(function(data) {      var len = math.max.apply(math, data.map(function(buffer) {        return buffer.bytelength      }));      context = new offlineaudiocontext(2, len, 44100);      return promise.all(data.map(function(buffer) {          return audio.decodeaudiodata(buffer)            .then(function(buffersource) {              var source = context.createbuffersource();              source.buffer = buffersource;              source.connect(context.destination);              return source.start()            })        }))        .then(function() {          return context.startrendering()        })        .then(function(renderedbuffer) {          return new promise(function(resolve) {            var mix = audio.createbuffersource();            mix.buffer = renderedbuffer;            mix.connect(audio.destination);            mix.connect(mixedaudio);                          recorder = new mediarecorder(mixedaudio.stream);            recorder.start(0);            mix.start(0);            div.innerhtml = "playing , recording tracks..";            // stop playback , recorder in 60 seconds            stopmix(duration, mix, recorder)              recorder.ondataavailable = function(event) {              chunks.push(event.data);            };              recorder.onstop = function(event) {              var blob = new blob(chunks,  {                "type": "audio/ogg; codecs=opus"              });              console.log("recording complete");              resolve(blob)            };          })        })        .then(function(blob) {          console.log(blob);          div.innerhtml = "mixed audio tracks ready download..";          var audiodownload = url.createobjecturl(blob);          var = document.createelement("a");          a.download = description + "." + blob.type.replace(/.+\/|;.+/g, "");          a.href = audiodownload;          a.innerhtml = a.download;          document.body.appendchild(a);          a.insertadjacenthtml("afterend", "<br>");          player.src = audiodownload;          document.body.appendchild(player);        })    })    .catch(function(e) {      console.log(e)    });
<!doctype html>  <html>    <head>  </head>    <body>    <div>loading audio tracks.. please wait</div>  </body>    </html>

you can alternatively utilize audiocontext.createchannelmerger(), audiocontext.createchannelsplitter()

var sources = ["/path/to/audoi1", "/path/to/audio2"];     var description = "mix"; var chunks = []; var channels = [[0, 1], [1, 0]]; var audio = new audiocontext(); var player = new audio(); var merger = audio.createchannelmerger(2); var splitter = audio.createchannelsplitter(2); var mixedaudio = audio.createmediastreamdestination(); var duration = 60000; var context; var recorder; var audiodownload;  player.controls = "controls";  function get(src) {   return fetch(src)     .then(function(response) {       return response.arraybuffer()     }) }  function stopmix(duration, ...media) {   settimeout(function(media) {     media.foreach(function(node) {       node.stop()     })   }, duration, media) }  promise.all(sources.map(get)).then(function(data) {     return promise.all(data.map(function(buffer, index) {         return audio.decodeaudiodata(buffer)           .then(function(buffersource) {             var channel = channels[index];             var source = audio.createbuffersource();             source.buffer = buffersource;             source.connect(splitter);             splitter.connect(merger, channel[0], channel[1]);             return source           })       }))       .then(function(audionodes) {         merger.connect(mixedaudio);         merger.connect(audio.destination);         recorder = new mediarecorder(mixedaudio.stream);         recorder.start(0);         audionodes.foreach(function(node) {           node.start(0)         });          stopmix(duration, ...audionodes, recorder);          recorder.ondataavailable = function(event) {           chunks.push(event.data);         };          recorder.onstop = function(event) {           var blob = new blob(chunks, {             "type": "audio/ogg; codecs=opus"           });           audiodownload = url.createobjecturl(blob);           var = document.createelement("a");           a.download = description + "." + blob.type.replace(/.+\/|;.+/g, "");           a.href = audiodownload;           a.innerhtml = a.download;           player.src = audiodownload;           document.body.appendchild(a);           document.body.appendchild(player);         };       })   })   .catch(function(e) {     console.log(e)   }); 

Comments

Popular posts from this blog

php - How to display all orders for a single product showing the most recent first? Woocommerce -

asp.net - How to correctly use QUERY_STRING in ISAPI rewrite? -

angularjs - How restrict admin panel using in backend laravel and admin panel on angular? -