2010-07-16 32 views
2

我試圖在Flash中創建參數均衡器。我一直在尋找一種方式來讀取音頻數據,並在Flash動態播放它們之前處理樣本。在一個Sound對象中加載聲音並使用Sound.extract()來讀取數據,處理它,然後播放第二個空的Sound對象並將數據寫入其sampleData事件似乎是實現它的方式(請糾正我如果我錯了或者有更好的方法)。AS3需要幫助Sound.extract()

當Sound對象仍在加載聲音文件時,有沒有辦法使用Sound.extract()?我不想在播放之前等待整個聲音文件加載。不幸的是,無論何時在Sound對象仍在加載時使用Sound.extract(),它都會返回一個零長度的字節數組。

有沒有辦法在玩之前等待足夠的樣本加載?我想,當Flash影片吃完所有加載的樣本,而聲音文件仍在加載時,我會再次遇到同樣的問題。

這裏是我的代碼的簡化版本。它工作到目前爲止,但只有當我等待Sound對象觸發Event.COMPLETE事件。

var inputSound:Sound = new Sound(); 
inputSound.load("somefile.mp3"); 
inputSound.addEventListener(Event.COMPLETE, loadComplete); 

var outputSound:Sound = new Sound(); 
outputSound.addEventListener(SampleDataEvent.SAMPLE_DATA, processSamples); 
var sc:SoundChannel; 

/*if I called ouputSound.play() right now, it wouldn't work.*/ 

function loadComplete(e:Event) : void 
{ 
    sc = outputSound.play(); 
} 

function processSamples(e:SampleDataEvent) : void 
{ 
    var samples:ByteArray = new ByteArray(); 
    var len:int = snd.extract(samples, 8192); 
    var sample:Number; 
    var i:int = 0; 

    trace(len.toString()); 

    samples.position = 0; 

    //TODO: Sound Processing here 

    //The following code plays a sine wave over the input sound as a test 

    while (samples.bytesAvailable) 
    { 
     i++; 
     sample = samples.readFloat(); 
     sample += Math.sin(i * Math.PI/256) * 0.5; 
     e.data.writeFloat(sample); 
     sample = samples.readFloat(); 
     sample += Math.sin(i * Math.PI/256) * 0.5; 
     e.data.writeFloat(sample); 
    } 
} 

編輯:如果我嘗試使用進度事件,我將需要做更多的低層次的東西來實現緩衝和諸如此類的東西(什麼我需要考慮?)。有人能幫我解決嗎?另外,有沒有辦法以毫秒爲單位來說明樣本的位置?我是否必須假設所有聲音文件都是44.1 kHz立體聲(它們可能不是),還是有更好的方法?

回答

5

退房在這個職位的解決方案在這裏

How to compute viewport from scrollbar?

你並不需要整個軌道提取到一個字節組。你只需要在需要的時候得到你需要的東西。

如果你真的要提取的軌道在一個去,你可以使用

sound.extract(yourbytearray,sound.lenght*44.1) 

// lenght *44.1 gives you the number of samples if the mp3 is encoded at 44100 

一個你有你所有的PCM數據,在您的processsamples處理程序,而不是調用聲音提取物,你會做這樣的事情

if(yourbytearray.bytesAvailable==0) 
{ 
    yourbytearray.position==0 
} 

var left:Number = youbytearray.readFloat 

var right:Number = youbytearray.readFloat 

//process the left with eq 

//process the right with eq 

event.data.writeFloat(left); 
event.data.writeFloat(right); 

一次提取所有的音頻可能是最簡單的,但你會遇到長達8分鐘以上的MP3的內存問題。

在整個樣本毫秒的事情.....

bytearray.position/bytearray.lenght給你在哪裏歌給你。

除以44100,它會給你毫秒數。

提出的問題,如果你需要我清理東西了

+0

我已經通過檢查解決我的問題的主要部分,如果有加載到填充樣品緩衝足夠的數據,如果沒有,則等待直到5000毫秒的音頻可用並輸出沉默。 但是,我現在正在做的事情是否可以安全地假設一切都會以44.1 kHz編碼?聲音文件將被用戶選擇。如果這樣做不安全,是否有一種簡單的方法可以找到採樣率,並且是否有方法來改變空聲音對象的採樣率,或者我將不得不插入並隨時將其轉換爲44.1 kHz ? – 2010-07-19 17:35:03

+0

90%的時間你會發現一個MP3編碼爲44.1,但事實並非總是如此。當你加載它時,你可以讀取mp3頭,並確定安全的編碼率。 – dubbeat 2010-07-20 12:54:39

+0

acual是alwys 44100 Hz立體聲和32位採樣率。 Sund.excrt()使它變成這樣。 dolan http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#extract() – 2012-07-02 10:23:02