Создайте звуковой сигнал с помощью аудио API Mozilla - PullRequest
2 голосов
/ 10 сентября 2011

Я исследую использование тонального генератора аудио API Mozilla:

  function AudioDataDestination(sampleRate, readFn) {
    // Initialize the audio output.
    var audio = new Audio();
    audio.mozSetup(1, sampleRate);

    var currentWritePosition = 0;
    var prebufferSize = sampleRate / 2; // buffer 500ms
    var tail = null, tailPosition;

    // The function called with regular interval to populate 
    // the audio output buffer.
    setInterval(function() {
      var written;
      // Check if some data was not written in previous attempts.
      if(tail) {
        written = audio.mozWriteAudio(tail.subarray(tailPosition));
        currentWritePosition += written;
        tailPosition += written;
        if(tailPosition < tail.length) {
          // Not all the data was written, saving the tail...
          return; // ... and exit the function.
        }
        tail = null;
      }

      // Check if we need add some data to the audio output.
      var currentPosition = audio.mozCurrentSampleOffset();
      var available = currentPosition + prebufferSize - currentWritePosition;
      if(available > 0) {
        // Request some sound data from the callback function.
        var soundData = new Float32Array(available);
        readFn(soundData);

        // Writting the data.
        written = audio.mozWriteAudio(soundData);
        if(written < soundData.length) {
          // Not all the data was written, saving the tail.
          tail = soundData;
          tailPosition = written;
        }
        currentWritePosition += written;
      }
    }, 100);
  }

  // Control and generate the sound.

  var frequency = 0, currentSoundSample;
  var sampleRate = 44100;

  function requestSoundData(soundData) {
    if (!frequency) { 
      return; // no sound selected
    }

    var k = 2* Math.PI * frequency / sampleRate;
    for (var i=0, size=soundData.length; i<size; i++) {
      soundData[i] = Math.sin(k * currentSoundSample++);
    }        
  }

  var audioDestination = new AudioDataDestination(sampleRate, requestSoundData);

  function start() {
    currentSoundSample = 0;
    frequency = parseFloat(document.getElementById("freq").value);
  }

  function stop() {
    frequency = 0;
  }

Я бы хотел, чтобы этот тон был включен в течение 500 мс, затем выключен в течение 500 мс, а затем повторяться, пока не будет нажата кнопка остановки.Я думал, что смогу просто сделать это, установив номера выборок от 22 050 до 44 100 на ноль.Однако этот метод, похоже, не работает.Я думаю, это потому, что функция повторного заполнения буфера происходит каждые 100 мс, но теперь это за пределами моих знаний.Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 12 сентября 2011

На самом деле, мне кажется, это работает нормально.Я изменил цикл в вашей requestSoundData функции следующим образом:

for (var i=0, size=soundData.length; i<size; i++) {
  if (currentSoundSample % 44100 < 22050)
    soundData[i] = Math.sin(k * currentSoundSample);
  else
    soundData[i] = 0;
  currentSoundSample++;
}

Сэмплы с 22 050 по 44 100 установлены на ноль, и это, кажется, дает именно тот эффект, который вы хотели.Здесь вы можете попробовать код: http://jsfiddle.net/95jCt/

...