С кем нибудь можно об uFMOD поговорить ?

Тема в разделе "WASM.ZEN", создана пользователем DevilDevil, 16 ноя 2007.

  1. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Пишу простой звуковой движок, чтение XM взял из MinifMod - предка uFMOD-а. Чтение Wave-данных свелось примерно к:

    procedure ReadModuleTick(WaveBuffer : pointer);
    begin
    ZeroMemory(WaveBuffer, Module.samplespertick shl 3);

    FMUSIC_UpdateXM(Module);
    FSOUND_Mixer_FPU_Ramp(WaveBuffer, Module.samplespertick, #0);
    FSOUND_MixerClipCopy_Float32(WaveBuffer, WaveBuffer, Module.samplespertick);
    end;

    Вопрос: можно ли чтото похожее замутить с uFMOD-ом ?
     
  2. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    DevilDevil
    Вы примеры идущие с дистрибутивом ufmod смотреть не пробовали?
     
  3. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    ещё как пробовал. там проигрывание осуществляется на уровне самого движка, а мне надо вручную считывать сгенерированные Wave-данные
     
  4. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    ufmod работает с xm форматом
     
  5. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Asterix, а Minifmod с чем ?
    а на колонки звук в каком формате идёт ?
     
  6. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    minifmod тоже
     
  7. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Asterix, читай первый пост.
    2 внутренние функции
    Код (Text):
    1. FSOUND_Mixer_FPU_Ramp/FSOUND_MixerClipCopy_Float32
    позволяют получить wave-данные (они собственно и проигрываются), равный в моём случае одному текущему тику XM-файла.
     
  8. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    DevilDevil
    Уже ответил Вам мылом. Прямого доступа к PCM данным не предусмотрено (исключение - версия для Колибри) на уровне АПИ, но исходники открыты :) В ufmod.asm чётко виден цикл, который копирует PCM данные в драйвер. Можете добавить туда свой код и перекомпилировать :)
     
  9. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Quantum, ааа, так ты - русский! хе-хе-хе...

    я асм знаю совсем чуть-чуть, поэтому сложновато. особенно непонятно, где какие функции.

    догадки:
    - всё, что мне нужно - это "core.asm" + в "ufmod.asm" посматривать.
    - где-то должна быть структура FMUSIC_MODULE
    - должны быть функции типа LoadXM, FreeXM, UpdateXM и Mixer-функции
    - какие проблемы с синхронизацией, используются глобальные переменные ? В Minifmod, кстати, я эту проблему решал, хитро, но решал. Хотя можно и обычной критической секцией обходиться.
     
  10. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    DevilDevil
    Скорее наоборот. Всё, что связано с выводом PCM на драйвер - это в ufmod.asm. В core.asm находится движок, но его Вам трогать врядли понадобиться :)

    Нечто вроде того имеется, но работает совсем не так, как в miniFMOD. А что Вам нужно из FMUSIC_MODULE?

    Да, всё это есть, но не предусмотрено возможности вызывать эти функции извне.

    Проблема в том, что если Вы вовремя не дадите миксеру квант времени, чтобы заполнить буфер, звучать всё будет как минимум обрывисто. Потом по форумам начинают сеять сплетни о том, что uFMOD уступает по качеству звучания каким-то другим движкам. Поэтому движок берёт на себя синхронизацию с буфером драйвера.

    Вот место в коде ufmod.asm где выводится PCM:

    Код (Text):
    1.     align 4
    2. fill_loop_2:      ; <--- начало цикла
    3.     lodsd
    4. if INFO_API_ON
    5.     push edi
    6.     cdq
    7.     mov edi,eax
    8.     push esi
    9.     xor eax,edx
    10.     mov esi,255*volumerampsteps/2
    11. ; *** куча кода
    12.     dec ecx
    13.     stosw
    14.     jnz fill_loop_2
    15.         ; <--- конец цикла
    Адрес буфер драйвера помещается в регистр ESI перед началом цикла. Чтоб PCM копировался не в драйвер, а в какой-то другой массив, достаточно подменить значение ESI перед началом цикла. Но для этого нужно более-менее хорошо разбираться в ассемблере.
     
  11. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Quantum, я половину сказанного недопонимаю, но постараюсь провести аналогии с minifMod, может ридём к общему пониманию.

    PCM рендерится не в драйвер, а в свой внутрненний буффер. В драйверный буффер в определённый момент копируются данные из внутреннего буффера.

    что есть квант времени?
    может быть мы говорим о разных вещах, но MinifMod-овский двиг требует, условно говоря, количество семплов, которые надо смиксировать. Я смешивал сразу 1 тик в свой буффер, размер которого мне известен ( samplespertick*4 ). С драйверным буффером я общаюсь сам :) .

    SamplesPerTick. + необходимо узнавать, что трек закончился.
    Но более важно, я хочу иметь доступ к нескольким открытым трекам (нескольким FMUSIC_MODULE).

    Насколько сложно сделать их "public" и использовать ?

    Я попытался поискать сорсы для Kolibri, безуспешно o_O?
    + мне надо производить чтение из Delphi-йского TStream-а.
     
  12. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    DevilDevil
    Это справедливо для miniFMOD, если мне не изменяет память, но в uFMOD всё совсем иначе: во внутреннем буфере данные хранятся не в PCM, а в некотором 32-битном формате, который использует встроенный миксер. В определённый момент данные конвертируются на лету в 16-битный PCM и копируются в драйвер. В частности благодаря этой схеме uFMOD на порядок быстрее miniFMOD'а.

    Это время, которое выделяется потоку, который подгружает данные в буфер драйвера. Если оставить это на совести пользовательского кода, нет гарантии, что данные запишутся вовремя.

    samplespertick хранится по адресу переменной _mod + 60 байт. Но _mod не экпортируется. Правда, ничто не мешает сделать её паблик.

    Есть флаг XM_NOLOOP с которым проигрывание не зацикливается. Если задать этот флаг, то конец трека можно определить по состоянию хендла треда. Переменная с этим хэндлом - hThread, но она тоже не экспортируется. Стандартные виндовые функции для синхронизации вроде WaitForSingleObject как раз для подобных ситуаций и предназначены.

    Дело не в паблик, а в том, что эти функции не предназначены для вызова извне. Если не подставить нужные значения в регистры и стек, вызов любой из этих "функций" окончится плачевно.

    Они на офф. сайте ufmod.sf.net в соответсвующем пакете. И в последнем релизе Колибри тоже присутствуют. Только там изпользуется совсем другая схема чтения файлов, выделения динамической памяти и т.д. Т.е. под win32 от этого кода пользы не будет.

    На данном этапе адаптировать исходники библиотеки под Ваши нужды мне представляется сложной задачей. Фишку с рендерингом в произвольный буфер вместо определённого драйвера как в Колибри некогда планировалось перенести в win32/linux/unix, но это произойдёт не скоро, если вообще произойдёт.
     
  13. DevilDevil

    DevilDevil Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2007
    Сообщения:
    101
    Это всё не то. Там можно несколько полей сравнивать на -1 вроде.

    Возможно, в MiniFMod так же.

    да врядли из-за такой не особо значительной вещи на порядок.


    по идее можно враппер сделать

    Вот в OggVorbis, например, вообще нет проигрывания. Тем не менее справляются как то люди. В ModPlug та же ситуация кстати.


    Хм... вот какой вопрос, личный почти...
    не знаешь, кого нибудь из фрилансеров, с кем пожно обговорить данный вопрос ?
     
  14. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Как не то? Я не представляю себе как можно более эффективно определить конец проигрывания. Не сравнивать же значение какой-то глобальной переменной в цикле пока не надоест, когда можно получить уведомление асинхронно через событие?

    Возможно, я не совсем ясно обьяснил ситуацию. Суть в том, что минифмод приводит всё к PCM на стадии микширования, а это значит что преобразование осуществляется для каждого из 32 каналов. уФМОД приводит всё к PCM один раз (!) непосредственно перед отправкой данных в драйвер. В добавок к этому, уФМОД использует целочисленный миксер, а не ФПУ-шный как в миниФМОД. Производительность действительно выше на порядок и я имею в виду десятичный порядок.

    Можно, но для этого нужно хорошо разобраться в коде, т.е. обязанность ложиться на разработчиков, но я пока не представляю себе пользы от экспорта LoadXM, UpdateXM и т.д. Если Вам нужно загрузить трек в память, но не начинать проигрывание, т.е. как при вызове LoadXM, просто вызовите uFMOD_PlaySong с флагом XM_SUSPENDED или как-то так мы его окрестили.

    В 99% случаев людям нужна либа для проигрывания, а не для абстрактной загрузки стрима в память, чтоб потом самостоятельно разруливать общение с драйвером, синхронизацию и т.д. Поэтому надстройки над Ogg, позволяющие одним вызовом функции начать воспроизведение более популярны, чем сам Ogg, как ни парадоксально :) Я не говорю, что запрошенная Вами фича никому больше не нужна, более того идея добавить такую возможность уже возникала, но пока имеются более приоритетные TODO.

    Дык, никто ж не захочет заниматься разбором километровых ассемблерных листингов, тем более что движок постоянно меняется и к следующей версии придётся разбираться по новой. Я бы на Вашем месте заюзал уже упомянутый модплуг, если проект не критичен к размеру, ведь так?