1/5/2011 10:01:04 AM
Title:
Sound Record and Play at 8Khz, Recording is OK but Why it is not Playing
Please refer to the question :
http://askmeflash.com/qdetail/1067/capturing-microphone-and-playing-at-lower-sampling-rate
For our project detail refer to :http://ganeshtiwaridotcomdotnp.blogspot.com/2010/12/text-prompted-remote-speaker.html
<><><><><><><><><><><><><><><><><><><><><><><><>
we were initially planning to record the audio at 22 Khz but later we come to conclusion that processing of 22Khz data will be expensive..... and 8Khz will be enough... only 8000 samples per second of audio signal.
the audio is captured at 8Khz and uploaded to server (file bytearray) by modifying AIR's WavWriter class. the saved .wav file is played correctly. but when we are playing the captured byteArray in Client side it is not played correctly.
here is the code :
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="230" height="95">
<fx:Script>
<![CDATA[
private var mic:Microphone;
public var byteArrayData:ByteArray;
public var pcmArray:Array;
private var snd:Sound;
import mx.core.FlexGlobals;
[Bindable]
private var micNames:Array = Microphone.names;//bind list of microphones to combo box
private var rate:int=8;
protected function recBtn_clickHandler(event:MouseEvent):void{
if (event.currentTarget.selected == true){
byteArrayData=new ByteArray();//byteArray variable to store recorded data
mic = Microphone.getMicrophone(micNamesCombo.selectedIndex);//choose mic from combo list
//set mic properties
mic.setUseEchoSuppression(true);
mic.rate=rate;
mic.setSilenceLevel(0);
//mic.setSilenceLevel(silenceLevel,timeOut);
//set handlers
mic.addEventListener(StatusEvent.STATUS, statusHandler);
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, getMicAudio);
//change components' properties
event.currentTarget.label = "Stop";
ply_Btn.enabled=false;
}
else{
//unset getMicAudio handler
mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, getMicAudio);
event.currentTarget.label = "Record";
ply_Btn.enabled=true;
}
}
protected function statusHandler(event:StatusEvent):void{
//if user denies to open microphone or not available or muted
if (mic == null) {
lblErr.text="Error on accessing microphone";
}
if(mic.muted==true){
lblErr.text="Your Microphone is Muted, unmute it";
}
}
//writes sound data to bytearray
private function getMicAudio(e:SampleDataEvent): void
{
byteArrayData.writeBytes(e.data);
//display byteArray length on label
lblByteCount.text = String(byteArrayData.length);
}
// plays sound
protected function plyBtn_clickHandler(event:MouseEvent):void{
if (event.currentTarget.selected == true){
event.currentTarget.label = "Stop";
byteArrayData.position = 0;//reset byteArray position to start
snd = new Sound();
snd.addEventListener(SampleDataEvent.SAMPLE_DATA, playRecorded);//start playing by invoking SampleDataEvent
var channel:SoundChannel;//to play, create SoundChannel variable
channel=snd.play();
channel.addEventListener(Event.SOUND_COMPLETE, stopPlayback);//when playing is complete
}
else{
event.currentTarget.label = "Play";
snd.close();
}
}
//<<<<<<<<<<<<<<<<<HERE IS THE PROBLEM>>>>>>>>>>>>>>>>>>>>
private function playRecorded(e:SampleDataEvent): void{
if (!byteArrayData.bytesAvailable > 0)//if end; return
return;
for (var i:int = 0; i < 8192/(44/rate); i++){
var sample:Number = 0;
if (byteArrayData.bytesAvailable > 0)
sample = byteArrayData.readFloat();
//write sample, i.e., play
for(var j:int=0; j<int((44.0/rate)*2);j++){//4 for 22 khz?for 8khz
e.data.writeFloat(sample);
}
}
}
//<<<<<<<<<<<<<<<<<WHAT IS THE SOLUTION >>>>>>>>>>>>>>>>>>>>
private function stopPlayback(e:Event): void{
ply_Btn.selected=false;
ply_Btn.label="play";
}
]]>
</fx:Script>
<mx:ComboBox id="micNamesCombo" dataProvider="{micNames}" x="105" y="11" width="115" toolTip="List of Available Microphones on your computer"/>
<s:ToggleButton id="rec_Btn" x="10" y="10" width="80" label="Record" click="recBtn_clickHandler(event);"/>
<s:ToggleButton id="ply_Btn" x="10" y="42" width="80" label="Play" click="plyBtn_clickHandler(event);" enabled="false"/>
<s:Label x="105" y="42" id="lblByteCount" width="116" height="21" fontSize="16"/>
<s:Label x="10" y="70" id="lblErr" width="210" height="20" text="" verticalAlign="middle"/>
</s:Group>
We searched for the solution but could not find. And there was nothing mentioned on Adobe documentation.
Anyway,
Why the code is not working.... what is the actual problem?
Please Help us.
Shawn
Points: 680
Posts:0
1/6/2011 1:02:47 AM
I will recommend you to use the 12khz atleast. 8khz is not supported by many sound cards on many operating systems. 8khz will sound slow and drowsy in some cases. This is my personal experience not documented by adobe since its not there issue but the sound drivers and OS.
1/6/2011 1:05:22 AM
I had faced a similar issue when using live audio with FMS at 8khz. sytems with win 2000 and MAC operating system did not work with 8khz setting. Ultimately we had to use the higher bit rate.
1/6/2011 4:42:52 AM
at 8 khz, the sound was recorded perfectly but it was not playing at all....
and at 11Khz, it played with high pitch.
and finally we decided to use 22Khz..... it is working fine.....
but our concern was just <b>the bigger size of array</b> to process in further steps...
thanks for the reply
1/6/2011 4:47:58 AM
i was initially guessing the problem with float value after calculating
8192/(44/rate)
and
int((44.0/rate)*2)
private function playRecorded(e:SampleDataEvent): void{
if (!byteArrayData.bytesAvailable > 0)//if end; return
return;
for (var i:int = 0; i < 8192/(44/rate); i++){
var sample:Number = 0;
if (byteArrayData.bytesAvailable > 0)
sample = byteArrayData.readFloat();
//write sample, i.e., play
for(var j:int=0; j<int((44.0/rate)*2);j++){//4 for 22 khz?for 8khz
e.data.writeFloat(sample);
}
}
}
8/17/2011 12:01:26 PM
Late response but maybe someone else will come across this as I did.
When you use 8000 samples per second, the playRecorded function isn't calling e.data.writeFloat(sample) enough times. It calls it 16379 times instead of 16834 times ( 8192 * 2 ) like the other rates ( 11025, 22050, 44100 ). If you call e.data.writeFloat( 0 ) for the remaining 455 times then you will have a good Sound object for playback.