1

私はリアルタイムでストリームを再生しようとしています (次のソースから入ってくるデータをそれに追加し続けます) が、ロードされた最初のチャンクの後に 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 を呼び出した時点でストリームにあるデータの量だけを再生します。

リアルタイムでバッファを変更する方法を知っている人はいますか? ストリームの再生が開始された後...?

4

2 に答える 2

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);

これで十分です。これがお役に立てば幸いです。

于 2010-08-09T00:13:45.633 に答える
1

PCM データではなく生データをストリーミングしたい場合は、FMOD ファイル システムをオーバーライドすることで実現できます。これを実現するには 2 つの方法があります。1 つ目は、これが 1 つの特定のファイルに対するものである場合、CreateSoundExInfo 構造体でファイル コールバックを設定することです。2 つ目は、すべての 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...
于 2010-08-09T05:56:50.870 に答える