在Flash Builder 4 beta中使用Pixel Bender作为数值运算引擎 (五)
混合音频文件
下一个例子可能更有实用价值,我们将要编写一个能够将两个音频文件混合为一个音频文件的音频混合器。
用来混合音频的kernel
该kernel利用了 mix(x, y, a) 函数,该函数返回对x和y进行线性插值(即x*(1.0-a)+y*a)后的结果。
下面是该kernel的代码:
<languageVersion : 1.0;> kernel sound < namespace : "elad"; vendor : "Elad Elrom"; version : 1; description : "track mixer"; > { input image4 src0; input image4 src1; output float4 dst; parameter float distort < minValue:float(0); maxValue:float(1.0); defaultValue:float(1.0); >; void evaluatePixel() { float4 s1 = sampleNearest(src0,outCoord()); float4 s2 = sampleNearest(src1,outCoord()); dst = mix(s1,s2,distort); } }
注意到该程序中有一个参数, distort,他是用来调节两个音轨的混合程度的(即上面公式中的a)。
用来混合音频的API
你可以从Google code下载TrackMixer类,它提供了用以混合两个音频文件的API,可以利用它直接混合两个音频文件。
这个类相对来说比较简单,首先是定义将要用到的变量:
// pixel bender class and shader private var shader:Shader; private var shaderJob:ShaderJob; // num of tracks // counter // buffer & sound objects private var buffer:Vector.<ByteArray> = new Vector.<ByteArray>; private var sound:Vector.<Sound> = new Vector.<Sound>;
start() 方法载入将要被混合的两个音频文件。
{ if (urls.length >2) { this.dispatchErrorEvent( "API only supports two tracks at this point." ); } numOfTracks = urls.length; { } }
在载入音轨之后,下一步就是设定ShaderJob及其参数,随后启动ShaderJob.
private function onSampleDataHandler(event:SampleDataEvent):void { var height:Vector.<int> = new Vector.<int>(numOfTracks); { sound[i].extract(buffer[i],BUFFER_SIZE * 4); height[i] = buffer[i].length >> 4; buffer[i].position = 0; shader.data["src"+i]["input"] = buffer[i]; shader.data["src"+i]["width"] = width; shader.data["src"+i]["height"] = height[i]; } shader.data.distort.value = [this.balance]; shaderJob = new ShaderJob(shader, event.data,width, height[0]); shaderJob.start(true); }
混合音频的应用程序
下一步就是创建一个利用了混合音频API的应用程序(见图6)

图6 音频混合应用程序
该程序同样嵌入了对应的Pixel Bender kernel并将其作为参数传入TrackMixer。然后启动TrackMixer,同时传入两个音频的URL。当滑块移动的时候,程序会调节混合器的平衡。全部代码如下:
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" xmlns:local="*" minWidth="1024" minHeight="768" creationComplete="creationCompleteHandler(event)"> <fx:Script> <![CDATA[ import com.elad.framework.sound.events.TrackMixerErrorEvent; import com.elad.framework.sound.TrackMixer; import mx.events.FlexEvent; [Embed("assets/pbj/TwoTracksMixer.pbj", mimeType="application/octet-stream")] private var trackMixer:TrackMixer; protected function creationCompleteHandler(event:FlexEvent):void { trackMixer = new TrackMixer(Kernel); trackMixer.addEventListener(TrackMixerErrorEvent.TRACK_MIXER_ERROR, function(e:*):void { trace(e.message); } ); trackMixer.start( ["assets/tracks/FeelinGood.mp3", "assets/tracks/Sunshine.mp3"] ); } { trackMixer.balance = event.currentTarget.value ; } ]]> </fx:Script> <mx:Slider x="28" y="171" id="balanceSlider" labels='["Track1","Mix","Track2"]' minimum="0" maximum="1" liveDragging="true" value="0.5" change="balanceSliderChangeHandler(event)" /> <local:Visualization type="wave" bars="32" width="300" height="137" x="28" y="14"/> </s:Application>

.gif)
.gif)




.gif)
发表新评论