(C++) SDL_mixer ist Stumm



  • Hallo!

    Ich arbeite gerade an einer kleinen Spieleengine für mich, die auf Windows und Linux laufen soll. Daher benutze ich auch SDL. Bisher habe ich schon alles mögliche für Video, Events, Input usw. gekapselt und läuft auch alles super. Nun möchte ich aber gerne etwas Musik ins Spiel bringen. Also habe ich mir SDL_mixer runtergeladen, die libvorbis usw. für OGG-Support ist auch alles installiert. Ich schaffe es sogar ohne jegliche Fehlermeldungen OGGs abzuspielen. Wenn ich den Status mit Mix_PlayingMusic prüfe erzählt er mir auch, dass die Musik läuft (Rückgabewert = 1). Aber ich höre nichts!
    Mag es vielleicht an Linux liegen? Ich hatte schon öfter Probleme mit dem Sound-System von Linux, und mich nervt vor allem das irgendwie immer nur ein Channel gleichzeitig ausgegeben wird, was auch zur Folge hat, dass wenn bei XMMS kurz Ruhe ist um den nächsten Track zu laden unzählige (unterdrückte) Sounds von anderen Programmen auftauchen. Bis vor kurzem hatte ich noch nicht einmal Sound, ich musste erst einen bestimmten Channel Stumm schalten, damit was zu hören war (was irgendwie komisch ist) - aber das ist eine andere Geschichte.
    Also was kann ich machen? Er scheint ja zu spielen, ich höre nur nichts!
    Der Code ist richtig, ich habe ihn im Nachhinein mit unzähligen Tutorials und Beispielcodes verglichen.



  • Wenn dein Programm unter Linux und Windows laufen soll, dann probiers mal unter Windows. Vielleicht liegts wirklich an der Einstellung deiner Soundkarte. Vielleicht könnstest du auch ein kleines Code Beispiel posten, welches bei dir nicht klappt.



  • @MAG
    Das sieht danach aus, als hättest du irgend einen schlechten OSS Treiber eingerichtet. Versuch lieber mal einen ALSA Treiber zu nehmen oder nimm einen Soundserver wie arts oder jackd zur Ausgabe.



  • 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.


Log in to reply