2015-07-13 7 views
0

У меня возникла проблема с преобразованием данных микрофона в 16-разрядное целое число со знаком PCM.Сэмплирование данных микрофона

приложение я имею в Adobe AIR с помощью ActionScript 3, но у меня есть служба демо-код, который используется Web Audio API и там говорится:

/** 
* Creates a Blob type: 'audio/l16' with the 
* chunk coming from the microphone. 
*/ 
var exportDataBuffer = function(buffer, bufferSize) { 
    var pcmEncodedBuffer = null, 
    dataView = null, 
    index = 0, 
    volume = 0x7FFF; //range from 0 to 0x7FFF to control the volume 

    pcmEncodedBuffer = new ArrayBuffer(bufferSize * 2); 
    dataView = new DataView(pcmEncodedBuffer); 

    /* Explanation for the math: The raw values captured from the Web Audio API are 
    * in 32-bit Floating Point, between -1 and 1 (per the specification). 
    * The values for 16-bit PCM range between -32768 and +32767 (16-bit signed integer). 
    * Multiply to control the volume of the output. We store in little endian. 
    */ 
    for (var i = 0; i < buffer.length; i++) { 
    dataView.setInt16(index, buffer[i] * volume, true); 
    index += 2; 
    } 

    // l16 is the MIME type for 16-bit PCM 
    return new Blob([dataView], { type: 'audio/l16' }); 
}; 

Мне нужен способ, чтобы преобразовать мои образцы в так же.

Это то, что я имею, но не кажется, что это будет работать:

function micSampleDataHandler(event:SampleDataEvent):void 
    { 

     while(event.data.bytesAvailable) 
     { 
      var sample:Number = event.data.readFloat(); 
      var integer:int; 
      sample = sample * 32768 ; 
      if(sample > 32767) sample = 32767; 
      if(sample < -32768) sample = -32768; 
      integer = int(sample) ; 
      soundBytes.writeInt(integer); 
     } 

    } 

Любой совет поможет мне кучу, спасибо

EDIT:

Это функция WaveEncoder у меня есть. Может ли это быть использовано для кодирования образцов в нужный формат:

public function encode(samples:ByteArray, channels:int=2, bits:int=16, rate:int=44100):ByteArray 
     { 
      var data:ByteArray = create(samples); 

      _bytes.length = 0; 
      _bytes.endian = Endian.LITTLE_ENDIAN; 

      _bytes.writeUTFBytes(WaveEncoder.RIFF); 
      _bytes.writeInt(uint(data.length + 44)); 
      _bytes.writeUTFBytes(WaveEncoder.WAVE); 
      _bytes.writeUTFBytes(WaveEncoder.FMT); 
      _bytes.writeInt(uint(16)); 
      _bytes.writeShort(uint(1)); 
      _bytes.writeShort(channels); 
      _bytes.writeInt(rate); 
      _bytes.writeInt(uint(rate * channels * (bits >> 3))); 
      _bytes.writeShort(uint(channels * (bits >> 3))); 
      _bytes.writeShort(bits); 
      _bytes.writeUTFBytes(WaveEncoder.DATA); 
      _bytes.writeInt(data.length); 
      _bytes.writeBytes(data); 
      _bytes.position = 0; 

      return _bytes; 
     } 

EDIT2:

Проблема, кажется, в: dataview.setInt16 (byteOffset, значение [, LittleEndian])

Как я сделать byteOffset в as3?

+0

Проверьте, если вы пишете двухканальный WAV вместо одноканального. Если да, напишите это int дважды, по одному для каждого канала. Также проверьте значения, считанные из bytearray sane (скажем, двухбайтное смещение при чтении поплавков приведет к смехотворным значениям, а 'readFloat()' не поймает это для вас). – Vesper

+0

Мне нужен результат, чтобы быть 1 каналом. Я проверил readFloat(), он всегда возвращает значение между -1 и 1 :( – deloki

ответ

0

Got it. writeInt() записывает 32 бита, и вам нужно писать только 16. Вместо этого используйте writeShort().

soundBytes.writeShort(integer); 
+0

спасибо, это определенно то, что мне нужно использовать вместо или writeInt, но оно пока не работает. Что-то все еще кажется отсутствующим – deloki

+0

Возможно, есть ошибка в настройке заголовка для 'soundBytes'. – Vesper

+0

не могли бы вы дать мне дополнительную информацию об этом? Что именно вы имеете в виду? Я не думаю, что я устанавливаю заголовки где-нибудь – deloki