У меня возникла проблема с преобразованием данных микрофона в 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?
Проверьте, если вы пишете двухканальный WAV вместо одноканального. Если да, напишите это int дважды, по одному для каждого канала. Также проверьте значения, считанные из bytearray sane (скажем, двухбайтное смещение при чтении поплавков приведет к смехотворным значениям, а 'readFloat()' не поймает это для вас). – Vesper
Мне нужен результат, чтобы быть 1 каналом. Я проверил readFloat(), он всегда возвращает значение между -1 и 1 :( – deloki