Информатика и образование
  Мобильная версия сайта            
               
[Главная] [Новости]
[Статьи]
[Проекты]
[Ссылки]
[Автор]
               
    [Архив новостей]        
               
  [Форум] на форуме можно задать вопрос, посмотреть ответы на часто задаваемые вопросы  
       
  Здравствуйте! Вы попали на информационно-образовательный сайт посвященный информатике, информационным технологиям и компьютерным играм. Подробнее о целях и задачах сайта в разделе Главная. [English version of this page here...]    
       
  [Базовые уроки по DirectX] [Основы DirectMusic на Delphi] [Основы DirectInput8 на Delphi] [Основы DirectSound8 на Delphi]    
  [Разработка компьютерной игры] [Пример игры Donuts3D]    
       
 

9/06/2008 Воспроизведение в игре музыки в формате XM.

Для воспроизведения используется компонент MiniFMOD 1.78 переписанный на Delphi. Успешно используется в примере игры XTropper (автор XProger).

   
       
 

Рассмотрим поэтапно как реализовано воспроизведение музыки в указанном примере игры.

В модуле XTropper.dpr -

uses {...} MiniFMOD in 'MiniFMOD\MiniFMOD.pas',

l_sound,

между операторами begin и end. -

snd_Init;

Game_Init;

внутри цикла "прокачки" сообщений -

Game_Update;

snd_Update;

   
       
 

function WndProc -

Case message of
WM_QUERYENDSESSION, WM_CLOSE:
begin
{...}
snd_deInit;

{...}

if inMenu then
Menu_Message(message, wParam, lParam);

 

   
       
 

Старт воспроизведения музыки - в модуле XTropper.dpr -

между begin и end.

Game_Update -

в модуле l_game.pas -

Game_Update -

XMStop

XMPlay

{...}

Game_Init > MenuInt

 

Процедуры GameStart и GameFree -

в модуле l_menu.pas -

Menu_Init, MenuLoad

{...}

procedure Menu_Message -

Game_Start;

   
       
 

Обобщим полученную информацию -

Исходный код для работы с MiniFMOD находится в папке MiniFMOD

в этой папке находятся

MiniFMOD.obj - по всей видимости скомпилированный в MSVS файл библиотеки работы с minifmod

MiniFMOD.pas - интерфейсы для использования данной библиотеки

Так и есть в комментариях к файлу MiniFMOD.pas приведено следующее -

