Èñïîëüçîâàíèå FMOD â çâóêîâûõ èãðàõ

Äàòà ïóáëèêàöèè:2005
Ïîäåëèòüñÿ â Twitter Ïîäåëèòüñÿ â F******k Ïîäåëèòüñÿ â VKontakte Ïîäåëèòüñÿ â Telegram Ïîäåëèòüñÿ â Mastodon

Äîñòîèíñòâà è íåäîñòàòêè FMOD

Ðå÷ü ïîéä¸ò î ïðîãðàììíîé áèáëèîòåêå äëÿ ðàáîòû ñî çâóêîì, èçâåñòíîé ïîä íàçâàíèåì FMOD. Ðàçðàáîò÷èêîì ýòîãî ïðîãðàììíîãî ïðîäóêòà ÿâëÿåòñÿ êîìïàíèÿ Firelight Technologies Pty, Ltd. Íà ìîìåíò íàïèñàíèÿ ñòàòüè ïîñëåäíèì ðåëèçîì FMOD áûëà âåðñèÿ 3.74. Ñ òåêóùèì ñîñòîÿíèåì äåë è ñ íîâûìè âåðñèÿìè, åñëè îíè ïîÿâèëèñü, âû ìîæåòå îçíàêîìèòüñÿ íà ñàéòå www.FMOD.org. Íà òîì æå ñàéòå âû ìîæåòå ïîëó÷èòü âåðñèè FMOD äëÿ ðàçëè÷íûõ îïåðàöèîííûõ ñèñòåì. Ïðÿìûå ññûëêè íà äèñòðèáóòèâ FMOD ðàñïîëîæåíû çäåñü.

Áèáëèîòåêà ôóíêöèé FMOD ïðåäñòàâëÿåò ñîáîé ðåàëèçàöèþ API âåðõíåãî óðîâíÿ, êîòîðûé âêëþ÷àåò øèðîêèé íàáîð ôóíêöèé äëÿ ðàáîòû ñî çâóêîâûìè ôàéëàìè ðàçëè÷íûõ ôîðìàòîâ, îáðàáîòêè çâóêîâûõ äàííûõ è âîñïðîèçâåäåíèÿ çâóêà ÷åðåç àóäèîñèñòåìó êîìïüþòåðà èëè èãðîâûõ ïðèñòàâîê. Äëÿ òîãî ÷òîáû ðàññêàçàòü îáî âñåõ âîçìîæíîñòÿõ ýòîãî API ïîòðåáóåòñÿ íå îäèí äåñÿòîê web-ñòðàíèö. Êðîìå òîãî, îñíîâíîé íàøåé òåìàòèêîé íàçâàíà ðàçðàáîòêà çâóêîâûõ èãð, äëÿ êîòîðûõ ãëàâíûé èíòåðåñ ïðåäñòàâëÿþò ôóíêöèè äëÿ ðàáîòû ñ îáú¸ìíûì (3D) çâóêîì. Çíàêîìñòâîì ñ ýòèìè ôóíêöèÿìè ìû è îãðàíè÷èìñÿ. Ñëåäóåò èìåòü â âèäó, ÷òî äàííàÿ ïóáëèêàöèÿ íå ÿâëÿåòñÿ ïîëíûì ðóêîâîäñòâîì ïî FMOD, ïîýòîìó, ðàçáèðàÿ ïðèâîäèìûå íèæå ïðèìåðû, íå ñëåäóåò ïðåíåáðåãàòü îôèöèàëüíîé äîêóìåíòàöèåé. Âñå ïðèìåðû â ñòàòüå ñîñòàâëåíû íà ÿçûêå ïðîãðàììèðîâàíèÿ C (Ñè).

Äëÿ ñîçäàíèÿ èñòî÷íèêîâ 3D çâóêà è ðàñ÷åòà òð¸õìåðíîé çâóêîâîé êàðòèíû FMOD (âåðñèÿ äëÿ Windows) èñïîëüçóåò â êà÷åñòâå áàçû ëþáóþ èç ñëåäóþùèõ çâóêîâûõ ñèñòåì: WMM (Windows Multimedia), DirectSound3D (çâóêîâàÿ ïîäñèñòåìà Microsoft DirectX) è A3D. FMOD îáåñïå÷èâàåò òàêîå âçàèìîäåéñòâèå ñ ýòèìè çâóêîâûìè ñèñòåìàìè, ÷òî ïåðåõîä îò îäíîé èç íèõ ê äðóãîé òðåáóåò ìèíèìàëüíûõ èçìåíåíèé â êîäå ïðîãðàììû (à ÷àñòî âîîáùå íå òðåáóåò íèêàêèõ èçìåíåíèé). Ïðè ðàáîòå ñ áàçîâîé çâóêîâîé ñèñòåìîé DirectSound3D ôóíêöèè FMOD çàìåòíî îáëåã÷àþò óïðàâëåíèå îáú¸ìíûìè èñòî÷íèêàìè çâóêà, óïðîùàþò èõ èíèöèàëèçàöèþ, âîñïðîèçâåäåíèå è ïîçèöèîíèðîâàíèå. Ïðîñòîòà ïðîãðàììèðîâàíèÿ FMOD (â ñðàâíåíèè ñ ïðîãðàììèðîâàíèåì áàçîâûõ çâóêîâûõ ñèñòåì) ÿâëÿåòñÿ âàæíûì äîñòîèíñòâîì ýòîãî API (Î ïðîãðàììèðîâàíèè íåïîñðåäñòâåííî DirectSound3D ìîæíî ïðî÷èòàòü â ñòàòüå Ïðîãðàììèðîâàíèå îáú¸ìíîãî çâóêà â DirectSound3D).

Äðóãèì äîñòîèíñòâîì FMOD ÿâëÿåòñÿ ë¸ãêîñòü óñòàíîâêè - äîñòàòî÷íî ðàçìåñòèòü â ñèñòåìíîé ïàïêå èëè â ïàïêå, èç êîòîðîé çàïóñêàåòñÿ ïðèëîæåíèå, dll áèáëèîòåêó, ÷òîáû ôóíêöèè FMOD ñòàëè äîñòóïíû.  âåðñèè 3.74, êðîìå îáû÷íîé äëÿ Windows 32-ðàçðÿäíîé dll, ïîñòàâëÿåòñÿ 64-ðàçðÿäíàÿ áèáëèîòåêà FMOD.

