dev.gamez.lv Forum Index dev.gamez.lv
Latvian Game Developers Community
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups 

Ebb3DSound

 
dev.gamez.lv Forum Index -> Tavi projekti
View previous topic :: View next topic  
Author Message
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sun Dec 02, 2007 2:09 pm    Post subject: Ebb3DSound

Tā kā ir ļoti grūti atrast 3D sound library komerciālai lietošanai, tad gadu vai 2 atpakaļ sāku rakstīt pats savu cross-platform DirectSound(tikai pie windows)/OpenAL sound library. Pats to esmu izmantojis 2 spēlēs un tagad nolēmu ar to padalīties. Mani interesētu jūsu iebildumi utt. lai vēlāk varētu to palaist arī plašākā tautā.

Download: šeit.
Pagaidām pakotnē ir sakompilēta tikai windows versija, ja kāds varētu, lūdzu pamēģiniet to sakompilēt uz citiem OS.

Fīčas:
WAV un OGG atbalsts.
3D Skaņa (un klausītāji - Listener)
Var regulēt skaņas/mūzikas skaļumu, ātrumu
Failu lasīšana no Zip arhīva

Plāni uz nākotni:
Callbacki (kad skaņa sāk/beidz spēlet)
Dažādi 3D efekti (kā klausītāja ātrums (velocity), doppler efekts utt.)
EAX atbalsts

Īsa pamācība:
Code:
//neimspeiss
using namespace ebb3dsound

CSoundSystem* soundSystem = CreateSoundSystem(DRIVER_DIRECTSOUND);

if (!soundSystem) Error();

if (!soundSystem->Init()) Error2();

CMusic* background = soundSystem->LoadMusic("background.ogg");

if (!background) Error3();

background->Play()


Un neaizmirstiet katru fremu izsaukt soundSystem->Update(); un protams, kad beidzat to lietot, tad izsauciet soundSystem->Deinit();
_________________
long time; /* know C */


Last edited by elvman on Sun Dec 02, 2007 7:50 pm; edited 3 times in total
Back to top
View user's profile Visit poster's website
snake5
Indago dalībnieks
Indago dalībnieks


Joined: 27 Jun 2007
Posts: 2590

PostPosted: Sun Dec 02, 2007 3:13 pm    Post subject:

šim ērtāk?
kanāli paši izdalās?
es tagad fmod šim projektam* lietoju, bet noderētu pats ātrākais un vienkāršākais variants Wink
* - bildē redzams particle aplis
_________________
"There are two choices here: "looks good" and "realism"." -- Paul Nettle
Back to top
View user's profile Visit poster's website
bubu
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 23 Mar 2004
Posts: 3223
Location: Riga

PostPosted: Sun Dec 02, 2007 3:18 pm    Post subject:

Ieteiktu CreateSoundSystem funkciju nelikt neimspeisā un uzlikt tai extern "C" izsaukumu, lai uzkompilēto DLL failu varētu lietot no jebkura C++ kompilētāja (MSVC, GCC, BC++, ...), kā arī jebkurām versijām (msvc6, msvc7, msvc8, gcc3, gcc4, ...). Citādi katrs kompilētājs un pat tā dažādās versijas ģenerē pilnīgi savādāku simbola vārdu, kurš tiek eksportēts no dll faila.

Kāpēc vajadzīgs DirectSound, ja tiek supportēts arī OpenAL, kurš pie tam ir cross-platformisks (jo šis vārds ir iekļauts kā fīča)?
Kam tas ZipArchive.cpp/h tur vajadzīgs?
Kāpēc skaņu nevar ielādēt no ogg, tikai mūziku var?
Kā diseiblot log faila rakstīšanu?
Kā var to skaņas/mūzikas ātrumu regulēt?
Kas ir WAW atbalsts? :)

BUGI:

Potenciāli memory leaki:
OALSound.cpp failā 36 un 46 rindās, ja nostrādā kāds return false zemāk (52, 70, ... u.c. rindās).

