http://www.adobe.com/cn/devnet/air/flex/articles/using_mic_api.html
要求
必备知识
本文面向可以使用 ActionScript 3 并且基本理解 ByteArrays 的开发人员。
用户级别
中级
必需产品
范例文件
- audio_sampler.zip (5 KB)
- dtmf_sampler.zip (11 KB)
设置和使用麦克风
到 Adobe AIR 2 发行版为止,就和 Flash 10 及更低版本一样,开发人员无法直接访问来自用户麦克风的任何数据。要访问这些数据,只能通过将 AIR 运行时或 Flash Player 连接到远程服务器(如 Adobe Flash Media Server),即可将麦克风数据发送给它们。AIR 2 引入了 SampleDataEvent.SAMPLE_DATA
事件,使您能访问这些原始数据,从而操作或存储它。例如,您现在可以添加简单的回音效果、音频门或其他声音功能,从而增强来自输入的声音。
您可以根据需要连接数量不限的麦克风(或线路输入)设备。也可以连接到一个已经可以使用NetStream.attachMicrophone()
输出的麦克风,使您能本地存储要发送到服务器的任何数据。返回的原始数据采用单声道(单声)浮点值、未经压缩的 PCM 样本的 ByteArray
格式。
选择麦克风输入
开始从麦克风输入接收数据之前,您需要选择数据来源的输入。要这样做,首先要将新的flash.media.Microphone
类导入您的项目。然后,向最终用户显示一个可用麦克风列表,允许他们选择正确的输入。不同于 Flash Player,AIR 不会显示供用户选择输入的安全对话框;您必须自己完成该操作。names
属性中的 Microphone
单例提供可用麦克风的列表。这个数组包含操作系统返回的输入源的名称(作为字符串)。您需要知道用户从该数组中选择的麦克风的索引编号。系统的默认麦克风索引为 0。
<mx:Script> <![CDATA[ import flash.media.Microphone; [Bindable] private var microphoneList:Array; public function setupMicrophoneList():void { microphoneList = Microphone.names; } ]]> </mx:Script> <mx:ComboBox id="comboMicList" dataProvider="{microphoneList}" />
设置麦克风实例
确定用户要使用哪个麦克风后,您需要实例化一个新的 Microphone
对象。将您的麦克风实例设置为一份Microphone
单例的 getMicrophone()
函数,传入选定麦克风的索引(如以下代码片段所示)。选择一个麦克风并实例化对象后,该对象将大量生产包含原始 PCM 数据的 SampleDataEvent.SAMPLE_DATA
事件。要开始接收麦克风事件,您需要将一个事件处理函数附加到 SAMPLE_DATA
事件。要停止接收麦克风事件,您需要删除该事件处理函数。
<mx:Script> <![CDATA[ import flash.events.SampleDataEvent; import flash.media.Microphone; [Bindable] private var microphoneList:Array; protected var microphone:Microphone; protected var isRecording:Boolean = false; protected function setupMicrophoneList():void { microphoneList = Microphone.names; } protected function setupMicrophone():void { microphone = Microphone.getMicrophone(comboMicList.selectedIndex); } protected function startMicRecording():void { isRecording = true; microphone.addEventListener(SampleDataEvent.SAMPLE_DATA, gotMicData); } protected function stopMicRecording():void { isRecording = false; microphone.removeEventListener(SampleDataEvent.SAMPLE_DATA, gotMicData); } private function gotMicData(micData:SampleDataEvent):void { // micData.data contains a ByteArray with our sample. } ]]> </mx:Script> <mx:ComboBox id="comboMicList" dataProvider="{microphoneList}"/> <mx:Button label="Start Rec" click="startMicRecording()"/> <mx:Button label="Stop Rec" click="stopMicRecording()"/> <mx:Button label="Select Mic" click="setupMicrophone()"/>
对采样数据稍作处理
拥有活动数据可以触发的事件后,您很可能希望对它稍作处理。要完成第一个示例,您只需回放记录的声音。将以下代码添加到现有项目中,并且不要忘记添加一个调用 playbackData()
函数的按钮。
import flash.media.Sound; import flash.utils.ByteArray; protected var soundRecording:ByteArray; protected var soundOutput:Sound; protected function playbackData():void { soundRecording.position = 0; soundOutput = new Sound(); soundOutput.addEventListener(SampleDataEvent.SAMPLE_DATA, playSound); soundOutput.play(); } private function playSound(soundOutput:SampleDataEvent):void { if (!soundRecording.bytesAvailable > 0) return; for (var i:int = 0; i < 8192; i++) { var sample:Number = 0; if (soundRecording.bytesAvailable > 0) sample = soundRecording.readFloat(); soundOutput.data.writeFloat(sample); soundOutput.data.writeFloat(sample); } }
除了回放音频,您还可以将原始数据封装到一个可存储到用户的硬盘驱动器的 WAV 文件。借助范例下载中包含的 WAVWriter 类,您可以将记录代码转换为特定比特率,并将数据与适当的头封装在一起写入磁盘。由于 WAV 文件只是前端带有头的 PCM 数据的 ByteArray 流,可以很方便地获得原始数据并创建这些文件。要将 WAV 文件保存在您的应用程序中,请导入 com.adobe.audio.format.WAVWriter 类并添加以下函数:
protected function saveFile():void { var outputFile:File = File.desktopDirectory.resolvePath("recording.wav"); var outputStream:FileStream = new FileStream(); var wavWriter:WAVWriter = new WAVWriter(); soundRecording.position = 0; // rewind to the beginning of the sample wavWriter.numOfChannels = 1; // set the inital properties of the Wave Writer wavWriter.sampleBitRate = 16; wavWriter.samplingRate = 44100; wavWriter.processSamples(outputStream, soundRecording, 44100, 1); // convert our ByteArray to a WAV file. outputStream.open(outputFile, FileMode.WRITE); //write out our file to disk. outputStream.close(); }
设置麦克风属性
Microphone 对象提供许多属性,帮助您控制从它那里获得的数据的质量和类型。例如,您可以设置驱动器级设置,如麦克风增益、静默级别和比率。如果您熟悉 Adobe Connect,可以通过“音频向导”配置所有这些设置,还可以通过微调为用户提供更多麦克风环境控制。可以通过麦克风实例完成所有这些设置。
您可能还希望允许用户将麦克风静音。(如果这样做,SampleDataEvent
将只发回充满零的 ByteArrays
。)可以通过 rate
属性配置质量设置,它决定了麦克风每秒传回给您的样本数量。添加事件监听器后不应更改这些属性中的任何一个,否则 ByteArray 中可能出现不匹配的数据。
对数据稍作处理
您对已记录数据的操作不受限制。许多开发人员发现自己要显示一个音量计或是针对目前记录或显示的数据的色谱分析器。例如,您可以使用 SoundMixer.ComputeSpectrum
计算显示色谱分析器或当前音频正弦波所需的值。但是请注意,ComputeSpectrum 类只适用于当前通过 Flash Player 主混音器向最终用户播放的音频。记住,如果您获得流的浮点值,它们将波形表示为 -1 到 1 的整数(可用于制作音频波图表)。
构建 DTMF 解析程序
将音频记录到 ByteArray 后,您可以取出音频的表示法并对它搜索模式。电话中常见的 DTMF 音调是一组嵌入声音记录中的正弦波。DTMF 音调由两个不同频率的正弦波组成,它们叠加在一起发出我们所知的按键杂声。
在以下示例中,您将启用默认麦克风并将一点数据记录到 ByteArray。然后将这个 ByteArray 传递给将尝试找到各个有效音调的函数。如果它找到两个音调的组合,就可以知道推送的编号。
要开始和停止麦克风记录,执行以下代码:
private function startMicRecording():void { micRecording = new ByteArray(); myMicrophone = Microphone.getMicrophone(); myMicrophone.rate = 44; myMicrophone.setLoopBack(enableLoopback); myMicrophone.addEventListener(SampleDataEvent.SAMPLE_DATA, gotMicData); } private function stopMicRecording():void { myMicrophone.removeEventListener(SampleDataEvent.SAMPLE_DATA, gotMicData); }
借助 gotMicData
事件,您将从 SAMPLE_DATA
事件接收到的数据传递给解析函数。
private function gotMicData(e:SampleDataEvent):void { var udioChunk:ByteArray = new ByteArray(); audioChunk.writeBytes(e.data); myDisplay.text = myDisplay.text + myDTMF.searchDTMF(audioChunk); }
searchDTMF
函数使用称为 Goertzel 的算法解析音频,确定特定音调是否存在。您将获得每个音调的强度并对它们分级。将查找最强的音调并指定它们的 DTMF 值。
运行该示例时,开始麦克风记录。将一个电话(或手机)放在麦克风旁,并按下键盘上的某个数字。myDisplay TextInput
中应当会显示您按下的键代表的数字。否则,可使用应用程序底部的滑块调节分贝敏感度。
后续工作
本文涵盖 AIR 2 中新增的 SampleDataEvent.SAMPLE_DATA
功能。我说明了如何启用麦克风、记录和操作结果。
- 针对
getMicrophone
功能的 Flash Platform 上的 ActionScript 3 参考 - Goertzel 算法
- AIR 开发人员中心上的麦克风范例应用程序和代码