FMOD ñîäåðæèò ïîäðîáíóþ äîêóìåíòàöèþ è ïðèìåðû (âìåñòå ñ çàãîëîâî÷íûìè è äðóãèìè ñëóæåáíûìè ôàéëàìè) äëÿ VisualC, BorlandC, Watcom C, Borland Delphi è VisualBasic. Äëÿ íåêîììåð÷åñêèõ ïðèëîæåíèé áèáëèîòåêà FMOD ïðåäîñòàâëÿåòñÿ áåñïëàòíî.

Ê íåäîñòàòêàì FMOD ñëåäóåò îòíåñòè îòñóòñòâèå òàêèõ âîçìîæíîñòåé (êîòîðûå ðåàëèçîâàíû â DirectSound3D), êàê ñîçäàíèå íàïðàâëåííûõ èñòî÷íèêîâ çâóêà è ñîçäàíèå çàâèñèìûõ èñòî÷íèêîâ çâóêà (ïî êðàéíåé ìåðå, â íàáîðå ôóíêöèé FMOD íå ïðåäñòàâëåíû ôóíêöèè, óñòàíàâëèâàþùèå äàííûå ïàðàìåòðû ïðîñòðàíñòâåííîé îáðàáîòêè çâóêà).

Ìîäåëü ïðîñòðàíñòâà â FMOD

Ìîäåëü ïðîñòðàíñòâà (ñèñòåìà êîîðäèíàò), èñïîëüçóåìàÿ äëÿ ðàçìåùåíèÿ èñòî÷íèêîâ 3D çâóêà, àíàëîãè÷íà ìîäåëè ïðîñòðàíñòâà â DirectSound3D. Çäåñü èñïîëüçóåòñÿ ëåâîñòîðîííÿÿ äåêàðòîâà ñèñòåìà êîîðäèíàò, ñîñòîÿùàÿ èç òð¸õ îðòîãîíàëüíûõ êîîðäèíàòíûõ îñåé. Îñü X (èêñ) íàïðàâëåíà âïðàâî; îñü Y (èãðåê) íàïðàâëåíà ââåðõ; îñü Z (çýò) íàïðàâëåíà âïåðåä (òî åñòü â ìîíèòîð, åñëè ñèäåòü ëèöîì ê íåìó). Ðàññòîÿíèå èçìåðÿåòñÿ â ìåòðàõ, íî ìîæíî óñòàíîâèòü äðóãóþ åäèíèöó èçìåðåíèÿ äëèí, çàäàâ ñîîòíîøåíèå ìåæäó ìåòðîì è íîâîé åäèíèöåé èçìåðåíèÿ. Ëþáàÿ òî÷êà â ïðîñòðàíñòâå çàäàåòñÿ ñâîèìè êîîðäèíàòàìè, êîòîðûå çàïèñûâàþòñÿ â ïîñëåäîâàòåëüíîñòè X, Y, Z. Êîîðäèíàòû ìîãóò ïðèíèìàòü êàê ïîëîæèòåëüíûå, òàê è îòðèöàòåëüíûå çíà÷åíèÿ. Êîîðäèíàòíóþ òðèàäó XYZ, õàðàêòåðèçóþùóþ ïîëîæåíèå òî÷êè â ïðîñòðàíñòâå, ìîæíî ðàññìàòðèâàòü êàê âåêòîð, íà÷àëî êîòîðîãî íàõîäèòñÿ â íà÷àëå îòñ÷åòà, òî åñòü â òî÷êå ñ êîîðäèíàòàìè (0, 0, 0), è êîíå÷íîé òî÷êîé ñ êîîðäèíàòàìè (X, Y, Z). Êðîìå âåêòîðîâ ïîëîæåíèÿ, â FMOD èñïîëüçóþòñÿ âåêòîðû ñêîðîñòè, íåîáõîäèìûå äëÿ âû÷èñëåíèÿ äîïëåðîâñêîãî ñìåùåíèÿ â ñïåêòðå çâóêà äâèæóùèõñÿ èñòî÷íèêîâ. Âåêòîð ñêîðîñòè çàäàåòñÿ òðåìÿ êîîðäèíàòàìè ñâîåé êîíå÷íîé òî÷êè (íà÷àëüíîé òî÷êîé âåêòîðà ñêîðîñòè ñ÷èòàåòñÿ òî÷êà (0, 0, 0)). Ñëåäóåò çàìåòèòü, ÷òî FMOD (êàê è DirectSound3D) íå çàíèìàåòñÿ ðàñ÷åòîì êîîðäèíàò äâèæóùåãîñÿ îáúåêòà. Ýòó çàäà÷ó äîëæåí ðåøàòü ïðîãðàììèñò, ïåðåäàâàÿ ôóíêöèÿì FMOD äàííûå, íåîáõîäèìûå äëÿ ìîäåëèðîâàíèÿ èñêëþ÷èòåëüíî çâóêîâîé êàðòèíû â êîíêðåòíîé òî÷êå ïðîñòðàíñòâà è â êîíêðåòíûé ìîìåíò. Òî åñòü ïî ñóòè FMOD (êàê è DirectSound3D) ðàññ÷èòûâàåò ñòàòè÷åñêóþ çâóêîâóþ êàðòèíó, êîòîðóþ ïðîãðàììèñò ìîæåò ñäåëàòü äèíàìè÷íîé äëÿ ñëóøàòåëÿ (èãðîêà), ÷àñòî ìåíÿÿ ïîëîæåíèå èñòî÷íèêîâ çâóêà.

 òåõ ôóíêöèÿõ FMOD, äëÿ êîòîðûõ â êà÷åñòâå ïàðàìåòðà äîëæåí ïåðåäàâàòüñÿ âåêòîð, èñïîëüçóåòñÿ óêàçàòåëü íà ñòðóêòóðó, ñîñòîÿùóþ èç òð¸õ âåùåñòâåííûõ (float) ÷èñåë, èëè íà ìàññèâ, ñîñòîÿùèé èç òð¸õ âåùåñòâåííûõ (float) ÷èñåë. Òî åñòü äâå ñëåäóþùèå êîíñòðóêöèè áóäóò îäèíàêîâî âîñïðèíÿòû ôóíêöèÿìè FMOD:

/* ìàñèâ */
float pos[3] = {10.0f, 2.0f, 4.2f};
/* ñòðóêòóðà */
struct VECTOR
{
float X;
float Y;
float Z;
};
VECTOR pos = {10.0f, 2.0f, 4.2f};