Iesaku lietot std::vector, jo tā destruktorā atmiņa automātiski tiek atbrīvota. Iesaku arī visu malloc/free vietā lietot šo pašu std::vector, piemēram Buffer memberam CWaveFile klasē.

DSSound.cpp failā 43 rindā, ja nostrādā kāds return false zemāk. Iesaku lietot std::auto_ptr, kurš savā destruktorā automātiski atbrīvos atmiņu.

OALMusic.cpp/DSMusic failos netiek aizvērts OggVorbis_File.

OALSystem.h failā Sounds un Musics memberu saturētie pointeri - netiek atbrīvoti.

Neaizvērti faili:
CWaveFile.cpp failā 23 rindā, ja nostrādā kāds return false zemāk.
OALMusic.cpp failā 35 rindā, ja nostrādā kāds return false.
DSMusic.cpp failā 39 rindā, ja nostrādā kāds return false.

Iesaku lietot std::ifstream, jo tā destruktorā fails automātiski tiek aizvērts.

Citi nelabumi:
DSSoundSystem.cpp failā netiek atbrīvots DirectSound objekts 27 rindā, ja nostrādā kāds return false zemāk.
Iesaku lietot CComPtr, kas destruktorā automātiski izsauc COM objekta Release metodi.

Ieteiktu OALSystem/DSSystem klasēm nerakstīt DeInit metodi. Tām vajadzētu savus resursus atbrīvot destruktorā. Un SoundSystem klasei DeInit metodei vajadzētu izsaukt TIKAI delete this, lai atbrīvojas izdalītā atmiņa, un tā kā destruktors ir virtuāls, tad mantotajām klasēm arī, protams, automātiski izsauksies destruktors.

Vai nevajadzētu arī tos sound/music/listener objektus, kas salikti memberos šīm abām System klasēm, aiznest uz virsklasi - SoundSystem? Tad to atbrīvošana būtu jāraksta tikai vienā vietā - SoundSystem destruktorā, nevis divās, kā ir tagad.

Derētu arī uztaisīt CVorbisFile klasi analoģisku CWaveFile klasei, jo tev atkārtojās kods DSMusic un OALMusic klasēs.

Slikti, ka nevar atbrīvot skaņas/mūzikas. Tādējādi būs kā Augonī - pēc pāris līmeņu ielādes būs simtiem megabaitu atmiņas aizņemti :) Ieteiktu CSound un CMusic klasēm uztaisīt līdzīgu DeInit metodi kā CSoundSystem klasie. Tai vajadzētu apturēt skaņu un atbrīvot atmiņu.

Slikti ir izmantot std::string klasi pār DLL faila robežām. Tā nav dažādu kompilētāju un viena kompilētāja dažādu versiju savietojama lieta (tas pats, ko teicu pašā augšā).

Imho visus tos OAL....h un DS....h failus derētu aiznest zem source direktorijas, lai nemaisās pa kājām. T.i. include direktorijā atstāt tikai tos failus, kuros jāskatās, ja grib bibliotēku izmantot.

Tipiskais gļuks (kurš man ar skvērus rakstot bija) - ja tev ir GUI logs, un spēlē background mūzika, tad, uzspiežot uz loga titlebara peli, pavelkot logu un nelaižot peli vaļā, mūzika apstājas un pēc atlaišanas vairs neturpina spēlēt.
Pret apstāšanos var cīnīties laižot mūzikas strīmošanas kodu atsevišķā threadā. Pret apstāšanos vajag tikai salabot update metodi, lai tā nedomā, ka mūzika ir apstājusies, ja buferis ir iztukšojies.

Quote:
un protams, kad beidzat to lietot, tad izsauciet soundSystem->Deinit() un delete soundSystem.

