Im having a issue with converting microphone data sampling to 16-bit PCM signed integer.
The app i have is in Adobe AIR with actionScript 3, but i have the service demo code which used Web Audio API and there it states:
/**
* 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' });
};
I need a way to convert my samples in the same way.
This is what i have but it doesn't seem to be working:
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);
}
}
Any advice would help me a bunch, thanks
EDIT:
This is the WaveEncoder function i have. Can this be used to encode the samples into desired format :
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:
Problem seems to be in : dataview.setInt16(byteOffset, value [, littleEndian])
How do i do the byteOffset in as3?
Got it. writeInt()
writes 32 bits, and you need to write only 16. Use writeShort()
instead.
soundBytes.writeShort(integer);