javascript - recorderJS record/download audio buffer WEB AUDIO API -


i want record audio output simple drum sequencer , export download wav file. have live link current attempt @ implementation attempt.

the sum output of sequencer routed variable finalmixnode yet setting input recorder.js doesn't work. think may problem audio context can't figure out. created oscillator , recorded output can't extend sequencer.

here main js code in trying record output. i'm hoping see missing.

//audio node variables var context; var convolver; var compressor; var mastergainnode; var effectlevelnode; var lowpassfilternode;  var notetime; var starttime; var lastdrawtime = -1; var loop_length = 16; var rhythmindex = 0; var timeoutid; var testbuffer = null;  var currentkit = null; var reverbimpulseresponse = null;  var tempo = 120; var tempo_max = 200; var tempo_min = 40; var tempo_step = 4;  if (window.hasownproperty('audiocontext') &&     !window.hasownproperty('webkitaudiocontext')) { window.webkitaudiocontext = audiocontext; }  $(function() { init(); toggleselectedlistener(); playpauselistener(); lowpassfilterlistener(); reverblistener(); createlowpassfiltersliders(); initializetempo(); changetempolistener(); });  function createlowpassfiltersliders() { $("#freq-slider").slider({ value: 1, min: 0, max: 1, step: 0.01, disabled: true, slide: changefrequency }); $("#quality-slider").slider({ value: 0, min: 0, max: 1, step: 0.01, disabled: true, slide: changequality }); }  function lowpassfilterlistener() { $('#lpf').click(function() { $(this).toggleclass("active"); $(this).blur(); if ($(this).hasclass("btn-default")) {   $(this).removeclass("btn-default");   $(this).addclass("btn-warning");   lowpassfilternode.active = true;   $("#freq-slider,#quality-slider").slider( "option", "disabled", false       );   }   else {   $(this).addclass("btn-default");   $(this).removeclass("btn-warning");   lowpassfilternode.active = false;   $("#freq-slider,#quality-slider").slider( "option", "disabled", true   );   }   })   }    function reverblistener() {   $("#reverb").click(function() {   $(this).toggleclass("active");   $(this).blur();   if ($(this).hasclass("btn-default")) {   $(this).removeclass("btn-default");   $(this).addclass("btn-warning");   convolver.active = true;   }   else {   $(this).addclass("btn-default");   $(this).removeclass("btn-warning");   convolver.active = false;   }   })   }  function changefrequency(event, ui) { var minvalue = 40; var maxvalue = context.samplerate / 2; var numberofoctaves = math.log(maxvalue / minvalue) / math.ln2; var multiplier = math.pow(2, numberofoctaves * (ui.value - 1.0)); lowpassfilternode.frequency.value = maxvalue * multiplier;  }  function changequality(event, ui) { //30 quality multiplier, now.  lowpassfilternode.q.value = ui.value * 30; }  function playpauselistener() { $('#play-pause').click(function() { var $span = $(this).children("span"); if($span.hasclass('glyphicon-play')) {   $span.removeclass('glyphicon-play');   $span.addclass('glyphicon-pause');   handleplay(); }  else {   $span.addclass('glyphicon-play');   $span.removeclass('glyphicon-pause');   handlestop();   }  });  }   function toggleselectedlistener() {  $('.pad').click(function() {  $(this).toggleclass("selected");  });  }  function init() { initializeaudionodes(); loadkits(); loadimpulseresponses(); }  function initializeaudionodes() { context = new webkitaudiocontext(); var finalmixnode; if (context.createdynamicscompressor) {   // create dynamics compressor sweeten overall mix.   compressor = context.createdynamicscompressor();   compressor.connect(context.destination);   finalmixnode = compressor;    } else {   // no compressor available in implementation.   finalmixnode = context.destination;   }    // create master volume.  // now, master volume static, in future there    slider  mastergainnode = context.creategain();  mastergainnode.gain.value = 0.7; // reduce overall volume avoid    clipping  mastergainnode.connect(finalmixnode);   //connect sounds mastergainnode play them  //don't need now, no wet dry mix effects // // create effect volume. // effectlevelnode = context.creategain(); // effectlevelnode.gain.value = 1.0; // effect level slider controls // effectlevelnode.connect(mastergainnode);  // create convolver effect convolver = context.createconvolver(); convolver.active = false; // convolver.connect(effectlevelnode);  //create low pass filter lowpassfilternode = context.createbiquadfilter(); //this backwards compatibility, type used integer lowpassfilternode.type = (typeof lowpassfilternode.type === 'string') ?     'lowpass' : 0; // lowpass //default value max cutoff, or passing frequencies lowpassfilternode.frequency.value = context.samplerate / 2; lowpassfilternode.connect(mastergainnode); lowpassfilternode.active = false; }  function loadkits() { //name must same path var kit = new kit("tr808"); kit.load();  //todo: figure out how test if kit loaded currentkit = kit; }  function loadimpulseresponses() { reverbimpulseresponse = new impulseresponse("sounds/impulse-  responses/matrix-reverb2.wav");  reverbimpulseresponse.load(); }   //todo delete function loadtestbuffer() { var request = new xmlhttprequest(); var url = "http://www.freesound.org/data/previews/102/102130_1721044-lq.mp3"; request.open("get", url, true); request.responsetype = "arraybuffer";  request.onload = function() { context.decodeaudiodata(   request.response,   function(buffer) {      testbuffer = buffer;   },   function(buffer) {     console.log("error decoding drum samples!");   } ); } request.send(); }  //todo delete function sequencepads() { $('.pad.selected').each(function() { $('.pad').removeclass("selected"); $(this).addclass("selected"); }); }  function playnote(buffer, notetime) { var voice = context.createbuffersource(); voice.buffer = buffer;  var currentlastnode = mastergainnode; if (lowpassfilternode.active) { lowpassfilternode.connect(currentlastnode); currentlastnode = lowpassfilternode; } if (convolver.active) { convolver.buffer = reverbimpulseresponse.buffer; convolver.connect(currentlastnode); currentlastnode = convolver; }  voice.connect(currentlastnode); voice.start(notetime); }  function schedule() { var currenttime = context.currenttime;  // sequence starts @ starttime, normalize currenttime it's 0 @ start of sequence. currenttime -= starttime;  while (notetime < currenttime + 0.200) {   var contextplaytime = notetime + starttime;   var $currentpads = $(".column_" + rhythmindex);   $currentpads.each(function() {     if ($(this).hasclass("selected")) {       var instrumentname = $(this).parents().data("instrument");       switch (instrumentname) {       case "kick":         playnote(currentkit.kickbuffer, contextplaytime);         break;       case "snare":         playnote(currentkit.snarebuffer, contextplaytime);         break;       case "hihat":         playnote(currentkit.hihatbuffer, contextplaytime);         break;       case "tomhi":         playnote(currentkit.tomhibuffer, contextplaytime);         break;       case "tommid":         playnote(currentkit.tommidbuffer, contextplaytime);         break;         case "tomlow":         playnote(currentkit.tomlowbuffer, contextplaytime);         break;         case "cl":         playnote(currentkit.clbuffer, contextplaytime);         break;        case "cb":         playnote(currentkit.cbbuffer, contextplaytime);         break;        case "cp":         playnote(currentkit.cpbuffer, contextplaytime);         break;       case "cy":         playnote(currentkit.cybuffer, contextplaytime);         break;     case "rs":         playnote(currentkit.rsbuffer, contextplaytime);         break;        }       //play buffer       //store data element in row tells instrument     }   });   if (notetime != lastdrawtime) {       lastdrawtime = notetime;       drawplayhead(rhythmindex);   }   advancenote();   }    timeoutid = requestanimationframe(schedule)   }    function drawplayhead(xindex) {   var lastindex = (xindex + loop_length - 1) % loop_length;    //can change class selector select column   var $newrows = $('.column_' + xindex);   var $oldrows = $('.column_' + lastindex);    $newrows.addclass("playing");   $oldrows.removeclass("playing");   }    function advancenote() {   // advance time 16th note...   // var secondsperbeat = 60.0 / thebeat.tempo;  //todo change tempo here, convert float  tempo = number($("#tempo-input").val());  var secondsperbeat = 60.0 / tempo;  rhythmindex++;  if (rhythmindex == loop_length) {      rhythmindex = 0;  }  //0.25 because each square 16th note notetime += 0.25 * secondsperbeat // if (rhythmindex % 2) { //     notetime += (0.25 + kmaxswing * thebeat.swingfactor) * secondsperbeat; // } else { //     notetime += (0.25 - kmaxswing * thebeat.swingfactor) * secondsperbeat; // }  }  function handleplay(event) { rhythmindex = 0; notetime = 0.0; starttime = context.currenttime + 0.005; schedule(); }  function handlestop(event) { cancelanimationframe(timeoutid); $(".pad").removeclass("playing"); }  function initializetempo() { $("#tempo-input").val(tempo); }  function changetempolistener() { $("#increase-tempo").click(function() { if (tempo < tempo_max) {   tempo += tempo_step;   $("#tempo-input").val(tempo); } });  $("#decrease-tempo").click(function() { if (tempo > tempo_min) {   tempo -= tempo_step;   $("#tempo-input").val(tempo); }  }); }    function __log(e, data) { log.innerhtml += "\n" + e + " " + (data || '');  }   var audio_context;  var recorder;   function startusermedia() {  var input = finalmixnode;  __log('media stream created.');  input.start();  __log('input connected audio context destination.');   recorder = new recorder(input);  __log('recorder initialised.');  }   function startrecording(button) {  recorder && recorder.record();  button.disabled = true;  button.nextelementsibling.disabled = false;  __log('recording...');  }     function stoprecording(button) {   recorder && recorder.stop();   button.disabled = true;   button.previouselementsibling.disabled = false;   __log('stopped recording.');    // create wav download link using audio data blob   createdownloadlink();  recorder.clear();  }   function createdownloadlink() {  recorder && recorder.exportwav(function(blob) {   var url = url.createobjecturl(blob);   var li = document.createelement('li');   var au = document.createelement('audio');   var hf = document.createelement('a');    au.controls = true;   au.src = url;   hf.href = url;   hf.download = new date().toisostring() + '.wav';   hf.innerhtml = hf.download;   li.appendchild(au);   li.appendchild(hf);   recordingslist.appendchild(li); }); }  window.onload = function init() { try {   // webkit shim  window.audiocontext = window.audiocontext ||   window.webkitaudiocontext;   navigator.getusermedia = navigator.getusermedia ||   navigator.webkitgetusermedia;   window.url = window.url || window.webkiturl;   // audio_context = new audiocontext;   __log('audio context set up.'); } catch (e) {   alert('no web audio support in browser!'); }  startusermedia();  }; 

your finalmixnode scoped initializeaudionodes() function, therefore undefined when call startusermedia().

also, variable either dynamiccompressor node or audiocontext's destination.
recorderjs needs node output (which audiodestinationnode doesn't have currently1 ) make sure construct recorder final compressor node (or final gainnode)

executing in js console page work :
var recorder = new recorder(compressor);

1 @padenot noticing me it's being discussed here


Comments

Popular posts from this blog

c# - Validate object ID from GET to POST -

node.js - Custom Model Validator SailsJS -

php - Find a regex to take part of Email -