Tā nedrīkst! Tas ir potenciāla atmiņas sabojāšana un tātad krašs tuvākajā nākotnē. Jo new tiek izsaukts no cpp faila, kas tiek iespējams salinkots ar citu C/C++ runtaimu - tātad citu atmiņas menedžeri. Paskaties kā tev ir tagad - dll fails, kurā runtaims ir statiski pielinkots. Izsaucot new OALSystem no tā dll faila atmiņa tiek izdalīta ar to runtaimu, kurš ir iekš dll faila. Taču izsaucot delete soundSystem no savas programmas es šo pointeri padošu savam C/C++ runtaimam, kura atmiņas menedžeris nav tas pats, kas iekš tava dll faila. Tādējādi iekšēji tas (atmiņas menedžeris) var pilnīgi sajāt visas savas iekšējās struktūras, jo tam vajag atbrīvot atmiņu, kuru tas nav izdalījis. Labākais risināums ir tas, ko es augstāk uzraksīju - no DeInit metodes CSoundSystem klasē izsaukt delete this. Tādējādi, tā kā šī metode (DeInit) atrodas dll failā, šis izsaukums izmantos to pašu atmiņas menedžeri, ko new izsaukums. Atmiņa atbrīvosies korekti.

Gudrākā variantā ieteiktu nowrapot šo pointeri ar kādu smart pointera paveidu, tādējādi nevajadzēs pašam izsaukt DeInit metodi.

Iesaku arī publicēt zem kādas licences tu to izplati (kautkāda open-source, vai public-domain, vai vēl sazin kas)

Edit:
Jā un patiešām - daudz noderīgāk būtu kanālu (sourču) automātiska menedžēšana nevis pliks API wraperis... Tipa, ko darīt, kad grib jaunu skaņu taisīt, bet OpenAL vairs nevar izdalīt sourci, jo hardware vairāk neatbalsta? Tur vajadzētu kautkādas prioritātes piešķirt sourcēm, lai svarīgās vienmēr spēlētu, bet nesvarīgākās var apturēt un laist pa virsu svarīgās.
Back to top
View user's profile Send e-mail
snake5
Indago dalībnieks
Indago dalībnieks


Joined: 27 Jun 2007
Posts: 2590

PostPosted: Sun Dec 02, 2007 3:41 pm    Post subject:

oj...
Shocked
nu lab..
šausmaini.. es palieku pie FMOD, bet būs jāveido kanālu dalītāju klase..

nu man dažas idejas par to klasi rodas, domāju, ka varbūt citur arī der..
1. kanālus visus inicializēt pašā sākumā
2. visus turēt std::vector'ā
3. katrā frame updeitā kārtot kanālus pēc prioritātes, lai vieglāk būtu nomainīt kanālus ar mazāku prioritāti
4. lietot papildkanālus, kurus izdala tikai, ja par maz brīvo kanālu, tie nedara neko, skaņas katrā updeitā pārnes uz reāli strādājošiem kanāliem
5. kanālus pēc atskaņošanas beigām atbrīvo pēc mana vector'a atbrīvotāja metodes*

* - te tā ir
Code:

//OBJEKTA STRUKTŪRAS PAMATS
struct Object
{
   bool Active;
};
//DEFINĒJAM OBJEKTU GLABĀTUVI
std::vector<Object*> Objects;
//KODS UPDATE FUNKCIJĀ
std::vector<Object*>::iterator it = Objects.begin();
std::vector<Object*>::iterator itend = Objects.end();
while (it != itend)
{
   Object* bb = *it;
   //UPDATE
   Object* bbb = Objects.back();
   if (bbb->Active == false)
   {
      delete bbb;
      Objects.pop_back();
      break;
   }
   it++;
}
it = Objects.begin();
itend = Objects.end();
while (it != itend)
{
   Object* bbb = *it;
   if (bbb->Active == false)
   {
      Objects.erase(Objects.begin());
      it = Objects.begin();
      itend = Objects.end();
   }
   else
   {
      break;
   }
}

Strādā lieliski un ātri Wink
_________________
"There are two choices here: "looks good" and "realism"." -- Paul Nettle