{
MiniFMOD 1.7 is a free C library from Fairlight
Technologies (http://www.fmod.org) which allows
you to play .XM files. Compiled into a .OBJ,
it is then possible to use it in any language
that supports OMF .OBJ files.

Here is the Delphi header I made for it.

Twis (June 2004).
}

Т.е. это говорит именно о том, что obj-файл это объектный файл библиотеки minifmod 1.7

Следует отметить, что minifmod не гарантирует 100% точности и идентичности звука XM-файла по сравнению скажем с воспроизведением в плеере или трекере. Об этом свидетельствуют заметки в readme содержащиеся в дистрибутиве midifmod178.rar (85 Кб). Однако на первых порах для игры данная библиотека думаю подойдет.

В реальных тестах и проверках будет ясно. Посмотрим.

   
       
 

Продолжим обобщения -

Итак, в папку проекта игры нужно добавить папку MiniFMOD содержащую указанные выше 2 файла.

Далее -

в раздел uses модуля проекта или модуля приложения добавить ссылку на файл MidiFMOD.pas

модуль l_sound ? Суть вопроса: Как происходит воспроизведение музыки при помощи MiniFMOD -

путем вывода результата непосредственно на звуковую карту или же требуется предварительный рендеринг в звуковой буфер DirectSound с последующим выводом полученного через IDirectSound?

Поскольку в модуле l_sound содержится ссылка на MidiFMOD.pas, то скорее всего это 2 вариант, т.е.

при помощи miniFMOD XM файл сначала выводится в выделенный звуковой буфер IDirectSoundBuffer, а затем полученный кусочек уже воспроизводится средствами IDirectSound.

Однако эксперимент с комментированием ссылки на uses MiniFMOD внутри модуля l_sound показывает, что ошибок компиляции не возникает. Следовательно l_sound не использует MiniFMOD и ссылка возможно осталась ошибочно.

Смотрим далее -

   
       
 

из-за указанной особенности в uses также нужно добавить использование модуля l_sound.pas написанного XProger

Где-то после создания окна приложения, например в OneTimeSceneInit вызвать процедуры подобные snd_Init и Game_Init.

внутри метода Run -

перед FrameMove или даже внутри FrameMove вызываем процедуры подобные

Game_Update;

snd_Update;

Следует обратить внимание на то, что - в модуле проекта XTropper.dpr между begin и end. -

{...}

while not isQuit do
begin
while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;

if not glActive then
WaitMessage
else
begin
Time := GetTimer;
Time_Delta := Time - Time_Old;

flag := false;
for i := 1 to Time_Delta div 20 do
// будет ли влиять указанная периодичность на качество воспроизведения???
begin
Game_Update;
snd_Update;
flag := true;
end;

if flag = true then
Time_Old := Time - Time_Delta mod 20;
// или это не окажет влияния???
Game_Render;
end;
end;

{...}

   
       
 

внутри MsgProc -

при WM_DESTROY -

//WM_QUERYENDSESSION, WM_CLOSE: //в модуле проекта XTropper.dpr закрытие происходит по данным сообщениям

Game_Free;
//внутри данной процедуры происходит освобождение объекта XM-плеера - XMFree.

snd_deInit;

   
       
 

Это всё что касается создания, обработки и уничтожения объектов воспроизведения музыки.

Теперь необходимо рассмотреть детальную реализацию того, что происходит внутри данных процедур, касающееся загрузки конкретных XM-модулей, запуска и останова проигрывания, регулировки громкости и других особенностей.

   
       
  Использование модуля l_sound.pas можно пока оставить без изменений, поскольку он выполняет роль фактического плеера, служит для управления звуком (запуск, стоп, громкость и т.п.) на уровне возможностей IDirectSound. Единственно, что поскольку l_sound.pas ориентирован на работу со старыми интерфейсами из модуля DirectX.pas (версии DirectX 6), то в этом плане возможно потребуется его переделка.    
       
 

Game_Init -

Menu_Init -

XMLoadFromFile('data\music\baits.xm');
XMPlay;

Game_Update -

XMStop //вероятно так сделано для того, чтобы очередной кусок был выведен в звуковой буфер с опережением

XMPlay //т.е. сначала кусок выводится потом работа продолжается, а затем выполняется останов и снова вывод новой порции в буфер Это предположение, посмотрим что на практике!!!

 

   
       
 

Game_Free -

XMStop;
XMFree;

В приложении XTropper воспроизведение музыки управляется через объект меню -

внутри функции обработки сообщений (function WndProc ...) -

Game_Free при сообщениях WM_QUERYENDSESSION, WM_CLOSE, а в конце ее -

if inMenu then
Menu_Message(message, wParam, lParam);

При выборе пункта меню Start - внутри указанной процедуры -

Game_Start;

Game_Start -

XMFree;
XMLoadFromFile('data\music\rave.xm');
XMPlay;

   
       
 

Внутри модуля l_menu.pas также есть процедура -

procedure Menu_Load;
begin
XMFree;
XMLoadFromFile('data\music\baits.xm');
XMPlay;
end;

Где и как она вызывается?

Ответ - она вызвается внутри модуля l_input.pas в ответ на нажатие Escape -

procedure KeyOnUp(ID: Byte);
begin
Key[ID] := false;
case ID of
VK_ESCAPE : if not inMenu then
begin
snd_StopAll(0);
Player.ResetKeys;
if Player.Health = 0 then
Menu_Load;
inMenu := true;
end;

end;
end;

 

   
       
 

Теперь рассмотрим работу со звуком - использование модуля l_sound.pas в приложении XTropper -

Рассмотрение пока не требуется, т.к. XM воспроизводится без IDirectSound. Однако таким образом не используются все преимущества IDirectSound. В частности отсутствует возможность регулировки громкости музыки.

   
       
 

Попробуем использовать возможности MiniFMOD в имеющемся объеме для воспроизведения музыки.

Оказалось достаточно даже следующего способа работы:

Создаем 2 метода -

function TD3DGameApp.InitMusic: HResult;
begin
result := S_OK;

XMLoadFromFile('Media\Music\wizard_morning.xm');
XMPlay;
end;

procedure TD3DGameApp.FreeMusic;
begin
XMStop;
XMFree;
end;

   
       
  И вызываем их где-либо, например в конце CreateSoundObjects и DestroySoundObjects. Всё. При старте приложения сразу же включается музыка.    
       
 

Если требуется загрузка и воспроизведение иной мелодии, то достаточно вызвать следующую последовательность команд -

XMStop;
XMFree;

XMLoadFromFile('Media\Music\wizard_morning.xm');
XMPlay;

   
       
 

Возникает воспрос как регулировать громкость мелодии?

Поскольку miniFMOD скорее всего воспроизводит музыку через средства Windows без DirectSound, то теоретически должна быть возможность регулирования громкости за счет доступа к глобальному регулятору громкости системы. Есть ли такая возможность в модуле MMSystem.pas ?

   
       
 

Организация проигрывания различных музыкальных тем в разных частях приложения:

При старте приложения должна играть 1 тема,

При выходе в главное меню - другая

При переходе к игровой сцене - тема для нее.

На стадии загрузки игровой сцены должна загружаться мелодия для нее.

При старте игровой сцены должно включаться воспроизведение.

При выходе из игровой сцены воспроизведение должно останавливаться.

При удалении игровой сцены должен очищаться объект проигрывателя XM-мелодии.

Остановка и последующий старт воспроизведения не приводят к моментальному появлению звука. Имеет место некоторая задержка. Это свидетельствует о том, что для моментального включения/отключения мелодии нужно воспользоваться регулировкой громкости.

В модуле MMSystem.pas действительно есть функция - function waveOutSetVolume

Единственным недостатком таких регулировок будет то, что будет изменяться глобальная громкость воспроизведения в системе, а не локальная - данной мелодии.

Можно тажке посмотреть как реализовано управление громкостью в мультимедиа-плеере TMediaPlayer. Это ничего не дает. Там нет таких процедур!!!

Однако читая документацию по waveOutSetVolume, а также просматривая код модулей MMSystem.pas и MiniFMOD.pas обнаруживаем, что

1) громкость регулируется для локального экземпляра звука - значит это то, что нам нужно.

2) экспорты некоторых функций - в модуле MiniFMOD.pas являются сходными из аналогичных модуля MMSystem.pas Это еще раз подтверждает, что музыка воспроизводится минуя DirectSound обращаясь напрямую к системным функциям мультимедиа. Это же дает зацепку о способе регулировки звука при помощи указанного метода.

waveOutSetVolume требует 2-х параметров:

HWAVEOUT hwo, - обработчик устройства воспроизведения
DWORD dwVolume - громкость - младшее слово - левый канал, старшее - правый.

[далее] - о воспроизведении музыки при помощи библиотеки OggVorbis

   
       
  [Назад] [Все уроки]    
       
 

Обновления и новости о развитии Delphi DirectX проекта
смотри на сайтах:

http://www.megainformaticsite.pochta.ru

http://www.megainformatic.boom.ru

http://www.megainformatic.narod.ru

 

   
       
 

Cвои пожелания, вопросы или заметки отправляйте на:

megainformatic@mail.ru

 
     
   Обмен ссылками  
     
     
             
 
 
         
(с) МЕГА ИНФОРМАТИК 2006-2009
Hosted by uCoz