Ìîäåëü ïðîñòðàíñòâà â FMOD âêëþ÷àåò åùå íåêîòîðûå ïàðàìåòðû ñðåäû, âëèÿþùèå íà ðàñïðîñòðàíåíèå çâóêîâûõ âîëí. Ñ ïîìîùüþ ôóíêöèé FMOD ìîæíî óñòàíîâèòü ñòåïåíü çàòóõàíèÿ çâóêà è ñòåïåíü âûðàæåííîñòè äîïëåðîâñêîãî ýôôåêòà.

Îáúåêòû çâóêîâîé êàðòèíû â FMOD

 FMOD ñóùåñòâóþò äâà âèäà îáúåêòîâ òð¸õìåðíîãî çâóêîâîãî ïðîñòðàíñòâà: èñòî÷íèêè çâóêà è ñëóøàòåëè.  îòëè÷èå îò DirectSound3D, FMOD ïîääåðæèâàåò ìîäåëü íåñêîëüêèõ ñëóøàòåëåé. Âî âñåì îñòàëüíîì îáå ñèñòåìû àíàëîãè÷íû.

Èñòî÷íèêè çâóêà â FMOD ìîãóò áûòü òîëüêî òî÷å÷íûìè è íåíàïðàâëåííûìè, ÷òî îçíà÷àåò îòñóòñòâèå ó èñòî÷íèêà ñîáñòâåííûõ ðàçìåðîâ â è âñåíàïðàâëåííîñòü ðàñïðîñòðàíåíèÿ çâóêà îò ýòîãî èñòî÷íèêà. Ïîëîæåíèå ñëóøàòåëÿ, íàïðîòèâ, ÿâëÿåòñÿ îðèåíòèðîâàííûì. Äëÿ ýòîãî çàäàþòñ íàïðàâëåíèå äâóõ îðòîãîíàëüíûõ âåêòîðîâ åäèíè÷íîãî ðàçìåðà. Ïåðâûé âåêòîð îðèåíòèðóåò íàïðàâëåíèå ëèöà, òî åñòü óêàçûâàåò, êóäà ñìîòðèò ñëóøàòåëü. Âòîðîé âåêòîð âñåãäà íàïðàâëåí èç ìàêóøêè ââåðõ, òî åñòü óêàçûâàåò íàïðàâëåíèå âåðòèêàëüíîé îñè ñëóøàòåëÿ. Ìîäóëü êàæäîãî èç ýòèõ âåêòîðîâ ðàâåí åäèíèöå èçìåðåíèÿ äëèíû, ïîýòîìó îíè íîñÿò íàçâàíèÿ åäèíè÷íûõ (Ìîäóëü âåêòîðà âû÷èñëÿåòñÿ êàê êîðåíü êâàäðàòíûé èç ñóììû êâàäðàòîâ äëèí åãî ïðîåêöèé íà îñè êîîðäèíàò).

Ôóíêöèè äëÿ ðàáîòû ñ 3D çâóêîì