Last edited by snake5 on Sun Dec 02, 2007 3:48 pm; edited 1 time in total
Back to top
View user's profile Visit poster's website
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sun Dec 02, 2007 3:44 pm    Post subject:

Šeit es tikai padalos ar kodu, licenci (BSD) katrā failā pielikšu vēlāk. Kritika ņemta vērā, tuvākajā laikā visu pārrakstīšu.
_________________
long time; /* know C */
Back to top
View user's profile Visit poster's website
snake5
Indago dalībnieks
Indago dalībnieks


Joined: 27 Jun 2007
Posts: 2590

PostPosted: Sun Dec 02, 2007 3:47 pm    Post subject:

Atvainojos, aizmirsu manā piemērā noņemt timeleft'us, te tie nebūs vajadzīgi..

bubu, redzēju, ka manā postā tev kautkas nepatika..
ja vajag pierādījumu tam, ka viss lieliski strādā...
vai arī ja nepatika mans kanālu dalītāja variants..
vai arī ja nepatika, ka es par savu variantu sāku runāt..
anyway, man tas liekas labs variants, un izveidot arī nebūtu grūti..
_________________
"There are two choices here: "looks good" and "realism"." -- Paul Nettle
Back to top
View user's profile Visit poster's website
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sun Dec 02, 2007 5:10 pm    Post subject:

Starp citu bubu - tu esi redzējis, kā Irrlicht strādā? CreateDevice ir neimspeisā un strādā uz visām platofrmām un irrlichta deinicializēšana notiek ar ->drop (ja referenču skaits ir 0, tad tiek izpildīts delete).

DirectSound un OpenAL ir tikai outputam. Arī FMOD ļauj izvēlēties kādu outputu izmantot (WinMM, DirectSound vai OpenAL).
_________________
long time; /* know C */
Back to top
View user's profile Visit poster's website
snake5
Indago dalībnieks
Indago dalībnieks


Joined: 27 Jun 2007
Posts: 2590

PostPosted: Sun Dec 02, 2007 5:15 pm    Post subject:

DirectSound'am vairs īsti nav jēgas, jo tas uz Vistas nestrādā!
daudz piemēru spēlēm, kurām nav skaņu/mūzikas..
_________________
"There are two choices here: "looks good" and "realism"." -- Paul Nettle
Back to top
View user's profile Visit poster's website
bubu
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 23 Mar 2004
Posts: 3223
Location: Riga

PostPosted: Sun Dec 02, 2007 5:32 pm    Post subject:

elvman: Esmu redzējis. Tieši tas drop ir aptuveni tas pats, kas tavs DeInit. Tik tavā gadījumā vajag vēl papildus delete. Kam lieki sarežģīt dzīvi? Tāpēc arī tev to ieteicu - ienes delete iekš DeInit'a, tad būs gandrīz tieši tāpat kā irrlicht'ā (tik tev nav referenču skaitīšana).

Un es jau nesaku, ka nestrādās tas neimspeisa variants. Bez-neimspeisa variants būs labāks ar to, ka varēs izmantot ar viena C++ kompilētāja uzbuildotu dll failu citam. Nevajadzēs pārbuildot.

OpenAL zem Windows arī ļauj izvēlēties, ko lietot. Defaultā tas lieto hardwari pa tiešo, ja var. Ja nevar, tad DirectSound. Un visbeidzot fallbacko uz WinMM.
Back to top
View user's profile Send e-mail
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sun Dec 02, 2007 8:30 pm    Post subject:

Ok,
1. izņēmu funkciju no neimspeisa un ieliku extern "C",
2. tagad vairs nevajag izsaukt delete soundSystem,
3. salaboju lielu daļu no memory leakiem (visus vēl nē),
4. tagad stringiem izmantoju char*,
5. konstificēju visas getteru funkcijas,
6. pārvietoju neizmantojamos headerus uz source folderi,
7. defineeju savus mainiigo nosaukumus (types.h).
ZipArchive.h/.cpp fails tur staav no laikiem, kad varēja lasīt no zip failiem. Tad to fīču izņēmu, bet tagad laikam būs jāliek atpakaļ.
_________________
long time; /* know C */
Back to top
View user's profile Visit poster's website
snake5
Indago dalībnieks
Indago dalībnieks


