2015-09-29 32 views
0

我一直在與MIDI教程搞亂並觸發示例。但是我不知道如何去除代碼中樣本的隨機變化。任何想法如何消除音高變化?Audio Midi API-如何從音頻樣本中移除音高變化?

連結教程:http://www.keithmcmillen.com/blog/making-music-in-the-browser-web-midi-api/

<html> 
<head> 
    <meta charset="UTF-8"> 
    <title>Web MIDI API</title> 
    <style> 
    *:before, *:after { 
     -webkit-box-sizing: border-box; 
     -moz-box-sizing: border-box; 
     box-sizing: border-box; 
    } 
    h4 { 
     margin: 0 0 5px 0; 
    } 
    p { 
     margin: 0 0 10px 0; 
    } 
    #content, #device_info { 
     max-width: 800px; 
     margin: 0 auto; 
     padding: 10px 0; 
     font-family: sans-serif; 
     font-size: 12px; 
     line-height: 12px; 
     letter-spacing: 1.5px; 
    } 
    #content, #key_data { 
     margin-top: 0px; 
     text-align: center; 
    } 
    #inputs, #outputs { 
     display: inline-block; 
     width: 49%; 
     margin-top: 10px; 
     vertical-align: top; 
    } 
    #outputs { 
     text-align: right; 
    } 
    .info { 
     padding: 20px; 
     border-radius: 3px; 
     box-shadow: inset 0 0 10px #ccc; 
     background-color: rgba(233,233,233,0.25); 
    } 
    .small { 
     border-bottom: 1px solid #ccc; 
     margin-left: 10px; 
    } 
    p:not(.small){ 
     text-transform: uppercase; 
     font-weight: 800; 
    } 
    .button { 
     display: inline-block; 
     width: 100px; 
     height: 100px; 
     margin: 10px; 
     background-color: #00adef; 
     border-radius: 10px; 
     opacity: 1; 
     cursor: pointer; 
     border: 2px solid white; 
     transition: all 0.2s; 
    } 
    .button.active { 
     background-color: #9a6aad; 
     opacity: 0.25; 
     box-shadow: inset 0px 0px 30px orange; 
     border: 2px solid rgba(100,100,100,0.3); 
     animation: shake .2s ease-in-out; 
    } 
    @keyframes shake { 
     0% { 
      transform: translateX(0); 
      transform: translateY(0); 
      transform: scale(1,1); 
     } 
     20% { 
      transform: translateX(-10px); 
      transform: translateY(-100px); 
      transform: scale(0.5,0.75); 
     } 
     40% { 
      transform: translateX(10px); 
      transform: translateY(0px); 
      transform: scale(1.5,2); 
     } 
     60% { 
      transform: translateX(-10px); 
      transform: translateY(-50px); 
      transform: scale(0.5,0.75); 
     } 
     80% { 
      transform: translateX(10px); 
      transform: translateY(50px); 
      transform: scale(1.3,2); 
     } 
     100% { 
      transform: translateX(0); 
      transform: translateY(0); 
     } 
    } 
    </style> 