äëÿ ïðîñòîòû èçëîæåíèÿ íèæå ïðèâîäÿòñÿ íå òîëüêî ôóíêöèè FMOD, îòâå÷àþùèå íåïîñðåäñòâåííî çà ñîçäàíèå îáú¸ìíîãî çâóêà, íî è âñå òå ôóíêöèè, êîòîðûìè íåîáõîäèìî âîñïîëüçîâàòüñÿ ïðîãðàììèñòó, ÷òîáû ðàáîòàòü ñ áèáëèîòåêîé FMOD. Ïðè÷åì â ñïèñêå ôóíêöèè ðàñïîëîæåíû â òîé îðèåíòèðîâî÷íîé ïîñëåäîâàòåëüíîñòè, â êîòîðîé èõ ñëåäóåò âûçûâàòü â ïðîãðàììå, âçàèìîäåéñòâóþùåé ñ FMOD.  äîêóìåíòàöèè, êîòîðàÿ âõîäèò â êîìïëåêò FMOD âñå ïðèâîäèìûå íèæå ôóíêöèè ïîìåùåíû â ðàçäåë "FSOUND API Reference".

  • FSOUND_GetVersion() - âîçâðàùàåò âåðñèþ áèáëèîòåêè FMOD, óñòàíîâëåííîé íà êîìïüþòåðå. Âîçâðàùàåìîå çíà÷åíèå ñëåäóåò ñðàâíèòü ñ êîíñòàíòîé FMOD_VERSION, êîòîðàÿ õðàíèò íîìåð âåðñèè FMOD, äëÿ êîòîðîé áûëà ñêîìïèëèðîâàíà ïðîãðàììà.
  • FSOUND_SetOutput () / FSOUND_GetOutput () - âûáðàòü/ïîëó÷èòü áàçîâóþ çâóêîâóþ ñèñòåìó (Windows Multimedia, DirectSound, A3D è ò.ï.). Âûáîð áàçîâîé ñèñòåìû äîëæåí ïðîèçâîäèòñÿ äî âûçîâà ôóíêöèè FSOUND_Init().
  • FSOUND_SetDriver () / FSOUND_GetDriver () - âûáðàòü/ïîëó÷èòü íîìåð óñòðîéñòâà âûâîäà (çâóêîâîé êàðòû). Âûáîð óñòðîéñòâà äîëæåí ïðîèçâîäèòñÿ äî âûçîâà ôóíêöèè FSOUND_Init().
  • FSOUND_SetMixer () /FSOUND_GetMixer () - âûáðàòü/ïîëó÷èòü òèï öèôðîâîãî ìèêøåðà. Âûáîð ìèêøåðà äîëæåí ïðîèçâîäèòñÿ äî âûçîâà ôóíêöèè FSOUND_Init(). Îïðåäåëåíèå òèïà ìèêøåðà íå ÿâëÿåòñÿ îáÿçàòåëüíûì, òàê êàê FMOD ñàìîñòîÿòåëüíî îïðåäåëèò ëó÷øèé èç èìåþùèõñÿ âàðèàíòîâ.
  • FSOUND_Init() - èíèöèàëèçèðóåò çâóêîâóþ ñèñòåìó FMOD.
  • FSOUND_Sample_Load () - çàãðóæàåò â ïàìÿòü è äåêîäèðóåò çâóêîâîé ôàéë (ïîääåðæèâàþòñÿ .wav, .mp2, .mp3, .ogg, .raw è äð.).
  • FSOUND_3D_SetDistanceFactor () - ïîçâîëÿåò óñòàíîâèòü åäèíèöû èçìåðåíèÿ äëèí, îòëè÷íûå îò ìåòðîâ.
  • FSOUND_3D_SetDopplerFactor () - ïîçâîëÿåò óñòàíîâèòü äîïëåðîâñêîå ñìåùåíèå. Áàçîâîå çíà÷åíèå (1.0) ñîîòâåòñòâóåò ñêîðîñòè çâóêà 340 ì/ñ.
  • FSOUND_3D_SetRolloffFactor () - ïîçâîëÿåò óñòàíîâèòü óðîâåíü ïîòåðü ýíåðãèè çâóêîâîé âîëíû (çàòóõàíèÿ). Áàçîâîå çíà÷åíèå (1.0) ñîîòâåòñòâóåò íîðìàëüíûì óñëîâèÿì.
  • FSOUND_PlaySoundEx () - ïðîèãðûâàåò çâóêîâîé ôàéë, çàãðóæåííûé â ïàìÿòü, ÷åðåç çâóêîâîé êàíàë.
  • FSOUND_3D_SetAttributes () / FSOUND_3D_GetAttributes () - óñòàíîâèòü/ïîëó÷èòü âåêòîð ïîëîæåíèÿ è âåêòîð ñêîðîñòè èñòî÷íèêà çâóêà.
  • FSOUND_3D_SetMinMaxDistance () / FSOUND_3D_GetMinMaxDistance () óñòàíîâèòü / ïîëó÷èòü ìèíèìàëüíîå è ìàêñèìàëüíîå ðàññòîÿíèå ñëûøèìîñòè èñòî÷íèêà çâóêà. Ìèíèìàëüíûì íàçûâàåòñÿ òàêîå ðàññòîÿíèå îò èñòî÷íèêà çâóêà äî ñëóøàòåëÿ, ïðè óìåíüøåíèè êîòîðîãî ãðîìêîñòü çâóêà áîëüøå íå âîçðàñòàåò, à îñòàåòñÿ íà òîì çíà÷åíèè, êîòîðîãî îíà äîñòèãëà íà ìèíèìàëüíîì ðàññòîÿíèè. Óñòàíàâëèâàÿ ðàçíûå ìèíèìàëüíûå ðàññòîÿíèÿ, íàïðèìåð, äëÿ ñàìîëåòà è øìåëÿ, ìîæíî ñäåëàòü èõ îäèíàêîâî çàìåòíûìè íà ñëóõ, íåñìîòðÿ íà òî, ÷òî ãóë ìîòîðà áóäåò âîñïðèíèìàòüñÿ êàê áîëåå ìîùíûé çâóê. Ìàêñèìàëüíûì íàçûâàåòñÿ òàêîå ðàññòîÿíèå îò èñòî÷íèêà çâóêà äî ñëóøàòåëÿ, íà÷èíàÿ ñ êîòîðîãî ãðîìêîñòü çâóêà áîëüøå íå óìåíüøàåòñÿ, à îñòàåòñÿ íà óðîâíå, êîòîðûé îíà äîñòèãëà íà ìàêñèìàëüíîì ðàññòîÿíèè. Ýòî îçíà÷àåò, ÷òî êàê áû äàëåêî íå íàõîäèëñÿ èñòî÷íèê çâóêà, îí áóäåò ñëûøåí.
  • FSOUND_SetPaused () - ïðèîñòàíàâëèâàåò / âîçîáíîâëÿåò âîñïðîèçâåäåíèå çâóêà â êàíàëå.
  • FSOUND_3D_Listener_SetAttributes () / FSOUND_3D_Listener_GetAttributes () - óñòàíîâèòü/ ïîëó÷èòü âåêòîð ïîëîæåíèÿ, âåêòîð ñêîðîñòè è âåêòîðû îðèåíòàöèè ñëóøàòåëÿ.
  • FSOUND_Update () -îáíîâèòü ñîñòîÿíèå çâóêîâîãî ìèêøåðà, òî åñòü îáíîâèòü ñîñòîÿíèå çâóêîâîé ïàíîðàìû, ïîñëå ÷åãî âñå èçìåíåíèÿ â ïîëîæåíèè ñëóøàòåëÿ èëè èñòî÷íèêîâ çâóêà âñòóïàþò â ñèëó.
  • FSOUND_Sample_Free () - îñâîáîæäàåò ïàìÿòü îò çâóêîâûõ äàííûõ, çàãðóæåííûõ ôóíêöèåé FSOUND_Sample_Load().
  • FSOUND_Close () - âûãðóæàåò çâóêîâóþ ñèñòåìó FMOD.

Äàííûé ñïèñîê ÿâëÿåòñÿ ìèíèìàëüíî íåîáõîäèìûì è íå âêëþ÷àåò ðÿä ôóíêöèé, ïîçâîëÿþùèõ ïîëó÷àòü äîïîëíèòåëüíóþ èíôîðìàöèþ î çâóêîâîé êàðòå, ïîääåðæèâàåìûõ àëãîðèòìàõ îáðàáîòêè çâóêà è ò.ï., à òàêæå óïðàâëÿòü íåêîòîðûìè ïàðàìåòðàìè âîñïðîèçâåäåíèÿ çâóêà.

Àëãîðèòì èñïîëüçîâàíèÿ FMOD â èãðîâûõ ïðîãðàììàõ

 öåíòðå íàøåãî âíèìàíèÿ áóäóò èãðû, èñïîëüçóþùèå îáú¸ìíûé (3D) çâóê. Êàê ïðàâèëî, â èãðàõ ñóùåñòâóåò îñíîâíîé öèêë èãðû, âíóòðè êîòîðîãî ïðîèñõîäèò ïåðåìåùåíèå èãðîâûõ îáúåêòîâ â ïðîñòðàíñòâå. Òàêîå ïåðåìåùåíèå ìîæåò áûòü âûçâàíî äåéñòâèÿìè èãðîêà (íàïðèìåð, â àâòîñèìóëÿòîðå ýòî ìîæåò áûòü ïîâîðîò ðóëåâîãî êîëåñà âïðàâî èëè âëåâî) èëè èçìåíåíèåì èãðîâîé ñèòóàöèè (íàïðèìåð, â "ýêøåíå" ìîæåò ïðèáëèçèòñÿ ìîíñòð). Ðàññ÷èòàâ íîâûå êîîðäèíàòû îáúåêòîâ, ñëåäóåò èçìåíèòü è ïîëîæåíèå èñòî÷íèêîâ çâóêà òàê, ÷òîáû îíè ñîîòâåòñòâîâàëè íîâîìó ïîëîæåíèþ îáúåêòîâ â èãðîâîì ïðîñòðàíñòâå.

