AudioMixer.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2005 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 #include "pent_include.h"
00019 #include "AudioMixer.h"
00020 #include "SettingManager.h"
00021 #include "Kernel.h"
00022 
00023 #include "AudioProcess.h"
00024 #include "MusicProcess.h"
00025 #include "AudioChannel.h"
00026 
00027 #include "MidiDriver.h"
00028 
00029 #include <SDL.h>
00030 
00031 namespace Pentagram {
00032 
00033 AudioMixer *AudioMixer::the_audio_mixer = 0;
00034 
00035 AudioMixer::AudioMixer(int sample_rate_, bool stereo_, int num_channels_) : 
00036                 audio_ok(false), 
00037                 sample_rate(sample_rate_), stereo(stereo_),
00038                 midi_driver(0), midi_volume(255),
00039                 num_channels(num_channels_), channels(0)
00040 {
00041         the_audio_mixer = this;
00042 
00043         con.Print(MM_INFO, "Creating AudioMixer...\n");
00044 
00045         SDL_AudioSpec desired, obtained;
00046 
00047         desired.format = AUDIO_S16SYS;
00048         desired.freq = sample_rate_;
00049         desired.channels = stereo_?2:1;
00050         desired.samples = 1024;
00051         desired.callback = sdlAudioCallback;
00052         desired.userdata = reinterpret_cast<void*>(this);
00053 
00054 #ifdef UNDER_CE
00055         desired.freq = 11025;
00056         desired.channels = 1;
00057 #endif
00058 
00059         // Open SDL Audio (even though we may not need it)
00060         SDL_InitSubSystem(SDL_INIT_AUDIO);
00061         int ret = SDL_OpenAudio(&desired, &obtained);
00062         audio_ok = (ret == 0);
00063 
00064         if (audio_ok) {
00065                 pout << "Audio opened using format: " << obtained.freq << " Hz " << (int) obtained.channels << " Channels" <<  std::endl;
00066                 // Lock the audio
00067                 Lock();
00068 
00069                 sample_rate = obtained.freq;
00070                 stereo = obtained.channels == 2;
00071 
00072                 channels = new AudioChannel*[num_channels];
00073                 for (int i=0;i<num_channels;i++)
00074                         channels[i] = new AudioChannel(sample_rate,stereo);
00075 
00076                 // Unlock it
00077                 Unlock();
00078 
00079                 // GO GO GO!
00080                 SDL_PauseAudio(0);
00081         }
00082 }
00083 
00084 void AudioMixer::createProcesses()
00085 {
00086         Kernel *kernel = Kernel::get_instance();
00087 
00088         // Create the Audio Process
00089         kernel->addProcess(new AudioProcess());
00090 
00091         // Create the Music Process
00092         kernel->addProcess(new MusicProcess(midi_driver));
00093 }
00094 
00095 AudioMixer::~AudioMixer(void)
00096 {
00097         con.Print(MM_INFO, "Destroying AudioMixer...\n");
00098 
00099         closeMidiOutput();
00100 
00101         SDL_CloseAudio();
00102 
00103         the_audio_mixer = 0;
00104 
00105         if (channels) for (int i=0;i<num_channels;i++) delete channels[i];
00106         delete [] channels;
00107 }
00108 
00109 void AudioMixer::Lock()
00110 {
00111         SDL_LockAudio();
00112 }
00113 
00114 void AudioMixer::Unlock()
00115 {
00116         SDL_UnlockAudio();
00117 }
00118 
00119 void AudioMixer::reset()
00120 {
00121         if (!audio_ok) return;
00122 
00123         con.Print(MM_INFO, "Resetting AudioMixer...\n");
00124 
00125         Lock();
00126 
00127         if (midi_driver) {
00128                 for (int i = 0; i < midi_driver->maxSequences(); i++) {
00129                         midi_driver->finishSequence(i);
00130                 }
00131         }
00132 
00133         if (channels) for (int i=0;i<num_channels;i++) channels[i]->stop();
00134 
00135         Unlock();
00136 }
00137 
00138 int AudioMixer::playSample(AudioSample *sample, int loop, int priority, bool paused, uint32 pitch_shift_, int lvol, int rvol)
00139 {
00140         if (!audio_ok || !channels) return -1;
00141 
00142         int lowest = -1;
00143         int lowprior = 65536;
00144 
00145         // Lock the audio
00146         Lock();
00147 
00148         int i;
00149         for (i=0;i<num_channels;i++)
00150         {
00151                 if (!channels[i]->isPlaying()) {
00152                         lowest = i;
00153                         break;
00154                 }
00155                 else if (channels[i]->getPriority() < priority) {
00156                         lowprior = channels[i]->getPriority();
00157                         lowest = i;
00158                 }
00159         }
00160 
00161         if (i != num_channels || lowprior < priority)
00162                 channels[lowest]->playSample(sample,loop,priority,paused,pitch_shift_,lvol,rvol);
00163         else 
00164                 lowest = -1;
00165 
00166         // Unlock
00167         Unlock();
00168 
00169         return lowest;
00170 }
00171 
00172 bool AudioMixer::isPlaying(int chan)
00173 {
00174         if (chan > num_channels || chan < 0 || !channels || !audio_ok) return 0;
00175 
00176         Lock();
00177 
00178                 bool playing = channels[chan]->isPlaying();
00179 
00180         Unlock();
00181 
00182         return playing;
00183 }
00184 
00185 void AudioMixer::stopSample(int chan)
00186 {
00187         if (chan > num_channels || chan < 0 || !channels || !audio_ok) return;
00188 
00189         Lock();
00190 
00191                 channels[chan]->stop();
00192 
00193         Unlock();
00194 }
00195 
00196 void AudioMixer::setPaused(int chan, bool paused)
00197 {
00198         if (chan > num_channels || chan < 0 || !channels || !audio_ok) return;
00199 
00200         Lock();
00201 
00202                 channels[chan]->setPaused(paused);
00203 
00204         Unlock();
00205 }
00206 
00207 bool AudioMixer::isPaused(int chan)
00208 {
00209         if (chan > num_channels || chan < 0 || !channels || !audio_ok) return false;
00210 
00211         Lock();
00212 
00213                 bool ret = channels[chan]->isPaused();
00214 
00215         Unlock();
00216 
00217         return ret;
00218 }
00219 
00220 void AudioMixer::setVolume(int chan, int lvol, int rvol)
00221 {
00222         if (chan > num_channels || chan < 0 || !channels || !audio_ok) return;
00223 
00224         Lock();
00225 
00226                 channels[chan]->setVolume(lvol,rvol);
00227 
00228         Unlock();
00229 }
00230 
00231 void AudioMixer::getVolume(int chan, int &lvol, int &rvol)
00232 {
00233         if (chan > num_channels || chan < 0 || !channels || !audio_ok) return;
00234 
00235         Lock();
00236 
00237                 channels[chan]->getVolume(lvol,rvol);
00238 
00239         Unlock();
00240 }
00241         
00242 
00243 void AudioMixer::sdlAudioCallback(void *userdata, Uint8 *stream, int len)
00244 {
00245         AudioMixer *mixer = reinterpret_cast<AudioMixer *>(userdata);
00246 
00247         mixer->MixAudio(reinterpret_cast<sint16*>(stream), len);
00248 }
00249 
00250 void AudioMixer::MixAudio(sint16 *stream, uint32 bytes)
00251 {
00252         if (!audio_ok) return;
00253 
00254         if (midi_driver && midi_driver->isSampleProducer())
00255                 midi_driver->produceSamples(stream, bytes);
00256 
00257         if (channels) for (int i=0;i<num_channels;i++)
00258                 if (channels[i]->isPlaying()) channels[i]->resampleAndMix(stream,bytes);
00259 }
00260 
00261 void AudioMixer::openMidiOutput()
00262 {
00263         if (midi_driver) return;
00264         if (!audio_ok) return;
00265 
00266         MidiDriver * new_driver = 0;
00267         con.Print(MM_INFO, "Initializing MidiDriver...\n");
00268 
00269         SettingManager *settingman = SettingManager::get_instance();
00270 
00271         // First thing attempt to find the Midi driver as specified in the config
00272         std::string desired_driver;
00273         settingman->setDefault("midi_driver", "default");
00274         settingman->get("midi_driver", desired_driver);
00275 
00276         // Has the config file specified disabled midi?
00277         if (audio_ok) new_driver = MidiDriver::createInstance(desired_driver,sample_rate,stereo);
00278 
00279         // If the driver is a 'sample' producer we need to hook it to SDL
00280         if (new_driver)
00281         {
00282                 Lock();
00283                 midi_driver = new_driver;
00284                 Unlock();
00285                 midi_driver->setGlobalVolume(midi_volume);
00286         }
00287 }
00288 
00289 void AudioMixer::closeMidiOutput()
00290 {
00291         if (!midi_driver) return;
00292         con.Print(MM_INFO, "Destroying MidiDriver...\n");
00293 
00294         midi_driver->destroyMidiDriver();
00295 
00296         Lock();
00297         delete midi_driver;
00298         midi_driver = 0;
00299         Unlock();
00300 }
00301 
00302 };

Generated on Fri Jul 27 22:27:09 2007 for pentagram by  doxygen 1.4.7