Joined: 27 Jun 2007
Posts: 2590

PostPosted: Sun Dec 02, 2007 9:07 pm    Post subject:

char* ?
tu visiem to izmanto vai tikai iekš klasēm/struktūrām vai kā argumentus?

pēc īsa brīža droši vien tev kāds ieteiks lietot std::string
_________________
"There are two choices here: "looks good" and "realism"." -- Paul Nettle
Back to top
View user's profile Visit poster's website
Tenjou



Joined: 22 Nov 2005
Posts: 275

PostPosted: Sun Dec 02, 2007 9:10 pm    Post subject:

snake5: Tu vispār izlasīji bubu postu garo?

bubu rakstīja:
Quote:
Slikti ir izmantot std::string klasi pār DLL faila robežām. Tā nav dažādu kompilētāju un viena kompilētāja dažādu versiju savietojama lieta (tas pats, ko teicu pašā augšā).
Back to top
View user's profile
bubu
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 23 Mar 2004
Posts: 3223
Location: Riga

PostPosted: Sun Dec 02, 2007 9:21 pm    Post subject:

Drusku vēl parevidēju tavu sourci:

1) Ja gribēsi kompilēt zem ne-Windows kompilētājiem, tad nāksies uzdefinēt vēl vienu EBB3DSOUND_API vērtību. Jo citiem tādu __declspec direktīvu nav.

2) Kam šitais vispār vajadzīgs - _STDCALL_SUPPORTED ? __cdecl teorētiski ir ātrāks.

3) brr, kas pa C'ismu...
Code:
typedef enum SOUNDDRIVER
{
   DRIVER_DIRECTSOUND=0,
   DRIVER_OPENAL=1,
}SOUNDDRIVER;

C++'ā enums definē tāpat kā struc/class:
Code:
enum SOUNDDRIVER
{
   DRIVER_DIRECTSOUND=0,
   DRIVER_OPENAL=1,
};


4) SoundSystem.cpp destruktors. Nav īsti labi mainīt vektora saturu, ja tu pa to iterē. Varēt jau var, bet nevajag. Īpaši jau tavā gadījumā, kad viss tiek iznīcināts. Vienkārši izej vektoram cauri normālā virzienā, izdzēs objektus un nesauc nekādu pop_back. Vektors atmiņu pats atbrīvos destruktorā. Darbosies gan ātrāk, gan arī mazāk jāraksta.

5) SoundSystem.cpp 60 rinda. Ļoti nestandarta konstrukcija. Atkarībā no platformas un kompilētāja settingiem kautkas var nestrādāt. Iesaku lietot va_start makrosu. Tam jau tam tas ir arī domāts - lai universālā veidā izdarītu to, ko tu dari 60 rindā.

6) SoundSystem.cpp 61 rinda. Potenciāls stack-corruptions. Iesaku lietot vsnprintf funkciju.
Back to top
View user's profile Send e-mail
snake5
Indago dalībnieks
Indago dalībnieks


Joined: 27 Jun 2007
Posts: 2590

PostPosted: Sun Dec 02, 2007 9:21 pm    Post subject:

Tenjou wrote:
snake5: Tu vispār izlasīji bubu postu garo?

bubu rakstīja:
Quote:
Slikti ir izmantot std::string klasi pār DLL faila robežām. Tā nav dažādu kompilētāju un viena kompilētāja dažādu versiju savietojama lieta (tas pats, ko teicu pašā augšā).

ax tā...
nu tad no manas puses ieteikums argumentiem izmantot const char*
_________________
"There are two choices here: "looks good" and "realism"." -- Paul Nettle
Back to top
View user's profile Visit poster's website
Display posts from previous:   
dev.gamez.lv Forum Index -> Tavi projekti All times are GMT + 2 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group