Èãðîâîìó öèêëó, êàê ïðàâèëî, ïðåäøåñòâóåò òà ÷àñòü ïðîãðàììû, â êîòîðîé ïðîèñõîäèò èíèöèàëèçàöèÿ ïåðåìåííûõ, çàãðóçêà íåîáõîäèìûõ áèáëèîòåê è ðåñóðñîâ. Ïðè èñïîëüçîâàíèè FMOD, â ýòîé ÷àñòè äîëæíû ðàñïîëàãàòüñÿ ôóíêöèè: FSOUND_SetOutput, FSOUND_SetDriver è FSOUND_SetMixer.  êà÷åñòâå ïàðàìåòðà äëÿ àâòîìàòè÷åñêîãî îïðåäåëåíèÿ áàçîâîé çâóêîâîé ñèñòåìû â ôóíêöèþ FSOUND_SetOutput ìîæíî ïåðåäàòü -1 (0FFFFFFFFh).

Ïîñëå óñïåøíîé èíèöèàëèçàöèè FMOD íåîáõîäèìî â ñîîòâåòñòâèè ñî ñöåíàðèåì èãðû ðàçìåñòèòü â ïàìÿòè çâóêîâûå äàííûå. Ôóíêöèÿ FSOUND_Sample_Load, îòâå÷àþùàÿ çà ýòîò ïðîöåññ, ïîääåðæèâàåò íåñêîëüêî çâóêîâûõ ôîðìàòîâ è çàãðóçêà, ñêàæåì, .mp3 ôàéëà ñ òî÷êè çðåíèÿ ïðîãðàììèñòà íè÷åì íå îòëè÷àåòñÿ îò çàãðóçêè ôàéëà â ôîðìàòå wav. Çäåñü ïîëíîñòüþ ïðîÿâëÿþòñÿ äîñòîèíñòâà áèáëèîòåêè FMOD, ïîçâîëÿþùåé óïðîñòèòü óòîìèòåëüíóþ ïðîöåäóðó ñîçäàíèÿ çâóêîâûõ áóôåðîâ è çàãðóçêè â íèõ äàííûõ, õàðàêòåðíóþ äëÿ DirectSound. Ðåçóëüòàòîì ðàáîòû FSOUND_Sample_Load áóäåò óêàçàòåëü íà îáðàçåö çâóêà, ðàçìåùåííûé â ïàìÿòè. Åñëè îáðàòèòüñÿ ê òåðìèíîëîãèè DirectSound, òî ýòî áóäåò àíàëîã âòîðè÷íîãî çâóêîâîãî áóôåðà. Óêàçàííûé îáðàçåö çâóêà ìîæåò áûòü èñïîëüçîâàí äëÿ ñîçäàíèÿ íåñêîëüêèõ èñòî÷íèêîâ 3D çâóêà, ïðè ýòîì íåò íåîáõîäèìîñòè ñîçäàâàòü äîïîëíèòåëüíûå êîïèè ýòîãî îáðàçöà.

Òåïåðü, êîãäà íåîáõîäèìûå äàííûå çàãðóæåíû, ìîæíî ïðèñòóïàòü ê ôîðìèðîâàíèþ òð¸õìåðíîé çâóêîâîé êàðòèíû. Íåîáõîäèìî ïîìíèòü, ÷òî èçìåíåíèå âåêòîðà ïîëîæåíèÿ è âåêòîðà ñêîðîñòè, à òàêæå ìíîãèõ èíûõ õàðàêòåðèñòèê èñòî÷íèêà çâóêà âîçìîæíî òîëüêî íåïîñðåäñòâåííî âî âðåìÿ âîñïðîèçâåäåíèÿ çâóêà ôóíêöèÿìè FSOUND_PlaySound è FSOUND_PlaySoundEx, ïîýòîìó, ïðåæäå ÷åì ïîìåñòèòü èñòî÷íèê çâóêà â êàêóþ-ëèáî òî÷êó ïðîñòðàíñòâà, âû äîëæíû íà÷àòü âîñïðîèçâåäåíèå ýòîãî çâóêà. Îäíàêî ïðè âûçîâå óêàçàííûõ ôóíêöèé çâóê áóäåò âîñïðîèçâîäèòüñÿ â òîé òî÷êå, ãäå íàõîäèòñÿ ñëóøàòåëü (Listener), ÷òî ìîæåò íàðóøèòü ñöåíó èãðû (íàïðèìåð, ìîíñòð, êîòîðûé äîëæåí ïðèáëèæàòüñÿ èç ñàìîãî äàëüíåãî çàêîóëêà, âäðóã çàðû÷èò ïîä óõîì ó èãðîêà). ×òîáû èçáåæàòü ïîäîáíîãî êàçóñà, â ôóíêöèè FSOUND_PlaySoundEx() ïðåäóñìîòðåí ñïåöèàëüíûé ïàðàìåòð, êîòîðûé ñðàçó æå ïðèîñòàíàâëèâàåò âîñïðîèçâåäåíèå çâóêà. Ìîë÷àùèé èñòî÷íèê ìîæíî, áåç ðèñêà íàðóøèòü ñöåíó èãðû, ïîìåñòèòü â íóæíîå ìåñòî è âîçîáíîâèòü âîñïðîèçâåäåíèå çâóêà. Äëÿ òîãî ÷òîáû èçìåíåíèÿ â çâóêîâîé êàðòèíå âñòóïèëè â ñèëó, íåîáõîäèìî âûçâàòü ôóíêöèþ FSOUND_Update.

Ñëåäóåò ñêàçàòü, ÷òî â ïîíÿòèÿõ FMOD âîñïðîèçâåäåíèå çâóêà ïðîèñõîäèò ÷åðåç êàíàë (channel), ïîýòîìó âñå, ÷òî ïðîãðàììèñò ñîáèðàåòñÿ ñäåëàòü ñ èñòî÷íèêîì 3D çâóêà, íåîáõîäèìî âûïîëíÿòü, ïîëüçóÿñü ôóíêöèÿìè, êîòîðûå ðàáîòàþò ñ êàíàëîì. Ïåðâûì ïàðàìåòðîì â òàêèõ ôóíêöèÿõ âûñòóïàåò íîìåð êàíàëà.

