2011-01-07 51 views
0

我發佈了一個question on gamedev關於如何在FMOD中播放nsf文件(NES控制檯音樂)。它沒有得到任何結果,但從那時起我取得了一些進展。我決定最簡單的方法就是將現有的播放器編譯成一個dll,然後從C#調用它來填充我的緩衝區。現在的問題是讓它聽起來正確,並確保我所有的參數都是正確的。FMOD.net流媒體,回調和exinfo參數

這裏是事實至今:

  1. 美國國家科學基金會的DLL是處理short S,這樣的數據是PCM16。
  2. 我正在使用的示例nsf的播放速率爲60 Hz。
  3. 只是現在打轉轉,我使用的是基於2和3的48000
  4. 的頻率,該dll計算48000/60HZ的必需的緩衝器大小= 800這意味着它將使800 short值得的每個模擬NES幀的緩衝區。

到目前爲止,我已經得到了我的C#代碼,以正確的音高和速度播放nsf,但它非常有顆粒感/模糊,我認爲FMOD讀回調給出了一個事實數據長度爲1600,而我應該預計爲800.我嘗試過使用所有數字,並且要麼崩潰,要麼音樂改變音高,速度,或者兩者兼而有之。

下面是我的一些C#代碼:

uint channels = 1, frequency = 48000; 

FMOD.MODE mode = (FMOD.MODE.DEFAULT | FMOD.MODE.OPENUSER | FMOD.MODE.LOOP_NORMAL); 

FMOD.Sound sound = new FMOD.Sound(); 
FMOD.CREATESOUNDEXINFO ex = new FMOD.CREATESOUNDEXINFO(); 
ex.cbsize = Marshal.SizeOf(ex); 
ex.fileoffset = 0; 
ex.format = FMOD.SOUND_FORMAT.PCM16; 

// does this even matter? It doesn't change my results as long as it's long enough for one update 
ex.length = frequency; 

ex.numchannels = (int)channels; 
ex.defaultfrequency = (int)frequency; 
ex.pcmreadcallback = pcmreadcallback; 
ex.dlsname = null; 

// eventually I will calculate this with frequency/nsf hz, but I'm just testing for now 
ex.decodebuffersize = 800; 

// from the dll 
load_nsf_file("file.nsf", 8, (int)frequency); // 8 is the track number to play 

var result = system.createSound(
     (string)null, 
     (mode | FMOD.MODE.CREATESTREAM), 
     ref ex, 
     ref sound); 

channel = new FMOD.Channel(); 
result = system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel); 

private FMOD.RESULT PCMREADCALLBACK(IntPtr soundraw, IntPtr data, uint datalen) 
{ 
    // from the dll 
    process_buffer(data, (int)800); // if I use datalen, it usually crashes (I can't get datalen to = 800 safely) 

    return FMOD.RESULT.OK; 
} 

因此,這裏是我的一些問題:

  1. 什麼是和讀的datalen參數exinfo.decodebuffersize,頻率之間的關係,回電話?有了這個代碼示例,它將以3200進入。我不知道它和decodebuffersize之間的因子是從哪裏來的。
  2. 是否datalen在回調中提到byte s或short s? process_buffer函數使用一個簡短的數組及其長度。我希望fmod也在談論短褲,因爲我告訴它PCM16。
  3. 也許我的播放質量不好,因爲一些完全不同的原因。如果是這樣,我不知道從哪裏開始解決。那裏有任何想法?

回答

1
  1. 的FMOD_CREATESOUNDEXINFO「decodebuffersize」構件是PCM樣品和對照多少數據將在「pcmreadcallback」函數來請求英寸因此,由於您將其設置爲800和PCM16,「datalen」將爲1600,因爲該值以字節爲單位。你提到的'datalen'值是1600(如預期),但後來你說它是3200,或許我已經混淆了你的意思。最後,「頻率」只是告訴FMOD玩數據的速度有多快,這應該與您的'process_buffer'函數產生的效果相匹配。

  2. 'datalen'以字節爲單位。

  3. 一個很好的方法來測試這個簡單的方法是生成5秒鐘的音頻,然後將其加載到FMOD中作爲示例。這避免了讀取回調的潛在複雜性。

BTW:'ex。長度「告訴Sound :: getLength你的文件實際上有多大,如果你正在使用FMOD_CREATESAMPLE,這是多少內存分配。

+0

謝謝,這就是我所需要的。質量問題實際上是在NSF庫中,而不是我的FMOD代碼。 – Tesserex 2011-01-11 03:19:18