我正在尝试实时播放一个流(我从一个nexternal源继续向我发送数据)但无论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时播放流中的数据量。
有谁知道如何实时修改缓冲区?流开始播放后......?
答案 0 :(得分: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);
这应该足以让你前进,希望这会有所帮助。
答案 1 :(得分: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...