Ñèíòàêñèñ âûçîâà ôóíêöèè FSOUND_PlaySoundEx ñëåäóþùèé:

int F_API FSOUND_PlaySoundEx(
int channel,
FSOUND_SAMPLE *sptr,
FSOUND_DSPUNIT *dspunit,
signed char startpaused
);

 êà÷åñòâå ïàðàìåòðîâ ýòà ôóíêöèÿ ïîëó÷àåò íîìåð êàíàëà (channel), ÷åðåç êîòîðûé áóäåò âîñïðîèçâîäèòñÿ çâóê,; óêàçàòåëü (äåñêðèïòîð sptr) íà îáðàçåö çâóêà, ðàçìåùåííûé â ïàìÿòè; óêàçàòåëü (äåñêðèïòîð dspunit) íà áëîê êàíàëîâ, ê êîòîðîìó äîëæåí ïðèñîåäèíèòüñÿ âíîâü ñîçäàâàåìûé êàíàë (ýòîò ïàðàìåòð ìîæåò èìåòü çíà÷åíèå NULL); ôëàã ïðèîñòàíîâêè âîñïðîèçâåäåíèÿ (paused), êîòîðûé äîëæåí áûòü TRUE, ÷òîáû âîñïðîèçâåäåíèå çâóêà ñðàçó æå áûëî ïðèîñòàíîâëåíî.

Åñëè íåîáõîäèìî ñîçäàòü íîâûé êàíàë, òî â ïàðàìåòðå channel ïåðåäàåòñÿ êîíñòàíòà FSOUND_FREE. Åñëè íåîáõîäèìî, ÷òîáû çâóê âîñïðîèçâîäèëñÿ âî âñåõ ñóùåñòâóþùèõ êàíàëàõ, òî â channel ïåðåäàåòñÿ êîíñòàíòà FSOUND_ALL.

Ôóíêöèÿ âîçâðàùàåò íîìåð (äåñêðèïòîð) êàíàëà, ÷åðåç êîòîðûé âîñïðîèçâîäèòñÿ çâóê. Åñëè âîçíèêëà îøèáêà, òî ôóíêöèÿ âîçâðàùàåò -1 (0FFFFFFFFH). Íîìåð (äåñêðèïòîð) êàíàëà íåîáõîäèì äëÿ ðàáîòû ñ ôóíêöèÿìè êàíàëüíîãî óðîâíÿ, íàïðèìåð, FSOUND_3D_SetAttributes.

Òàêèì îáðàçîì, ñîçäàíèå è ïîçèöèîíèðîâàíèå èñòî÷íèêà çâóêà ïðîãðàììíî ìîæåò áûòü ðåàëèçîâàíî òàê:

FSOUND_SAMPLE *samp1 = NULL;
int channel1 = -1;
/* ïðîâåðÿåì âåðñèþ FMOD */
if (FSOUND_GetVersion() < FMOD_VERSION)
{
/* îáðàáîòêà îøèáêè */
return 1;
}
/* âûáèðàåì áàçîâóþ çâóêîâóþ ñèñòåìó DirectSound */
FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND);
/* âûáèðàåì çâóêîâóþ êàðòó ïî óìîë÷àíèþ */
FSOUND_SetDriver(0);
/* ïîçâîëÿåì FMOD âûáðàòü ìèêøåð */
FSOUND_SetMixer(FSOUND_MIXER_AUTODETECT);
/* èíèöèàëèçèðóåì FMOD */
/* ÷àñòîòà, ê êîòîðîé áóäóò ïðèâîäèòñÿ âñå çâóêè â ìèêøåðå, - 22050 Ãö */
/* ìàêñèìàëüíîå ÷èñëî ïðîãðàììíûõ êàíàëîâ - 32 */
if (!FSOUND_Init(22050, 32, 0))
{
/* îáðàáîòêà îøèáêè */
return 1;
}
/* çàãðóæàåì â ïàìÿòü çâóêîâîé ôðàãìåíò èç ôàéëà myfile.wav */
/* êîíñòàíòà FSOUND_HW3D óêàçûâàåò, ÷òî íåîáõîäèìî âêëþ÷èòü àïïàðàòíóþ ïîääåðæêó 3D çâóêà */
samp1 = FSOUND_Sample_Load(FSOUND_FREE, "myfile.wav", FSOUND_HW3D, 0, 0);
if (!samp1)
{
/* îáðàáîòêà îøèáêè */
return 1; 
}
/* óñòàíàâëèâàåì öèêëè÷åñêîå âîñïðîèçâåäåíèå, ò.å. */
/* èñòî÷íèê ñëûøåí âñåãäà */
FSOUND_Sample_SetMode(samp1, FSOUND_LOOP_NORMAL);
/* óêàçûâàåì ïîçèöèþ è ñêîðîñòü èñòî÷íèêà */
float pos[3] = { -10.0f, -20.0f, 0.5f };
float vel[3] = { 0,0,0 };
/* ñîçäàåì íîâûé êàíàë äëÿ âîñïðîèçâåäåíèÿ çâóêà */
/* ñðàçó æå ïðèîñòàíàâëèâàåì âîñïðîèçâåäåíèå */
channel1 = FSOUND_PlaySoundEx(FSOUND_FREE, samp1, NULL, TRUE);
if (channel1 == -1)
{
/* îáðàáîòêà îøèáêè */
return 1; 
}
/* ïîìåùàåì èñòî÷íèê çâóêà â íóæíóþ òî÷êó */
FSOUND_3D_SetAttributes(channel1, pos, vel);
/* çäåñü ìîæåò ïðîèñõîäèòü èçìåíåíèå ïîçèöèè ñëóøàòåëÿ */
. . .
/* îáíîâëÿåì çâóêîâóþ êàðòèíó */
FSOUND_Update();
/* âîçîáíîâëÿåì âîñïðîèçâåäåíèå */
FSOUND_SetPaused(channel1, FALSE);
. . .

