访问原始声音数据

通过使用 SoundMixer.computeSpectrum() 方法,应用程序可以读取当前所播放的波形的原始声音数据。如果当前播放多个 SoundChannel 对象, SoundMixer.computeSpectrum() 方法将显示混合在一起的每个 SoundChannel 对象的组合声音数据。

声音数据的返回方式

声音数据是作为 ByteArray 对象(包含 512 个 4 字节数组)返回的,其中的每个字节表示一个介于 -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() 方法来显示定期绘制动画的声音波形图:

代码运行后相同的 3 个圆。“b”与“a”的右边缘重叠。“c”与“a”的右下部重叠,且与“b”的左下部重叠。
<html> 
    <title>Sound Spectrum</title> 
    <script src="AIRAliases.js" /> 
    <script> 
        const PLOT_WIDTH = 600; 
        const CHANNEL_LENGTH = 256; 
         
        var snd = new air.Sound(); 
        var req = new air.URLRequest("test.mp3"); 
        var bytes = new air.ByteArray(); 
        var divStyles = new Array;     
         
        /** 
            * Initializes the application. It draws 256 DIV elements to the document body, 
             * and sets up a divStyles array that contains references to the style objects of  
             * each DIV element. It then calls the playSound() function. 
             */ 
        function init() 
        { 
            var div; 
            for (i = 0; i < CHANNEL_LENGTH; i++) 
            { 
                div = document.createElement("div"); 
                div.style.height = "1px";  
                div.style.width = "0px";  
                div.style.backgroundColor = "blue"; 
                document.body.appendChild(div); 
                divStyles[i] = div.style; 
            } 
            playSound(); 
        } 
        /** 
             * Plays a sound, and calls setInterval() to call the setMeter() function 
             * periodically, to display the sound spectrum data. 
             */ 
        function playSound()  
        { 
            if (snd.url != null) 
            { 
                snd.close(); 
            } 
            snd.load(req);         
            var channel = snd.play(); 
            timer = setInterval(setMeter, 100); 
            snd.addEventListener(air.Event.SOUND_COMPLETE, onPlaybackComplete); 
        } 
         
        /** 
             * Computes the width of each of the 256 colored DIV tags in the document, 
             * based on data returned by the call to SoundMixer.computeSpectrum(). The  
            * first 256 floating point numbers in the byte array represent the data from 
             * the left channel, and then next 256 floating point numbers represent the  
             * data from the right channel. 
             */ 
        function setMeter() 
        { 
            air.SoundMixer.computeSpectrum(bytes, false, 0);         
            var n;             
            for (var i = 0; i < CHANNEL_LENGTH; i++)  
            { 
                bytes.position = i * 4; 
                n = Math.abs(bytes.readFloat()); 
                bytes.position = 256*4 + i * 4; 
                n += Math.abs(bytes.readFloat()); 
                divStyles[i].width = n * PLOT_WIDTH; 
            } 
        } 
        /** 
         * When the sound is done playing, remove the intermediate process  
         * started by setInterval(). 
         */ 
        function onPlaybackComplete(event) 
        { 
            clearInterval(interval); 
        } 
    </script> 
    <body onload="init()"> 
    </body> 
</html>

此示例首先加载并播放声音文件,然后使用 setInterval() 函数监视 SoundMixer.computeSpectrum() 方法,该方法将声音波形数据存储在 bytes ByteArray 对象中。

声音波形是通过设置表示条形图的 div 元素的宽度进行绘制的。