2010-08-08 104 views
1

我試圖實時播放流(當它從外部來源發出時,我保留其數據)但是不管FMOD不想在播放之後繼續播放第一塊已經加載了,它似乎是在播放之前複製了內存流/解碼它,然後當它播放時它不再使用我的流。C#FMOD實時播放流

我使用下面打我流:

 var exinfo = new FMOD.CREATESOUNDEXINFO(); 
     exinfo.cbsize = Marshal.SizeOf(exinfo); 
     exinfo.length = (uint)_buffer.Length; 

     _result = System.createStream(_buffer, MODE.CREATESTREAM | MODE.OPENMEMORY_POINT , ref exinfo, ref _sound); 
     FMODErrorCheck(_result); 

     _result = System.playSound(FMOD.CHANNELINDEX.FREE, _sound, false, ref _channel); 
     FMODErrorCheck(_result); 

但無論怎樣,它只能播放那是流在調用playSound點的數據量。

任何人都可以知道如何實時修改緩衝區嗎?流開始播放後......?

回答

1

如果您希望流式傳輸原始數據,而不是PCM數據,您可以通過覆蓋FMOD文件系統來實現這一點。有兩種方法可以實現這一點,第一種方法是通過在CreateSoundExInfo結構中設置文件回調,如果這是針對一個特定文件的。第二個是你可以爲所有FMOD文件操作全局設置文件系統(例如你想用多個文件來完成)。

我會解釋後者,但切換到前者雖然是微不足道的。有關完整的示例,請參閱「filecallbacks」FMOD示例。

函數指針:

private FMOD.FILE_OPENCALLBACK myopen = new FMOD.FILE_OPENCALLBACK(OPENCALLBACK); 
private FMOD.FILE_CLOSECALLBACK myclose = new FMOD.FILE_CLOSECALLBACK(CLOSECALLBACK); 
private FMOD.FILE_READCALLBACK myread = new FMOD.FILE_READCALLBACK(READCALLBACK); 
private FMOD.FILE_SEEKCALLBACK myseek = new FMOD.FILE_SEEKCALLBACK(SEEKCALLBACK); 

回調:

private static FMOD.RESULT OPENCALLBACK([MarshalAs(UnmanagedType.LPWStr)]string name, int unicode, ref uint filesize, ref IntPtr handle, ref IntPtr userdata) 
{ 
    // You can ID the file from the name, then do any loading required here 
    return FMOD.RESULT.OK; 
} 

private static FMOD.RESULT CLOSECALLBACK(IntPtr handle, IntPtr userdata) 
{ 
    // Do any closing required here 
    return FMOD.RESULT.OK; 
} 

private static FMOD.RESULT READCALLBACK(IntPtr handle, IntPtr buffer, uint sizebytes, ref uint bytesread, IntPtr userdata) 
{ 
    byte[] readbuffer = new byte[sizebytes]; 

    // Populate readbuffer here with raw data 

    Marshal.Copy(readbuffer, 0, buffer, (int)sizebytes); 
    return FMOD.RESULT.OK; 
} 

private static FMOD.RESULT SEEKCALLBACK(IntPtr handle, int pos, IntPtr userdata) 
{ 
    // Seek your stream to desired position 
    return FMOD.RESULT.OK; 
} 

實現:

// Usual init code here... 

result = system.setFileSystem(myopen, myclose, myread, myseek, 2048); 
ERRCHECK(result); 

// Usual create sound code here... 
2

我建議你查看FMOD附帶的「usercreatedsound」例子,它應該做你需要的。

基本思想是定義您希望在CreateSoundExInfo結構中播放的聲音的屬性,併爲其提供回調函數,您可以使用該回調函數從任意位置加載/傳輸數據。

函數指針:

private FMOD.SOUND_PCMREADCALLBACK pcmreadcallback = new FMOD.SOUND_PCMREADCALLBACK(PCMREADCALLBACK); 

回調用來填充FMOD聲音:

private static FMOD.RESULT PCMREADCALLBACK(IntPtr soundraw, IntPtr data, uint datalen) 
{ 
    unsafe 
    { 
     short *stereo16bitbuffer = (short *)data.ToPointer(); 

     // Populate the 'stereo16bitbuffer' with sound data 
    } 

    return FMOD_OK; 
} 

代碼來創建將使用回調的聲音:

// ...Usual FMOD initialization code here... 

FMOD.CREATESOUNDEXINFO exinfo = new FMOD.CREATESOUNDEXINFO(); 

// You define your required frequency and channels 
exinfo.cbsize   = Marshal.SizeOf(exinfo); 
exinfo.length   = frequency * channels * 2 * 5; // *2 for sizeof(short) *5 for 5 seconds 
exinfo.numchannels  = (int)channels; 
exinfo.defaultfrequency = (int)frequency; 
exinfo.format   = FMOD.SOUND_FORMAT.PCM16; 
exinfo.pcmreadcallback = pcmreadcallback; 

result = system.createStream((string)null, (FMOD.MODE.DEFAULT | FMOD.MODE.OPENUSER | FMOD.MODE.LOOP_NORMAL), ref exinfo, ref sound); 

這應該是足以讓你去,希望這有助於。

+0

感謝您的回答,將與OGG這項工作?因爲我沒有原始格式的文件... – 2010-08-09 03:11:46

+0

沒有這個解決方案只是爲PCM,我將提供壓縮數據的情況下的另一個答案。 – 2010-08-09 05:47:08