访问原始声音数据Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本 通过使用 SoundMixer.computeSpectrum() 方法,应用程序可以读取当前所播放的波形的原始声音数据。如果当前播放多个 SoundChannel 对象,SoundMixer.computeSpectrum() 方法将显示混合在一起的每个 SoundChannel 对象的组合声音数据。 声音数据是作为 ByteArray 对象(包含 512 个字节的数据)返回的,其中的每个字节包含一个介于 -1 和 1 之间的浮点值。这些值表示所播放的声音波形中的点的波幅。这些值是分为两个组(每组包含 256 个值)提供的,第一个组用于左立体声声道,第二个组用于右立体声声道。 如果将 FFTMode 参数设置为 true,SoundMixer.computeSpectrum() 方法将返回频谱数据,而非波形数据。频谱显示按声音频率(从最低频率到最高频率)排列的波幅。可以使用快速傅立叶变换 (FFT) 将波形数据转换为频谱数据。生成的频谱值范围介于 0 和约 1.414(2 的平方根)之间。 下图比较了将 FFTMode 参数设置为 true 和 false 时从 computeSpectrum() 方法返回的数据。此图所用数据的声音在左声道中包含很大的低音;而在右声道中包含击鼓声。
computeSpectrum() 方法也可以返回已在较低比特率重新采样的数据。通常,这会产生更平滑的波形数据或频率数据,但会以牺牲细节为代价。stretchFactor 参数控制 computeSpectrum() 方法数据的采样率。如果将 stretchFactor 参数设置为 0(默认值),则以采样率 44.1 kHz 采集声音数据样本。stretchFactor 参数值每连续增加 1,采样率就减小一半,因此,值 1 指定采样率 22.05 kHz,值 2 指定采样率 11.025 kHz,依此类推。当使用较高的 stretchFactor 值时,computeSpectrum() 方法仍会为每个立体声声道返回 256 个字节。 SoundMixer.computeSpectrum() 方法具有一些限制:
但在 AIR 应用程序中,应用程序安全沙箱中的内容(随 AIR 应用程序安装的内容)不受这些安全限制的约束。 构建简单的声音可视化程序以下示例使用 SoundMixer.computeSpectrum() 方法来显示声音波形图(它对每个帧进行动画处理): import flash.display.Graphics; import flash.events.Event; import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundMixer; import flash.net.URLRequest; const PLOT_HEIGHT:int = 200; const CHANNEL_LENGTH:int = 256; var snd:Sound = new Sound(); var req:URLRequest = new URLRequest("bigSound.mp3"); snd.load(req); var channel:SoundChannel; channel = snd.play(); addEventListener(Event.ENTER_FRAME, onEnterFrame); snd.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete); var bytes:ByteArray = new ByteArray(); function onEnterFrame(event:Event):void { SoundMixer.computeSpectrum(bytes, false, 0); var g:Graphics = this.graphics; g.clear(); g.lineStyle(0, 0x6600CC); g.beginFill(0x6600CC); g.moveTo(0, PLOT_HEIGHT); var n:Number = 0; // left channel for (var i:int = 0; i < CHANNEL_LENGTH; i++) { n = (bytes.readFloat() * PLOT_HEIGHT); g.lineTo(i * 2, PLOT_HEIGHT - n); } g.lineTo(CHANNEL_LENGTH * 2, PLOT_HEIGHT); g.endFill(); // right channel g.lineStyle(0, 0xCC0066); g.beginFill(0xCC0066, 0.5); g.moveTo(CHANNEL_LENGTH * 2, PLOT_HEIGHT); for (i = CHANNEL_LENGTH; i > 0; i--) { n = (bytes.readFloat() * PLOT_HEIGHT); g.lineTo(i * 2, PLOT_HEIGHT - n); } g.lineTo(0, PLOT_HEIGHT); g.endFill(); } function onPlaybackComplete(event:Event) { removeEventListener(Event.ENTER_FRAME, onEnterFrame); } 此示例先加载并播放一个声音文件,然后在播放声音的同时侦听将触发 onEnterFrame() 方法的 Event.ENTER_FRAME 事件。onEnterFrame() 方法先调用 SoundMixer.computeSpectrum() 方法,后者将声音波形数据存储在 bytes ByteArray 对象中。 声音波形是使用矢量绘图 API 绘制的。for 循环将循环访问第一批 256 个数据值(表示左立体声声道),然后使用 Graphics.lineTo() 方法绘制一条从每个点到下一个点的直线。第二个 for 循环将循环访问下一批 256 个值,此时按相反的顺序(从右到左)对它们进行绘制。生成的波形图可能会产生非常有趣的镜像图像效果,如以下图像中所示。 |
|