M
Der Code ist in Klassen unterteilt, aber ich poste mal die wichtigsten Code-Zeilen:
xaudio.h
/***************************************************************************
* Copyright (C) 2005 by Mathias Kahl *
* mathias_kahl@onlinehome.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef XH_AUDIO
#define XH_AUDIO
/*!
@file xaudio.h
@brief Klassen fuer Musik und Soundeffekte
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream>
#include <stdlib.h>
#include "SDL.h"
#include "SDL_mixer.h"
using namespace std;
/*!
@class XAudio
@brief Musik und Soundeffekte
@author Mathias Kahl
@version 0.1
@date 07.01.2005
Diese Klasse bietet Methode zur Ausgabe und Sampling von Musik und Soundeffekten.
*/
class XAudio
{
protected:
/// Frequenz
int m_iFrequency;
/// Sample Format
Uint16 m_iFormat;
/// Anzahl Sound Channels, 1=mono; 2=stereo
int m_iChannels;
/// Chunksize
int m_iChunkSize;
/// Hintergrundmusik-Stream
Mix_Music* m_pMusic[5];
/// Momentan ausgewaehlte Musik
int m_iSelectedMusic;
/// Dauer eines FadeIns in ms
int m_iMusicFadeIn;
/// Dauer eines FadeOuts in ms
int m_iMusicFadeOut;
/// Lautstaerke der Musik
int m_iMusicVolume;
public:
XAudio();
~XAudio();
int GetFrequency() { return m_iFrequency; }
Uint16 GetFormat() { return m_iFormat; }
int GetChannels() { return m_iChannels; }
int GetChunkSize() { return m_iChunkSize; }
Mix_Music* GetMusicStream() { return m_pMusic[m_iSelectedMusic]; }
int GetMusicFadeInLenght() { return m_iMusicFadeIn; }
int GetMusicFadeOutLenght() { return m_iMusicFadeOut; }
int GetMusicVolume() { return m_iMusicVolume; }
int GetCurrentMusic() { return m_iSelectedMusic; }
void SetFrequency(int i) { m_iFrequency = i; }
void SetFormat(Uint16 i) { m_iFormat = i; }
void SetChannels(int i) { m_iChannels = i; }
void SetChunkSize(int i) { m_iChunkSize = i; }
void SetFadeInLenght(int i) { m_iMusicFadeIn = i; }
void SetFadeOutLenght(int i) { m_iMusicFadeOut = i; }
/// Setzt die Musiklautstaerke, Angabe in Prozent (0-100)
bool SetMusicVolume(int i);
/// Waehlt einen der verfuegbaren Musik-Streams, 0 - 4
void SelectMusic(int i) { m_iSelectedMusic = i; }
/// Initialisiert die Sound-Engine
bool Init(int chunk_size=4096);
/// Laedt Musik (nur ein Musik-Channel gleichzeitig)
bool LoadMusic(char* path);
/// Gibt den Speicher frei und loescht die Musik
bool FreeMusic();
/// Gibt die Musik als Loop wieder, 0=1mal,-1=unendlich
bool PlayMusic(int loops,bool fadein);
/// Pausiert die Musik
void PauseMusic();
/// Nimmt die Wiedergabe von pausierter Musik wieder auf
void ResumeMusic();
/// Spult die Musik auf Anfang zurueck
void RewindMusic();
/// Stoppt Musik, optional mit FadeOut
bool StopMusic(bool fadeout);
/// Prueft ob Musik spielt
bool IsMusicPlaying();
/// Prueft ob eine pausierte Musik vorhanden ist
bool IsMusicPaused();
};
#endif
Implementierung (xaudio.cpp):
#include "xaudio.h"
XAudio::XAudio()
{
m_iFrequency = 22050; // 22050 Hz Standart
m_iFormat = MIX_DEFAULT_FORMAT;
m_iChannels = 2; // Stereo
m_iChunkSize = 1024;
m_iMusicFadeIn = 3000; // 3 s FadeIn
m_iMusicFadeOut = 3000; // 3 s FadeOut
m_iMusicVolume = 80; // 80% Musik-Lautstaerke
m_iSelectedMusic = 0; // ersten Stream Standartauswahl
m_pMusic[0] = NULL;
m_pMusic[1] = NULL;
m_pMusic[2] = NULL;
m_pMusic[3] = NULL;
m_pMusic[4] = NULL;
}
XAudio::~ XAudio()
{
for(int i=0;i<4;i++)
{
if(m_pMusic[i] != NULL)
{
Mix_FreeMusic(m_pMusic[i]);
m_pMusic[i] = NULL;
}
}
Mix_CloseAudio();
}
/*! initialisiert die Sound-Engine mit den Standartparametern und chunk_size.
Die Standartparameter fuer Format, Frequenz usw. koennen per Set* vor Aufruf von Init geaendert werden.
@param chunk_size Groesse der Sampling-Stuecke, je kleiner desto besser (und aufwendiger), Standart: 1024
@return Die Methode liefert true wenn alle Komponenten korrekt initialisiert wurden
@sa SetFrequency, SetFormat, SetChannels
*/
bool XAudio::Init(int chunk_size)
{
// Audio-Subsystem intitialisieren
if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
{
fprintf(stderr,"XAudio: Failed to init sub system: %s\n",SDL_GetError());
return false;
}
// MIXER starten
if(Mix_OpenAudio(m_iFrequency,m_iFormat,m_iChannels,m_iChunkSize) < 0)
{
fprintf(stderr,"XAudio: Open Audio failed: %s\n",SDL_GetError());
return false;
}
return true;
}
/*! Es wird die Lautstaerke der Musik gesetzt. Dies funktioniert nicht waehrend eines Fades.
@param i Lautstaerke in Prozent (0-100)
@return Diese Methode liefert immer true zurueck
*/
bool XAudio::SetMusicVolume(int i)
{
int m_iMusicVolume = (int) ((MIX_MAX_VOLUME / 100) * i);
Mix_VolumeMusic(m_iMusicVolume);
return true;
}
/*! Diese Methode laedt eine Musik-Datei (MP3,OGG,WAV,MOD oder MIDI)
@param path Speicherpfad zur Musikdatei, kann relativ oder absolut sein
@return liefert true wenn die Datei erfolgreich geladen wurde
*/
bool XAudio::LoadMusic(char* path)
{
if(m_pMusic[m_iSelectedMusic] != NULL) return false;
m_pMusic[m_iSelectedMusic] = Mix_LoadMUS(path);
if(NULL == m_pMusic[m_iSelectedMusic])
{
fprintf(stderr,"XAudio: Failed to load music (%s): %s\n",path,SDL_GetError());
return false;
}
return true;
}
/*! Gibt geladene Musik frei, wenn die Musik spielt wird sie vorher angehalten. Waehrend eines Fades
wartet die Methode bis dieser abgeschlossen ist.
@return gibt true zurueck wenn die Musik erfolgreich freigegeben wurde
*/
bool XAudio::FreeMusic()
{
if(m_pMusic[m_iSelectedMusic] == NULL) return false;
Mix_FreeMusic(m_pMusic[m_iSelectedMusic]);
m_pMusic[m_iSelectedMusic] = NULL;
return true;
}
/*! Gibt die momentan ueber SelectMusic ausgewaehlte Musik als Loop wieder.
@param loops Anzahl der Loops oder -1 fuer unendlich
@param fadein Bestimmt ob die Musik mit einem FadeIn gestartet werden soll
@return gibt true zurueck wenn die Musik erfolgreich gestartet werden konnte
@sa SelectMusic, SetFadeInLenght, PauseMusic, StopMusic
*/
bool XAudio::PlayMusic(int loops, bool fadein)
{
if(fadein)
{
if(Mix_FadeInMusic(m_pMusic[m_iSelectedMusic],loops,m_iMusicFadeIn) < 0)
{
fprintf(stderr,"XAudio: Playing music failed: %s\n",SDL_GetError());
return false;
}
}
else
{
if(Mix_PlayMusic(m_pMusic[m_iSelectedMusic],loops) < 0)
{
fprintf(stderr,"XAudio: Playing music failed: %s\n",SDL_GetError());
return false;
}
}
return true;
}
/*! Pausiert aktuell spielende Musik
*/
void XAudio::PauseMusic()
{
Mix_PauseMusic();
}
/*! Die momentan spielen Musik wird "zurueckgespult" und faengt wieder von vorne an. */
void XAudio::RewindMusic()
{
Mix_RewindMusic();
}
/*! Spielt angehaltene Musik weiter. Diese Methode funktioniert auch sicher bei gestoppter und
spielender Musik, ohne Fehler oder Exceptions zu produzieren.
@sa PlayMusic, PauseMusic, StopMusic
*/
void XAudio::ResumeMusic()
{
Mix_ResumeMusic();
}
/*! Die momentan spielende Musik wird angehalten, optional per Fadeout. Die Dauer des Fadeouts ist in der
Membervariablen XAudio::m_iFadeOut gespeichert.
@param fadeout Bestimmt ob die Musik vor dem Stoppen ausgefadet werden soll
@return Diese Methode liefert true wenn die Musik gestoppt werden konnte oder der Fadeout gestartet worden ist
@sa SetFadeOutLenght
*/
bool XAudio::StopMusic(bool fadeout)
{
if(fadeout)
{
if(Mix_FadeOutMusic(m_iMusicFadeOut) == 0)
{
fprintf(stderr,"XAudio: Fade Out Music failed: %s\n",SDL_GetError());
return false;
}
}
else
{
Mix_HaltMusic();
}
return true;
}
bool XAudio::IsMusicPlaying()
{
return (Mix_PlayingMusic() == 1);
}
bool XAudio::IsMusicPaused()
{
return (Mix_PausedMusic() == 1);
}
Das ganze wird dann folgendermaßen verwendet (es handelt sich dabei nur um ein Testprogramm fuer die Klassen):
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream>
#include <stdlib.h>
#include "SDL.h"
#include "xvideo.h"
#include "xevent.h"
#include "xinput.h"
#include "xaudio.h"
using namespace std;
int main()
{
if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_EVENTTHREAD)< 0)
{
cout <<"Could not initialize SDL:" << SDL_GetError() << endl;
SDL_Quit();
}
bool fQuit = false;
XVideo* pVideo = new XVideo();
XEvent* pEvent = new XEvent();
XInput* pInput = new XInput();
XAudio* pAudio = new XAudio();
pVideo->Init(320,240,0,false);
pVideo->SetWindowName("<<<< xGame >>>>");
pAudio->Init();
pAudio->LoadMusic("media/epok.ogg");
pAudio->SetMusicVolume(80);
pAudio->PlayMusic(1,false);
while(!fQuit)
{
// EventLoop
while(pEvent->FetchEvents())
{
if(pEvent->IsQuit()) fQuit = true;
if(pEvent->IsKeyUp(SDLK_a)) fprintf(stderr,"'a' was released\n");
if(pEvent->IsKeyDown(SDLK_b) && pInput->ModActive(KMOD_LCTRL)) fprintf(stderr,"STRG+B once\n");
if(pEvent->IsKeyDown(SDLK_SPACE))
{
if(pAudio->IsMusicPlaying()) fprintf(stderr,"music plays\n");
if(pAudio->IsMusicPaused()) fprintf(stderr,"music is paused\n");
}
if(pEvent->IsKeyDown(SDLK_b))
{
if(pAudio->IsMusicPlaying())
{
pAudio->PauseMusic();
fprintf(stderr,"pause>>");
}
else if(pAudio->IsMusicPaused())
{
pAudio->ResumeMusic();
fprintf(stderr,"resume>>");
}
}
if(pEvent->IsKeyDown(SDLK_c)) pAudio->StopMusic(false);
if(pEvent->IsKeyDown(SDLK_v)) pAudio->ResumeMusic();
}
// Eingabebuffer aktualisieren
pInput->FetchKeyboard();
pInput->FetchMouse();
// Tastatureingaben pruefen
if(pInput->ModActive(KMOD_LCTRL) && pInput->KeyPressed(SDLK_a))
{
fprintf(stderr,"STRG+A\n");
}
if(pInput->KeyPressed(SDLK_ESCAPE)) fQuit = true;
pVideo->Refresh();
SDL_Delay(50);
}
delete pVideo;
delete pEvent;
delete pInput;
delete pAudio;
SDL_Quit();
}
--
Was die Treiber angeht, ich will versuchen ALSA zu bekommen, wenn ich dazu was finde. Auf Windows habe ich's noch nicht ausprobiert. Danke für den Tip, das werde ich gleich mal machen.