audio_sound.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software
00006 // and you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
00009 
00010 /*!****************************************************************************
00011  * \file    audio_sound.cpp
00012  * \author  Tyler Olsen, roots@allacrost.org
00013  * \brief   Sound file for sound-related code in the audio engine.
00014  *****************************************************************************/
00015 
00016 #include "audio_sound.h"
00017 
00018 using namespace std;
00019 using namespace hoa_utils;
00020 
00021 namespace hoa_audio {
00022 
00023 namespace private_audio {
00024 
00025 // ****************************************************************************
00026 // ************************ SoundData Class Functions *************************
00027 // ****************************************************************************
00028 
00029 // Creates a new buffer for the filename and loads the WAV data.
00030 
00031 SoundData::SoundData(string fname) {
00032   filename = fname;
00033 
00034   sound = Mix_LoadWAV(filename.c_str());
00035   if (sound == NULL) {
00036     cout << "AUDIO ERROR: Could not open sound file " << filename << ": " << Mix_GetError() << endl;
00037     reference_count = 0;
00038   }
00039   else {
00040     reference_count = 1;
00041   }
00042 }
00043 
00044 SoundData::~SoundData() {
00045   if (reference_count > 0) {
00046     cerr << "AUDIO WARNING: Audio engine is attempting to delete buffer " << filename <<
00047       ", which still has " << static_cast<int32>(reference_count) << " refereces to it\n";
00048   }
00049 
00050   Mix_FreeChunk(sound);
00051   sound = NULL;
00052 }
00053 
00054 
00055 void SoundData::RemoveReference() {
00056   reference_count--;
00057   if (reference_count == 0) {
00058     // TODO: delete the class object and remove it from the sound_data map, but be careful
00059     // delete this;
00060   }
00061 }
00062 
00063 
00064 bool SoundData::IsValid() {
00065   if (sound != NULL && reference_count > 0) {
00066     return true;
00067   }
00068   return false;
00069 }
00070 
00071 
00072 void SoundData::DEBUG_PrintProperties() {
00073   if (IsValid() == false) {
00074     AudioManager->_audio_errors |= AUDIO_ERROR_NO_DATA;
00075     cerr << "ERROR: the data for the file " << filename << " is not valid" << endl;
00076   }
00077   else {
00078     cout << "--------------------------------------------------------------------------------" << endl;
00079     cout << "Filename:      " << filename << endl;
00080     // These properties are not easily available with SDL_mixer
00081 //    cout << "Frequency:   " << property << " Hz" << endl;
00082 //    cout << "Bit depth:   " << property << endl;
00083 //    cout << "Channels:    " << property << endl;
00084     cout << "Size:        " << sound->alen << " bytes" << endl;
00085     cout << "--------------------------------------------------------------------------------" << endl;
00086   }
00087 }
00088 
00089 } // namespace private_audio
00090 
00091 using namespace hoa_audio::private_audio;
00092 
00093 // ****************************************************************************
00094 // ***** SoundDescriptor Class Functions
00095 // ****************************************************************************
00096 
00097 // The constructor does not attempt to retrieve any resources.
00098 SoundDescriptor::SoundDescriptor() {
00099   _data = NULL;
00100   _loop_count = 0;
00101   _fade_in_time = 0;
00102   _fade_out_time = 0;
00103   _play_timeout = -1;
00104 }
00105 
00106 
00107 // The destructor will call the AudioManager singleton to manage the buffer and source that the class was using.
00108 SoundDescriptor::~SoundDescriptor() {
00109   if (_data != NULL) {
00110     _data->RemoveReference();
00111     _data = NULL;
00112   }
00113 }
00114 
00115 
00116 // This constructor will load the sound from memory, if it isn't loaded already.
00117 bool SoundDescriptor::LoadSound(string fname) {
00118   if (fname == "") {
00119     cerr << "AUDIO WARNING: Bad filename passed in LoadSound (empty string)." << endl;
00120     return false;
00121   }
00122 
00123   _data = AudioManager->_AcquireSoundData(fname);
00124   if (_data == NULL) {
00125     cerr << "AUDIO ERROR: Failed to get a buffer for sound file " << fname << endl;
00126     return false;
00127   }
00128   return true;
00129 }
00130 
00131 
00132 void SoundDescriptor::FreeSound() {
00133   if (_data != NULL) {
00134     _data->RemoveReference();
00135     _data = NULL;
00136   }
00137 }
00138 
00139 
00140 // Retrieve the state of the audio
00141 uint8 SoundDescriptor::GetSoundState() {
00142   if (_data == NULL) {
00143     return AUDIO_STATE_UNLOADED;
00144   }
00145 
00146   // This is needed because there is currently no guarantee if the _channel is still playing the chunk...
00147   if (Mix_GetChunk(_channel) != _data->sound) {
00148     return AUDIO_STATE_STOPPED;
00149   }
00150 
00151   switch(Mix_FadingChannel(_channel)) {
00152     case MIX_FADING_IN:
00153       return AUDIO_STATE_FADING_IN;
00154     case MIX_FADING_OUT:
00155       return AUDIO_STATE_FADING_OUT;
00156     default: // MIX_NO_FADING
00157       break;
00158   }
00159   
00160   if (Mix_Playing(_channel) != 0) {
00161     return AUDIO_STATE_PLAYING;
00162   }
00163 
00164   if (Mix_Paused(_channel) != 0) {
00165     return AUDIO_STATE_PAUSED;
00166   }
00167 
00168   return AUDIO_STATE_STOPPED;
00169 }
00170 
00171 
00172 void SoundDescriptor::PlaySound() {
00173   if (_data == NULL) {
00174     AudioManager->_audio_errors |= AUDIO_ERROR_NO_DATA;
00175     return;
00176   }
00177 
00178   if (_fade_in_time != 0) {
00179     _channel = Mix_FadeInChannelTimed(ANY_CHANNEL, _data->sound, _loop_count, _fade_in_time, _play_timeout);
00180   }
00181   else {
00182     _channel = Mix_PlayChannelTimed(ANY_CHANNEL, _data->sound, _loop_count, _play_timeout);
00183   }
00184 
00185   if (_channel == -1) {
00186     AudioManager->_audio_errors |= AUDIO_ERROR_PLAY_FAILURE;
00187   }
00188 }
00189 
00190 
00191 void SoundDescriptor::PauseSound() {
00192   if (_data == NULL) {
00193     AudioManager->_audio_errors |= AUDIO_ERROR_NO_DATA;
00194     return;
00195   }
00196   
00197   Mix_Pause(_channel);
00198 }
00199 
00200 
00201 void SoundDescriptor::ResumeSound() {
00202   if (_data == NULL) {
00203     AudioManager->_audio_errors |= AUDIO_ERROR_NO_DATA;
00204     return;
00205   }
00206   
00207   Mix_Resume(_channel);
00208 }
00209 
00210 
00211 void SoundDescriptor::StopSound() {
00212   if (_data == NULL) {
00213     AudioManager->_audio_errors |= AUDIO_ERROR_NO_DATA;
00214     return;
00215   }
00216   
00217   if (_fade_out_time != 0) {
00218     Mix_FadeOutChannel(_channel, _fade_out_time);
00219   }
00220   else {
00221     Mix_HaltChannel(_channel);
00222   }
00223 }
00224 
00225 
00226 // void SoundDescriptor::RewindSound() {}
00227 
00228 // void SoundDescriptor::FreeSound() {}
00229 
00230 
00231 } // namespace hoa_audio

Generated on Fri Jul 6 23:11:09 2007 for Hero of Allacrost by  doxygen 1.5.1