在Flash Builder 4 beta中使用Pixel Bender作为数值运算引擎 (五)

混合音频文件

下一个例子可能更有实用价值,我们将要编写一个能够将两个音频文件混合为一个音频文件的音频混合器。

用来混合音频的kernel

该kernel利用了 mix(x, y, a) 函数,该函数返回对xy进行线性插值(x*(1.0-a)+y*a)后的结果。

下面是该kernel的代码:

  1. <languageVersion : 1.0;>
  2.  
  3. kernel sound
  4. < namespace : "elad";
  5. vendor : "Elad Elrom";
  6. version : 1;
  7. description : "track mixer";
  8. >
  9. {
  10. input image4 src0;
  11. input image4 src1;
  12.  
  13. output float4 dst;
  14.  
  15. parameter float distort
  16. <
  17. minValue:float(0);
  18. maxValue:float(1.0);
  19. defaultValue:float(1.0);
  20. >;
  21.  
  22. void evaluatePixel()
  23. {
  24. float4 s1 = sampleNearest(src0,outCoord());
  25. float4 s2 = sampleNearest(src1,outCoord());
  26. dst = mix(s1,s2,distort);
  27. }
  28. }
  29.  

注意到该程序中有一个参数, distort,他是用来调节两个音轨的混合程度的(即上面公式中的a)。

用来混合音频的API

你可以从Google code下载TrackMixer类,它提供了用以混合两个音频文件的API,可以利用它直接混合两个音频文件。

这个类相对来说比较简单,首先是定义将要用到的变量:

 

  1. // pixel bender class and shader
  2. private var KernelClass:Class;
  3. private var shader:Shader;
  4. private var shaderJob:ShaderJob;
  5.  
  6. // num of tracks
  7. private var numOfTracks:Number = 0;
  8.  
  9. // counter
  10. private var trackDownloadCounter:int = 0;
  11.  
  12. // buffer & sound objects
  13. private var buffer:Vector.<ByteArray> = new Vector.<ByteArray>;
  14. private var sound:Vector.<Sound> = new Vector.<Sound>;
  15.  

start() 方法载入将要被混合的两个音频文件。

  1. public function start(urls:Array):void
  2. {
  3. if (urls.length >2)
  4. {
  5. this.dispatchErrorEvent( "API only supports two tracks at this point." );
  6. }
  7.  
  8. numOfTracks = urls.length;
  9.  
  10. for (var i:int = 0; i< numOfTracks; i++)
  11. {
  12. sound[i] = new Sound(new URLRequest(urls[i]));
  13. sound[i].addEventListener(Event.COMPLETE, onSoundLoaded);
  14. sound[i].addEventListener(IOErrorEvent.IO_ERROR, onError);
  15. }
  16. }
  17.  

在载入音轨之后,下一步就是设定ShaderJob及其参数,随后启动ShaderJob.

  1. private function onSampleDataHandler(event:SampleDataEvent):void
  2. {
  3. var width:int = 1;
  4. var height:Vector.<int> = new Vector.<int>(numOfTracks);
  5.  
  6. for (var i:int = 0; i < numOfTracks; i++)
  7. {
  8. buffer[i] = new ByteArray();
  9. sound[i].extract(buffer[i],BUFFER_SIZE * 4);
  10. height[i] = buffer[i].length >> 4;
  11. buffer[i].position = 0;
  12.  
  13. shader.data["src"+i]["input"] = buffer[i];
  14. shader.data["src"+i]["width"] = width;
  15. shader.data["src"+i]["height"] = height[i];
  16. }
  17.  
  18. shader.data.distort.value = [this.balance];
  19. shaderJob = new ShaderJob(shader, event.data,width, height[0]);
  20. shaderJob.start(true);
  21. }
  22.  
  23.  

混合音频的应用程序

下一步就是创建一个利用了混合音频API的应用程序(见图6)

The track mixing application

6 音频混合应用程序

该程序同样嵌入了对应的Pixel Bender kernel并将其作为参数传入TrackMixer。然后启动TrackMixer,同时传入两个音频的URL。当滑块移动的时候,程序会调节混合器的平衡。全部代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
  3. xmlns:s="library://ns.adobe.com/flex/spark"
  4. xmlns:mx="library://ns.adobe.com/flex/halo"
  5. xmlns:local="*"
  6. minWidth="1024" minHeight="768"
  7. creationComplete="creationCompleteHandler(event)">
  8.  
  9. <fx:Script>
  10. <![CDATA[
  11. import com.elad.framework.sound.events.TrackMixerErrorEvent;
  12. import com.elad.framework.sound.TrackMixer;
  13. import mx.events.FlexEvent;
  14.  
  15. [Embed("assets/pbj/TwoTracksMixer.pbj", mimeType="application/octet-stream")]
  16. private var Kernel:Class;
  17.  
  18. private var trackMixer:TrackMixer;
  19.  
  20. protected function creationCompleteHandler(event:FlexEvent):void
  21. {
  22. trackMixer = new TrackMixer(Kernel);
  23. trackMixer.addEventListener(TrackMixerErrorEvent.TRACK_MIXER_ERROR, function(e:*):void { trace(e.message); } );
  24. trackMixer.start( ["assets/tracks/FeelinGood.mp3", "assets/tracks/Sunshine.mp3"] );
  25. }
  26. protected function balanceSliderChangeHandler(event:Event):void
  27. {
  28. trackMixer.balance = event.currentTarget.value ;
  29. }
  30.  
  31. ]]>
  32. </fx:Script>
  33.  
  34. <mx:Slider x="28" y="171" id="balanceSlider" labels='["Track1","Mix","Track2"]'
  35. minimum="0" maximum="1"
  36. liveDragging="true" value="0.5"
  37. change="balanceSliderChangeHandler(event)" />
  38.  
  39. <local:Visualization type="wave" bars="32" width="300" height="137" x="28" y="14"/>
  40.  
  41. </s:Application>
  42.  

上一页 / 下一页

riadevID: 
您给予的分值: None

发表新评论

  • 网页地址和电子邮件地址将会被自动转换为链接。
  • 行和段被自动切分。
  • 您可以使用下面的标签来高亮显示您的评论内容: <code>, <blockcode>. 可以使用"[foo]".旁边显示标签样式 "<foo>" PHP代码可以用这样的区块来包含<?php ... ?> or <% ... %>

更多格式化选项信息

验证区域
系统验证:请回答下面的问题