LECKÉK:
Saját ablak
Directdraw1
Directdraw2
Directdraw_3
Sprite_1
Sprite 2
Billentyű_1
Billentyű_2
Egér
Joystick
Midi
Mp3_Ogg
Directsound
Időzítők
Fájlkezelés
| |
Üdvözöllek!
A midi osztályhoz kissé hasonló lesz az mp3 és ogg fájlok
lejátszása.
Jobbnak láttam,ha létrehozok egy struktúrát, amiben el lehet tárolni a betöltött
zene memóriacímét,és amikor lejátszásra kerül,akkor a dll fájl visszaad egy
számot,mégpedig a megnyitott hangpuffer azonosítóját, tehát erre a számra lehet
hivatkozni, amikor műveleteket végzünk az adott hangobjektumon, mint
lejátszás, hangerő, stop stb.
Hogy ne legyen a pause meghívásával gond, létrehoztam egy logikai változót
is,hogy megállított, vagy nem a lejátszás. Hozz Létre egy uj fájlt Mp3_ogg.hpp
néven, és a megszokott módon építsed fel az osztályt:
//
// Ogg és mp3 lejátszása:
//
#ifndef _OGG_MP3_
#define _OGG_MP3_
//
#include <fmod.h>
#pragma comment(lib,"fmodvc.lib")
#define MAX_CSATORNA 8 //egyszerre több zenét nem akarunk,ez is sok
//
typedef struct
{
FSOUND_SAMPLE* szam; //létrehozott objektum címe
int csatorna; // a felhasznált hangcsatorna száma
bool pause;
} HOBJ, *LPHOBJ ; //Hangobjektum és mutatója
class ZENE
{
public:
ZENE();
~ZENE();
bool zene_init( int melyik,int hova=0,bool loop=false);//hova= hányadik
tömbelembe
void zene_play( int melyik);
void zene_stop( int melyik);
void zene_hangero(int melyik,int volume);
void zene_torol( int melyik); //felszabadítja a csatornát következő zenének
void zene_pause(int melyik,bool paused=false);
protected:
LPHOBJ zenek[32]; //32db zeneszám mutatónak hely
bool fsound_init(); //dll betöltése és init
};
Nos látható, hogy a védett tagváltozók között szereplő
LPHOBJ zenek[32] csak egy 32 elemű
mutatótömb,tehát üres majd ha betöltjük a zeneszámot, akkor kap értéket.
Megvalósítások:
ZENE::ZENE()
{
for(int i=0;i<MAX_CSATORNA ;i++)
{
zenek[i]=NULL;
}
fsound_init();
}
ZENE::~ZENE()
{
for(int i=0;i<MAX_CSATORNA;i++)
{
if(!zenek[i]){delete zenek[i];zenek[i]=NULL;}
}
}
A konstruktor meghív egy inicializáló függvényt,ami betölti a
dll.t. A destruktor pedig felszabadít minden létező zeneszám memóriát,és a dll-t
is.
Az fsound_init() függvény:
bool ZENE::fsound_init()
{
if (FSOUND_GetVersion() < FMOD_VERSION)
{
// err("rossz dll");
return false;
}
FSOUND_SetOutput(FSOUND_OUTPUT_WINMM);
if (!FSOUND_Init(44100, 32,FSOUND_INIT_GLOBALFOCUS )) return false;//a dll
betöltése
return true;
Nézzük a többi függvényt:
bool ZENE::zene_init(int melyik,int hova,bool loop)
{
LPCTSTR nevek[]={"mp3_ogg//o1.ogg","mp3_ogg//z1.mp3","mp3_ogg//o2.ogg","mp3_ogg//z2.mp3"};
if(hova>=MAX_CSATORNA)return false;//nem létező mutató lenne
zenek[hova]=new HOBJ;//új példány létrehozása
zenek[hova]->szam=FSOUND_Sample_Load(FSOUND_FREE,nevek[melyik],loop,0,0);//betöltjük,és
visszakapjuk a mutatót
if(zenek[hova]->szam==NULL) return false;
zenek[hova]->csatorna=0,zenek[hova]->pause=false;
return true;
}
A zene_init() függvényt annyiszor hívjuk meg,amennyi számot szeretnénk
betölteni.
Bemenő paraméterek magukért beszélnek,a hova jelenti a mutatótömbben elfoglalt
helyét.Ez a függvény tölti fel a tömböt létező mutatókkal, de csak
MAX_CSATORNA darabot tudunk betölteni.Mivel nem
folyam jellegű ezért betölti az egész zenét a memóriába,eltelik 5-6 másodperc,
mire (gondolom kitömöríti) lefut. Jó lenne, ha a MAX_CSATORNA
értéke annyi lenne,amennyi nevet megadsz! Létre kell hozni egy új mappát
a zenéknek, és nevezd át őket z1 z2 ill ha ogg fájl, akkor o1 o2 stb.
A bemenőparaméterben a loop true akkor folyamatos
lejátszás.
A többi függvény:
void ZENE::zene_stop( int melyik)
{
FSOUND_StopSound(zenek[melyik]->csatorna);//az adott csatornát felszabadítja
//DIRECTSOUNDBUFFER
}
//
void ZENE::zene_hangero(int melyik,int volume)
{
if(!zenek[melyik])return;//ha ide nincs betöltve zene
FSOUND_SetVolume(zenek[melyik]->csatorna,volume);//0-255
}
//
void ZENE::zene_torol(int melyik)
{
if((melyik >= MAX_CSATORNA) | (!zenek[melyik])) return;//ha nem létezik
FSOUND_StopSound(zenek[melyik]->csatorna);
delete zenek[melyik];zenek[melyik]=NULL;
}
//
void ZENE::zene_pause(int melyik,bool paused)
{
if((melyik >= MAX_CSATORNA) | (!zenek[melyik])) return;//ha nem létezik
if(zenek[melyik]->pause==paused)return;//kétszer ne lehessen meghívni
zenek[melyik]->pause=paused;
FSOUND_SetPaused(zenek[melyik]->csatorna,paused);// true= pause
}
#endif
Csak a zene_torol() függvény szorul magyarázatra: Ha már nincs szükség az adott
objektumra,akkor előbb illik felszabadítani,mert a lefoglalt memória úgymarad!
Azaz ha a "helyére" akarsz tölteni másikat előbb meg kell hívni ezt a függvényt.
egy betöltött zenét többször is le lehet játszani pl visszhang:
zene.zene_play(0);Sleep(200);zene.zene_play(0);
Használata:
A main.cpp-ben törüljél,vagy tedd megjegyzés alá
minden Midi szöveget, ha nem akarod azt is egyszerre hallgatni!
#include <Sprite.hpp>
//#include <Midi.hpp>
#include <Ogg_Mp3.hpp>
//
//
//dekralációk
HINSTANCE hinstance;
RAJZ rajz;
INPUT input;
//MIDI midi;
ZENE zene;
SPRITE sprite;
A zeneszámok betöltése:
sprite.sp_init ();
// midi.midi_init();midi.midi_play();
zene.zene_init(0,0,1);
zene.zene_init(1,1,0);
zene.zene_play(0);zene.zene_hangero(0,255);
zene.zene_play(1);zene.zene_hangero(1,255);
while (fut)
A hangerőt most nem folyamatosan változtatom,hanem csak
egyszerű xor művelettel változtatom lenyomott billentyűnél minden 100.
képernyőváltáskor: Megírtam a pause használatát is az első zenéhez:
while (fut)
{
/* static int flag=0;//ha a pause függvényt többször hívod, kiakad a progi
tehát:
if(input.get_key(DIK_A,true) && !flag){midi.midi_pause(true);flag=1;}
if(input.get_key(DIK_B,true) && flag){midi.midi_pause(false);flag=0;}
if(input.get_key(DIK_C,true)){midi.midi_stop();midi.midi_init(1);midi.midi_play();}*/
//
static int vol1=0x7f,vol2=255,time=100;
if(input.get_key(DIK_H,true))// H betűt lenyomva tartani !!(hangerő váltás a 2
szám között
{
time--;if(time<0)
{
time=100;
vol1 ^=0x80;vol2 ^=0x80;zene.zene_hangero(0,vol1);zene.zene_hangero(1,vol2);
}
}
if(input.get_key(DIK_S,true) ){zene.zene_pause(0,1);}; //S STOP
if(input.get_key(DIK_A,false)){zene.zene_pause(0,0);}; //A START
uzenetkezelo();
Tehát a H betű hangerő váltása a két lejátszott szám között,
Az S a stop és a mellette lévő A betűre folytatja a lejátszást.
Irassuk ki!
uzenetkezelo();
sprite.frissit();
input.get_key(0,true);//csak azért hívjuk meg,hogy az esc-re kilépjen
rajz.kiirbetu("H Hangerő váltás hosszan
nyomni!!!",500,10);
rajz.kiirbetu("S STOP első pause",500,30);
rajz.kiirbetu("A Folytatjuk a lejátszást",500,50);
rajz.flip();
}
Azonban ha ezt a szöveget beírod, akkor a Sprite.hpp-ben a
frissit() függvényben ki kell venni!!!!
babu_mozgat_m();
babu_mozgat_joy();
// rajz.flip();
Mert ha nem, akkor a sprite osztály rajzol, képet vált, és itt is kiírunk képet
váltunk, az eredmény egy kék képernyő és egy rajzolt képernyő, tehát villog!!
Mód van lekérdezni hogy éppen lejátszott-e a szám, vagy nem, de ehhez kéne egy
időzítő
lehet csinálni most a képernyő frekvencia alapút (egyszerű számláló)
(Az időzítőkről később) le lehet keverni a hangot stb. Át kell nézni hozzá a
fmod.h headert.
Én ezt az osztályt csak egy szám lejátszására használnám,mert az igazi
hangeffekteknek ott van a DirectSound hangpuffer,és ez a következő lecke!
U.i.: Azért csatoltam a grafikát is,mert belevettem az egyik ürge mögött
menjenek el a sprite-ok!
Ne feledd ! Létre kell hozni a mappát és beletölteni a
fájlokat átnevezve a projectben!
itt van a forrás:
vissza:
|