FMODでnsfファイル(NESコンソールミュージック)を再生する方法について、gamedevに質問を投稿しました。結果は出ませんでしたが、それ以来、ある程度の進歩を遂げました。最も簡単な方法は、既存のプレーヤーをdllにコンパイルし、それをC#から呼び出してバッファーにデータを入力することであると判断しました。問題は、正しく聞こえるようにすることと、すべてのパラメーターが正しいことを確認することです。
これまでの事実は次のとおりです。
- nsf dllは
short
sを処理しているため、データはPCM16です。 - 私が使用しているサンプルnsfの再生レートは60Hzです。
- 今遊んでいるだけで、48000の周波数を使用しています。
- 2と3に基づいて、dllは48000 / 60hz = 800の必要なバッファーサイズを計算します。これは
short
、シミュレートされたNESフレームごとに800秒相当のバッファーをレンダリングすることを意味します。
これまでのところ、正しいピッチとテンポでnsfを再生するC#コードを入手しましたが、非常に粗く/あいまいです。これは、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;
}
だからここに私の質問のいくつかがあります:
- exinfo.decodebuffersize、頻度、および
datalen
読み取りコールバックのパラメーターの間の関係は何ですか?このコードサンプルでは、3200として入っています。それとdecodebuffersizeの間の4の因数がどこから来ているのかわかりません。 datalen
コールバックにbyte
sの数、またはshort
sを参照していますか?process_buffer関数は、短い配列とその長さを取ります。PCM16と言ったので、fmodもショートパンツについて話していると思います。- まったく別の理由で、再生品質が悪いのかもしれません。もしそうなら、私はそれをどこから解決し始めるのか分かりません。そこに何かアイデアはありますか?