Ñëåäóåò ïîìíèòü, ÷òî ôóíêöèè FSOUND_PlaySound è FSOUND_PlaySoundEx ïîìåùàþò èñòî÷íèê çâóêà â òåêóùóþ ïîçèöèþ ñëóøàòåëÿ, ïîýòîìó , åñëè â ïàðàìåòðå channel ýòèõ ôóíêöèé óêàçàí íîìåð (äåñêðèïòîð) ñóùåñòâóþùåãî êàíàëà, òî, íåñìîòðÿ íà òî, ÷òî äëÿ ýòîãî êàíàëà ôóíêöèåé FSOUND_3D_SetAttributes áûëà óñòàíîâëåíà ïîçèöèÿ, îòëè÷íàÿ îò ïîçèöèè ñëóøàòåëÿ, âñå ðàâíî èñòî÷íèê çâóêà ïåðåìåñòèòñÿ â ïîçèöèþ ñëóøàòåëÿ. ×òîáû èçáåæàòü èñêàæåíèÿ çâóêîâîé êàðòèíû, íåîáõîäèìî ïåðåä âûçîâîì FSOUND_PlaySoundEx ñîõðàíèòü ïîçèöèþ è ñêîðîñòü èñòî÷íèêà çâóêà â ñïåöèàëüíûõ ïåðåìåííûõ, ïîëó÷èâ ýòè çíà÷åíèÿ ôóíêöèåé FSOUND_3D_GetAttributes. Ïîñëå ÷åãî âûçâàòü FSOUND_PlaySoundEx ñ ïðèîñòàíîâêîé âîñïðîèçâåäåíèÿ; çàòåì ïåðåìåñòèòü èñòî÷íèê â íóæíóþ òî÷êó, âîñïîëüçîâàâøèñü ñîõðàíåííûìè çíà÷åíèÿìè, à óæ ïîòîì ïðîäîëæèòü âîñïðîèçâåäåíèå. Óêàçàííàÿ ïîñëåäîâàòåëüíîñòü äåéñòâèé, êðîìå âñåãî ïðî÷åãî, íàïðÿìóþ îòíîñèòñÿ ê îäíîêðàòíî ïðîèãðûâàåìûì çâóêàì (òî åñòü ê òàêèì èñòî÷íèêàì, êîòîðûå íå èçäàþò çâóê íåïðåðûâíî, à çâó÷àò ëèøü ïðè íàñòóïëåíèè îïðåäåëåííîãî ñîáûòèÿ â èãðå).

Äëÿ èçìåíåíèÿ ïîçèöèè, ñêîðîñòè è îðèåíòàöèè ñëóøàòåëÿ â ïðîñòðàíñòâå ñëåäóåò èñïîëüçîâàòü ôóíêöèþ FSOUND_3D_Listener_SetAttributes. Âîò åå ñèíòàêñèñ:

void F_API FSOUND_3D_Listener_SetAttributes(
const F_FLOAT_API *pos,
const F_FLOAT_API *vel,
F_FLOAT_API fx,
F_FLOAT_API fy,
F_FLOAT_API fz,
F_FLOAT_API tx,
F_FLOAT_API ty,
F_FLOAT_API tz
);

 êà÷åñòâå ïàðàìåòðîâ ýòà ôóíêöèÿ ïîëó÷àåò óêàçàòåëü íà òðèàäó êîîðäèíàò ïîçèöèè (pos), óêàçàòåëü íà âåêòîð ñêîðîñòè (vel), X, Y è Z ñîñòàâëÿþùèå åäèíè÷íîãî âåêòîðà, îïðåäåëÿþùåãî ôðîíòàëüíóþ îðèåíòàöèþ ãîëîâû ñëóøàòåëÿ (fx, fy, fz); X, Y è Z ñîñòàâëÿþùèå åäèíè÷íîãî âåêòîðà, îïðåäåëÿþùåãî âåðòèêàëüíóþ îðèåíòàöèþ ãîëîâû ñëóøàòåëÿ (tx, ty, tz). Íåñìîòðÿ íà òèï void, ôóíêöèÿ, ñîãëàñíî îôèöèàëüíîé äîêóìåíòàöèè, âîçâðàùàåò TRUE, åñëè åå âûïîëíåíèå áûëî óñïåøíûì, è FALSE â ñëó÷àå îøèáêè.

 îòëè÷èå îò DirectSound3D, â FMOD ìîæåò áûòü íå îäèí, à íåñêîëüêî ñëóøàòåëåé. Ýòî ñäåëàíî äëÿ èãðîâûõ ïðèñòàâîê, ãäå îäíî èãðîâîå óñòðîéñòâî ìîãóò èñïîëüçîâàòü îäíîâðåìåííî íåñêîëüêî èãðîêîâ. Âûáîð òåêóùåãî ñëóøàòåëÿ ïðîèçâîäèòñÿ ïðè ïîìîùè ôóíêöèè FSOUND_3D_Listener_SetCurrent.

Êîãäà èãðà çàâåðøåíà è â çàêëþ÷èòåëüíîì ñåãìåíòå êîäà ïðîãðàììû ïðîèñõîäèò îñâîáîæäåíèå ðåñóðñîâ, çàíÿòûõ ïðîãðàììîé, íåîáõîäèìî èñïîëüçîâàòü ôóíêöèè FSOUND_Sample_Free, êîòîðîé â êà÷åñòâå ïàðàìåòðà ïåðåäàåòñÿ óêàçàòåëü (äåñêðèïòîð) ôðàãìåíòà çâóêîâûõ äàííûõ â ïàìÿòè, è FSOUND_Close, êîòîðàÿ âûçûâàåòñÿ áåç ïàðàìåòðîâ è âûãðóæàåò çâóêîâóþ ñèñòåìó FMOD.

FSOUND_Sample_Free(samp1); 
FSOUND_Close();

Îáðàáîòêà îøèáîê

Áîëüøèíñòâî ôóíêöèé FMOD, åñëè èíîå íå îãîâîðåíî â äîêóìåíòàöèè, âîçâðàùàþò TRUE â ñëó÷àå óñïåøíîãî çàâåðøåíèÿ. Åñëè æå â ðàáîòå ôóíêöèè âîçíèêëà îøèáêà, òî âîçâðàùàåòñÿ FALSE. Äëÿ òîãî ÷òîáû ïîëó÷èòü äîïîëíèòåëüíóþ èíôîðìàöèþ îá îøèáêå, ñëåäóåò âîñïîëüçîâàòüñÿ ôóíêöèÿìè FSOUND_GetError è FMOD_ErrorString. Ïîñëåäíÿÿ ôóíêöèÿ ÿâëÿåòñÿ ìàêðîñîì, ïîýòîìó íåîáõîäèìî âêëþ÷èòü çàãîëîâî÷íûé ôàéë FMOD_errors.h.

