2016-06-11 103 views
0
正確

我一直在使用n音訊與 「射後不理音頻播放與n音訊」教程(謝謝你馬克這個真棒工具!)書面這裏: http://mark-dot-net.blogspot.nl/2014/02/fire-and-forget-audio-playback-with.htmln音訊:使用MixingSampleProvider與VolumeSampleProvider

我管理使用MixingSampleProvider作爲輸入添加一個VolumeSampleProvider。但是,當我現在連續播放兩個聲音時,即使第一個聲音已經播放,第一個聲音也總是獲得第二個聲音的音量。

所以我的問題是:如何添加聲音,每一個聲音獨立的音量?

這是我用什麼:

 mixer = new MixingSampleProvider(waveformat); 
     mixer.ReadFully = true; 
     volumeProvider = new VolumeSampleProvider(mixer); 
     panProvider = new PanningSampleProvider(volumeProvider); 
     outputDevice.Init(panProvider); 
     outputDevice.Play(); 

回答

1

我不是100%肯定的你問什麼,我不知道,如果你解決了這個已經,但這裏是我拿到這個。

ISampleProvider對象通過Read()方法玩「通過降壓」遊戲來源ISampleProvider。最終,有人會對音頻字節進行實際讀取。個人ISampleProvider類做他們對字節做任何事情。

MixingSampleProvider,例如,佔據N音源......那些獲得混合。當調用Read()時,它會迭代音頻源並從中讀取count字節。

它傳遞到VolumeSampleProvider處理所有字節(從這些各種來源)爲一組...它說:

buffer[offset+n] *= volume; 

那將全線調整字節...所以每一個字節通過volume乘數在緩衝區中進行調整;

PanningSampleProvider只是爲立體聲音頻提供乘法器並相應地調整字節,做與VolumeSampleProvider一樣的事情。

如果你要單獨處理音頻源卷,你需要處理MixingSampleProvider的上游。基本上,你傳遞給MixingSampleProvider的東西需要能夠獨立調整音量。

如果您通過一堆SampleChannel對象到您的MixingSampleProvider ...您可以完成獨立的音量調整。所述Samplechannel類結合有VolumeSampleProvider對象並提供Volume屬性,允許一個設置VolumeSampleProvider對象的音量。

SampleChannel還集成了一個MeteringSampleProvider即在一定期間內提供了最大樣本值的報告。它引發了一個事件,爲您提供一組這些值,每個通道一個。

+0

親愛的馬特,感謝你這個答案。我將不得不仔細看看SampleChannel類,以確定我是否可以使其工作。自從我上次研究這個代碼已經過去了一年多了,所以我不會想象我很快就會知道。問候。 – Paul

0

我意識到(感謝itsmatt),爲了使這項工作的唯一辦法,就是獨自離開混頻器和調節每個單獨CachedSound的平移和音量,將它添加到混合器之前。因此我需要重寫CachedSoundSampleProvider,使用pan和volume作爲額外的輸入參數。

這是新構造:

public CachedSoundSampleProvider(CachedSound cachedSound, float volume = 1, float pan = 0) 
    { 
     this.cachedSound = cachedSound; 
     LeftVolume = volume * (0.5f - pan/2); 
     RightVolume = volume * (0.5f + pan/2); 
    } 

這是新的read()函數:

public int Read(float[] buffer, int offset, int count) 
    { 
     long availableSamples = cachedSound.AudioData.Length - position; 
     long samplesToCopy = Math.Min(availableSamples, count); 

     int destOffset = offset; 
     for (int sourceSample = 0; sourceSample < samplesToCopy; sourceSample += 2) 
     { 
      float outL = cachedSound.AudioData[position + sourceSample + 0]; 
      float outR = cachedSound.AudioData[position + sourceSample + 1]; 

      buffer[destOffset + 0] = outL * LeftVolume; 
      buffer[destOffset + 1] = outR * RightVolume; 
      destOffset += 2; 
     } 

     position += samplesToCopy; 
     return (int)samplesToCopy; 
    }