</head> 
<body> 
    <div id="content"> 
     <div class="button" data-key="q" data-sound="audio/Slice1.mp3"></div> 
     <div class="button" data-key="w" data-sound="audio/dinky-snare.mp3"></div> 
     <div class="button" data-key="e" data-sound="audio/dinky-hat-2.mp3"></div> 
     <div class="button" data-key="r" data-sound="audio/dinky-cym.mp3"></div> 
     <div class="button" data-key="t" data-sound="audio/dinky-cym-noise.mp3"></div> 
    </div> 
    <div id="device_info"> 
     <div id="key_data"></div> 
     <div id="inputs"></div> 
     <div id="outputs"></div> 
    </div> 

    <script> 
    //http://stackoverflow.com/questions/23687635/how-to-stop-audio-in-an-iframe-using-web-audio-api-after-hiding-its-container-di 
    (function(){ 
     var log = console.log.bind(console), keyData = document.getElementById('key_data'), 
       deviceInfoInputs = document.getElementById('inputs'), deviceInfoOutputs = document.getElementById('outputs'), midi; 
     var AudioContext = AudioContext || webkitAudioContext; // for ios/safari 
     var context = new AudioContext(); 
     var activeNotes = []; 
     var btnBox = document.getElementById('content'), btn = document.getElementsByClassName('button'); 
     var data, cmd, channel, type, note, velocity; 

     // request MIDI access 
     if(navigator.requestMIDIAccess){ 
      navigator.requestMIDIAccess({sysex: false}).then(onMIDISuccess, onMIDIFailure); 
     } 
     else { 
      alert("No MIDI support in your browser."); 
     } 

     // add event listeners 
     document.addEventListener('keydown', keyController); 
     document.addEventListener('keyup', keyController); 
     for(var i = 0; i < btn.length; i++){ 
      btn[i].addEventListener('mousedown', clickPlayOn); 
      btn[i].addEventListener('mouseup', clickPlayOff); 
     } 
     // prepare audio files 
     for(var i = 0; i < btn.length; i++){ 
      addAudioProperties(btn[i]); 
     } 

     var sampleMap = { 
      key60: 1, 
      key61: 2, 
      key62: 3, 
      key63: 4, 
      key64: 5 
     }; 
     // user interaction 
     function clickPlayOn(e){ 
      e.target.classList.add('active'); 
      e.target.play(); 
     } 

     function clickPlayOff(e){ 
      e.target.classList.remove('active'); 
     } 

     function keyController(e){ 
      if(e.type == "keydown"){ 
       switch(e.keyCode){ 
        case 81: 
         btn[0].classList.add('active'); 
         btn[0].play(); 
         break; 
        case 87: 
         btn[1].classList.add('active'); 
         btn[1].play(); 
         break; 
        case 69: 
         btn[2].classList.add('active'); 
         btn[2].play(); 
         break; 
        case 82: 
         btn[3].classList.add('active'); 
         btn[3].play(); 
         break; 
        case 84: 
         btn[4].classList.add('active'); 
         btn[4].play(); 
         break;     
        default: 
         //console.log(e); 
       } 
      } 
      else if(e.type == "keyup"){ 
       switch(e.keyCode){ 
        case 81: 
         btn[0].classList.remove('active'); 
         break; 
        case 87: 
         btn[1].classList.remove('active'); 
         break; 
        case 69: 
         btn[2].classList.remove('active'); 
         break; 
        case 82: 
         btn[3].classList.remove('active'); 
         break; 
        case 84: 
         btn[4].classList.remove('active'); 
         break; 
        default: 
         //console.log(e.keyCode); 
       } 
      } 
     } 

     // midi functions 
     function onMIDISuccess(midiAccess){ 
      midi = midiAccess; 
      var inputs = midi.inputs.values(); 
      // loop through all inputs 
      for(var input = inputs.next(); input && !input.done; input = inputs.next()){ 
       // listen for midi messages 
       input.value.onmidimessage = onMIDIMessage; 

       listInputs(input); 
      } 
      // listen for connect/disconnect message 
      midi.onstatechange = onStateChange; 

      showMIDIPorts(midi); 
     } 

     function onMIDIMessage(event){ 
      data = event.data, 
      cmd = data[0] >> 4, 
      channel = data[0] & 0xf, 
      type = data[0] & 0xf0, // channel agnostic message type. Thanks, Phil Burk. 
      note = data[1], 
      velocity = data[2]; 
      // with pressure and tilt off 
      // note off: 128, cmd: 8 
      // note on: 144, cmd: 9 
      // pressure/tilt on 
      // pressure: 176, cmd 11: 
      // bend: 224, cmd: 14 
      log('MIDI data', data); 
      switch(type){ 
       case 144: // noteOn message 
        noteOn(note, velocity); 
        break; 
       case 128: // noteOff message 
        noteOff(note, velocity); 
        break; 
      } 

      //log('data', data, 'cmd', cmd, 'channel', channel); 
      logger(keyData, 'key data', data); 
     } 

     function onStateChange(event){ 
      showMIDIPorts(midi); 
      var port = event.port, state = port.state, name = port.name, type = port.type; 
      if(type == "input") 
       log("name", name, "port", port, "state", state); 

     } 

     function listInputs(inputs){ 
      var input = inputs.value; 
       log("Input port : [ type:'" + input.type + "' id: '" + input.id + 
         "' manufacturer: '" + input.manufacturer + "' name: '" + input.name + 
         "' version: '" + input.version + "']"); 
     } 

     function noteOn(midiNote, velocity){ 
      player(midiNote, velocity); 
     } 

     function noteOff(midiNote, velocity){ 
      player(midiNote, velocity); 
     } 

     function player(note, velocity){ 
      var sample = sampleMap['key'+note]; 
      if(sample){ 
       if(type == (0x80 & 0xf0) || velocity == 0){ //needs to be fixed for QuNexus, which always returns 144 
        btn[sample - 1].classList.remove('active'); 
        return; 
       } 
       btn[sample - 1].classList.add('active'); 
       btn[sample - 1].play(velocity); 
      } 
     } 

     function onMIDIFailure(e){ 
      log("No access to MIDI devices or your browser doesn't support WebMIDI API. Please use WebMIDIAPIShim " + e); 
     } 

     // MIDI utility functions 
     function showMIDIPorts(midiAccess){ 
      var inputs = midiAccess.inputs, 
        outputs = midiAccess.outputs, 
        html; 
      html = '<h4>MIDI Inputs:</h4><div class="info">'; 
      inputs.forEach(function(port){ 
       html += '<p>' + port.name + '<p>'; 
       html += '<p class="small">connection: ' + port.connection + '</p>'; 
       html += '<p class="small">state: ' + port.state + '</p>'; 
       html += '<p class="small">manufacturer: ' + port.manufacturer + '</p>'; 
       if(port.version){ 
        html += '<p class="small">version: ' + port.version + '</p>'; 
       } 
      }); 
      deviceInfoInputs.innerHTML = html + '</div>'; 

      html = '<h4>MIDI Outputs:</h4><div class="info">'; 
      outputs.forEach(function(port){ 
       html += '<p>' + port.name + '<br>'; 
       html += '<p class="small">manufacturer: ' + port.manufacturer + '</p>'; 
       if(port.version){ 
        html += '<p class="small">version: ' + port.version + '</p>'; 
       } 
      }); 
      deviceInfoOutputs.innerHTML = html + '</div>'; 
     } 

     // audio functions 
     function loadAudio(object, url){ 
      var request = new XMLHttpRequest(); 
      request.open('GET', url, true); 
      request.responseType = 'arraybuffer'; 
      request.onload = function(){ 
       context.decodeAudioData(request.response, function(buffer){ 
        object.buffer = buffer; 
       }); 
      } 
      request.send(); 
     } 

     function addAudioProperties(object){ 
      object.name = object.id; 
      object.source = object.dataset.sound; 
      loadAudio(object, object.source); 
      object.play = function(volume){ 
       var s = context.createBufferSource(); 
       var g = context.createGain(); 
       var v; 
       s.buffer = object.buffer; 
       s.playbackRate.value = randomRange(0.5, 2); 
       if(volume){ 
        v = rangeMap(volume, 1, 127, 0.2, 2); 
        s.connect(g); 
        g.gain.value = v * v; 
        g.connect(context.destination); 
       } 
       else{ 
        s.connect(context.destination); 
       } 

       s.start(); 
       object.s = s; 
      } 
     } 

     // utility functions 
     function randomRange(min, max){ 
      return Math.random() * (max + min) + min; 
     } 

     function rangeMap(x, a1, a2, b1, b2){ 
      return ((x - a1)/(a2-a1)) * (b2 - b1) + b1; 
     } 

     //function frequencyFromNoteNumber(note) { 
     // return 440 * Math.pow(2,(note-69)/12); 
     //} 

     function logger(container, label, data){ 
      messages = label + " [channel: " + (data[0] & 0xf) + ", cmd: " + (data[0] >> 4) + ", type: " + (data[0] & 0xf0) + " , note: " + data[1] + " , velocity: " + data[2] + "]"; 
      container.textContent = messages; 
     } 

    })(); 
    </script> 
</body> 
</html> 
+1

請不要鏈接到異地代碼。一個SSCCE會改善你的問題[http://sscce.org]。 – marko

回答

0

有一個在addAudioProperties()函數它設置播放速率隨機每次一條線。您可以通過回放速率設置爲1刪除此:

s.playbackRate.value = randomRange(0.5, 2);

成爲

s.playbackRate.value = 1;

+0

謝謝!有效 –

相關問題