Параметры потоковой передачи, обратного вызова и exinfo FMOD.net - PullRequest
0 голосов
/ 08 января 2011

Я опубликовал вопрос на gamedev о том, как проигрывать файлы nsf (консольная музыка NES) в FMOD. Это не дало никаких результатов, но с тех пор я добился определенного прогресса. Я решил, что самым простым способом было просто скомпилировать существующий проигрыватель в dll, а затем вызвать его из C # для заполнения моего буфера. Теперь проблема в том, чтобы заставить его звучать правильно и убедиться, что все мои параметры верны.

Вот факты на данный момент:

  1. nsf dll имеет дело с short s, поэтому данные PCM16.
  2. Образец nsf, который я использую, имеет скорость воспроизведения 60 Гц.
  3. Просто для игры сейчас я использую частоту 48000.
  4. На основе 2 и 3, dll вычисляет необходимый размер буфера 48000/60 Гц = 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. Какова связь между exinfo.decodebuffersize, частотой и параметром datalen обратного вызова чтения? В этом примере кода он равен 3200. Я не знаю, откуда взялся этот коэффициент 4 между ним и размером декодера.
  2. Является ли datalen в обратном вызове ссылкой на число byte с или short с? Функция process_buffer принимает короткий массив и его длину. Я ожидаю, что fmod говорит и о шортах, потому что я сказал ему PCM16.
  3. Возможно, мое качество воспроизведения плохое по совершенно другой причине. Если так, я понятия не имею, с чего начать. Есть идеи?

1 Ответ

1 голос
/ 10 января 2011
  1. Член FMOD_CREATESOUNDEXINFO 'decodebuffersize' находится в выборках PCM и контролирует, сколько данных будет запрашиваться в функции 'pcmreadcallback'. Таким образом, поскольку вы установили его на 800 и PCM16, значение datalen будет равно 1600, поскольку значение в байтах. Вы упоминаете, что значение datalen равно 1600 (как и ожидалось), но позже вы говорите, что это 3200, возможно, я запутал ваше значение. Наконец, «частота» просто говорит FMOD, как быстро воспроизводить ваши данные, это должно соответствовать тому, что когда-либо производит ваша функция «process_buffer».

  2. 'datalen' в байтах.

  3. Хороший способ проверить это просто - сгенерировать, скажем, 5 секунд аудио, а затем загрузить его в FMOD в качестве образца. Это позволяет избежать возможных осложнений с обратными вызовами чтения.

КСТАТИ: ex.length сообщает Sound :: getLength, насколько велик ваш файл на самом деле, и если вы используете FMOD_CREATESAMPLE, это то, сколько памяти выделяется.

...