Ôóíêöèÿ FSOUND_GetError íå òðåáóåò ïàðàìåòðîâ è âîçâðàùàåò êîä îøèáêè, âîçíèêøåé ïðè âûïîëíåíèè ôóíêöèè FMOD. Ìàêðîñ FMOD_ErrorString ïîëó÷àåò ýòîò êîä â êà÷åñòâå ïàðàìåòðà è âîçâðàùàåò òåêñòîâîå îïèñàíèå îøèáêè. Âîò ïðèìåð âûçîâà ýòèõ ôóíêöèé:

/* âûâîä ñîîáùåíèÿ îá îøèáêå â êîíñîëüíîì ðåæèìå */
printf("Error: %s\n", FMOD_ErrorString(FSOUND_GetError()));

Óïðàâëåíèå ðåñóðñàìè è çâóêîâûå ïëàòû íèæíåé öåíîâîé êàòåãîðèè

Ñåãîäíÿ ñóùåñòâóþò ðàçëè÷íûå ïî ïðîèçâîäèòåëüíîñòè è âîçìîæíîñòÿì çâóêîâûå êàðòû. Îäíè èç íèõ ñïîñîáíû ïîääåðæèâàòü äî 100 àïïàðàòíûõ êàíàëîâ äëÿ âîñïðîèçâåäåíèÿ 3D çâóêà, äðóãèå - íå áîëåå ÷åòûðåõ. Áûëî áû íåäàëüíîâèäíî ïðè ðàçðàáîòêå èãð îðèåíòèðîâàòüñÿ íà "ñëàáûå" çâóêîâûå êàðòû. Îäíàêî îøèáêà, êîòîðàÿ ìîæåò âîçíèêíóòü ïðè íåõâàòêå àïïàðàòíûõ êàíàëîâ â èãðå ñ áîëüøèì êîëè÷åñòâîì èñòî÷íèêîâ çâóêà, ìîæåò ñäåëàòü èãðó ñîâåðøåííî íåðàáîòîñïîñîáíîé íà óêàçàííîé ãðóïïå çâóêîâûõ êàðò.  êà÷åñòâå âûõîäà èç äàííîé ñèòóàöèè FMOD ïðåäëàãàåò èñïîëüçîâàòü ôóíêöèþ FSOUND_SetMinHardwareChannels.

Ýòà ôóíêöèÿ âûçûâàåòñÿ îäèí ðàç ïåðåä âûçîâîì FSOUND_Init è óñòàíàâëèâàåò ìèíèìàëüííîå êîëè÷åñòâî àïïàðàòíûõ êàíàëîâ, êîòîðîå äîëæíî ïîääåðæèâàòüñÿ çâóêîâîé êàðòîé. Ïîñëå ýòîãî ëèáî âñå èç óêàçàííîãî ïðè âûçîâå FSOUND_SetMinHardwareChannels ÷èñëà êàíàëîâ áóäóò âîñïðîèçâîäèòñÿ ñ èñïîëüçîâàíèåì àïïàðàòíûõ êàíàëîâ, ëèáî àïïàðàòíàÿ ïîääåðæêà èñïîëüçîâàòüñÿ íå áóäåò è ìèêøèðîâàíèå êàíàëîâ áóäåò ïðîèñõîäèòü ïðîãðàììíûì ïóòåì. Èíûìè ñëîâàìè, íàïðèìåð, åñëè ó âàñ 16 çâóêîâ è êàðòà èìååò òàêîå æå èëè áîëüøåå ÷èñëî àïïàðàòíûõ êàíàëîâ, òî âîñïðîèçâåäåíèå áóäåò èäòè ÷åðåç ýòè êàíàëû. Åñëè îêàæåòñÿ, ÷òî ó êàðòû âñåãî 4 êàíàëà, òî ñìåøèâàíèå âñåõ çâóêîâ áóäåò âûïîëíÿòüñÿ ïðîãðàììíî.

Ïîääåðæêà ïðèîðèòåòîâ

 FMOD ðåàëèçîâàíà ñèñòåìà ïðèîðèòåòîâ. Åñëè ìíîæåñòâî èñòî÷íèêîâ çâóêà äîëæíû âîñïðîèçâîäèòüñÿ íà îãðàíè÷åííîì ÷èñëå êàíàëîâ, òî íåêîòîðûå èç íèõ ìîãóò áûòü áîëåå âàæíûìè, ÷åì äðóãèå. Åñëè, íàïðèìåð, ãëàâíûì äåéñòâóþùèì ëèöîì â èãðå âûñòóïàåò ñòðåëîê, òî âîñïðîèçâåäåíèå çâóêà âûñòðåëà áûëî áû, âåðîÿòíî, ñàìûì âàæíûì. Òàê ÷òî ýòîìó èñòî÷íèêó çâóêà (âûñòðåë) ñëåäîâàëî áû óñòàíîâèòü ñàìûé âûñîêèé ïðèîðèòåò ïîñðåäñòâîì FSOUND_SetPriority. Ìåíåå âàæíûå çâóêè íå áóäóò âîñïðîèçâîäèòüñÿ, åñëè óæå çàíÿòû âñå äîñòóïíûå êàíàëû.

Çàêëþ÷åíèå

Èçëîæåííûé âûøå ìàòåðèàë ÿâëÿåòñÿ íåîáõîäèìûì äëÿ òîãî, ÷òîáû ïîçíàêîìèòüñÿ ñ âîçìîæíîñòÿìè FMOD â îáëàñòè ðàáîòû ñ îáú¸ìíûì çâóêîì è íà÷àòü èñïîëüçîâàòü ýòó áèáëèîòåêó â ñâîèõ ïðîãðàììàõ. Íî îäíîé ýòîé ñòàòüè íåäîñòàòî÷íî, ÷òîáû óçíàòü î âñåõ âîçìîæíîñòÿõ áèáëèîòåêè FMOD. Ñëåäóþùèì øàãîì ìîæåò ñòàòü èçó÷åíèå ïðèìåðîâ, âõîäÿùèõ â äèñòðèáóòèâíûé ïàêåò FMOD.



Ðàñïðîñòðàíåíèå ìàòåðèàëîâ ñàéòà îçíà÷àåò, ÷òî ðàñïðîñòðàíèòåëü ïðèíÿë óñëîâèÿ ëèöåíçèîííîãî ñîãëàøåíèÿ.
Èäåÿ è ðåàëèçàöèÿ: © Âëàäèìèð Äîâûäåíêîâ è Àíàòîëèé Êàìûíèí,  2004-2026