device_mixer.cpp

Go to the documentation of this file.
00001 #ifdef _MSC_VER
00002 #pragma warning(disable : 4786)
00003 #endif
00004 
00005 
00006 #include <algorithm>
00007 #include "device_mixer.h"
00008 #include "resampler.h"
00009 #include "utility.h"
00010 
00011 
00012 namespace audiere {
00013 
00014   MixerDevice::MixerDevice(int rate) {
00015     m_rate = rate;
00016   }
00017 
00018 
00019   OutputStream*
00020   MixerDevice::openStream(SampleSource* source) {
00021     return (source ? new MixerStream(this, source, m_rate) : 0);
00022   }
00023 
00024 
00025   OutputStream*
00026   MixerDevice::openBuffer(
00027     void* samples, int frame_count,
00028     int channel_count, int sample_rate, SampleFormat sample_format)
00029   {
00030     return openStream(OpenBufferStream(
00031       samples, frame_count,
00032       channel_count, sample_rate, sample_format));
00033   }
00034 
00035 
00036   int
00037   MixerDevice::read(const int sample_count, void* samples) {
00038 //    ADR_GUARD("MixerDevice::read");
00039 
00040     SYNCHRONIZED(this);
00041 
00042 //    ADR_LOG("done locking mixer device");
00043 
00044     // are any sources playing?
00045     bool any_playing = false;
00046     for (std::list<MixerStream*>::iterator i = m_streams.begin();
00047          i != m_streams.end();
00048          ++i)
00049     {
00050       any_playing |= (*i)->m_is_playing;
00051     }
00052   
00053     // if not, return zeroed samples
00054     if (!any_playing) {
00055       memset(samples, 0, 4 * sample_count);
00056       return sample_count;
00057     }
00058 
00059     ADR_LOG("at least one stream is playing");
00060 
00061     // buffer in which to mix the audio
00062     static const int BUFFER_SIZE = 4096;
00063 
00064     // mix the output in chunks of BUFFER_SIZE samples
00065     s16* out = (s16*)samples;
00066     int left = sample_count;
00067     while (left > 0) {
00068       int to_mix = std::min(BUFFER_SIZE, left);
00069 
00070       s32 mix_buffer[BUFFER_SIZE];
00071       memset(mix_buffer, 0, sizeof(mix_buffer));
00072     
00073       for (std::list<MixerStream*>::iterator s = m_streams.begin();
00074            s != m_streams.end();
00075            ++s)
00076       {
00077         if ((*s)->m_is_playing) {
00078           s16 stream_buffer[BUFFER_SIZE * 2];
00079           (*s)->read(to_mix, stream_buffer);
00080           for (int i = 0; i < to_mix * 2; ++i) {
00081             mix_buffer[i] += stream_buffer[i];
00082           }
00083         }
00084       }
00085 
00086       // clamp each value in the buffer to the valid s16 range
00087       for (int i = 0; i < to_mix * 2; ++i) {
00088         s32 mixed = mix_buffer[i];
00089         if (mixed < -32768) {
00090           mixed = -32768;
00091         } else if (mixed > 32767) {
00092           mixed = 32767;
00093         }
00094         *out++ = (s16)mixed;
00095       }
00096 
00097       left -= to_mix;
00098     }
00099 
00100     return sample_count;
00101   }
00102 
00103 
00104   MixerStream::MixerStream(
00105     MixerDevice* device,
00106     SampleSource* source,
00107     int rate)
00108   {
00109     m_device     = device;
00110     m_source     = new Resampler(source, rate);
00111     m_last_l     = 0;
00112     m_last_r     = 0;
00113     m_is_playing = false;
00114     m_volume     = 255;
00115     m_pan        = 0;
00116 
00117     SYNCHRONIZED(m_device.get());
00118     m_device->m_streams.push_back(this);
00119   }
00120 
00121 
00122   MixerStream::~MixerStream() {
00123     SYNCHRONIZED(m_device.get());
00124     m_device->m_streams.remove(this);
00125   }
00126 
00127 
00128   void
00129   MixerStream::play() {
00130     SYNCHRONIZED(m_device.get());
00131     m_is_playing = true;
00132   }
00133 
00134 
00135   void
00136   MixerStream::stop() {
00137     SYNCHRONIZED(m_device.get());
00138     if (m_is_playing) {
00139       m_is_playing = false;
00140       m_device->fireStopEvent(this, StopEvent::STOP_CALLED);
00141     } else {
00142       m_is_playing = false;
00143     }
00144   }
00145 
00146 
00147   bool
00148   MixerStream::isPlaying() {
00149     SYNCHRONIZED(m_device.get());
00150     return m_is_playing;
00151   }
00152 
00153 
00154   void
00155   MixerStream::reset() {
00156     SYNCHRONIZED(m_device.get());
00157     m_source->reset();
00158   }
00159 
00160 
00161   void
00162   MixerStream::setRepeat(bool repeat) {
00163     SYNCHRONIZED(m_device.get());
00164     m_source->setRepeat(repeat);
00165   }
00166 
00167 
00168   bool
00169   MixerStream::getRepeat() {
00170     SYNCHRONIZED(m_device.get());
00171     return m_source->getRepeat();
00172   }
00173 
00174 
00175   void
00176   MixerStream::setVolume(float volume) {
00177     SYNCHRONIZED(m_device.get());
00178     m_volume = int(volume * 255.0f + 0.5f);
00179   }
00180 
00181 
00182   float
00183   MixerStream::getVolume() {
00184     SYNCHRONIZED(m_device.get());
00185     return (m_volume / 255.0f);
00186   }
00187 
00188 
00189   void
00190   MixerStream::setPan(float pan) {
00191     SYNCHRONIZED(m_device.get());
00192     m_pan = int(pan * 255.0f);
00193   }
00194 
00195 
00196   float
00197   MixerStream::getPan() {
00198     SYNCHRONIZED(m_device.get());
00199     return m_pan / 255.0f;
00200   }
00201 
00202 
00203   void
00204   MixerStream::setPitchShift(float shift) {
00205     SYNCHRONIZED(m_device.get());
00206     m_source->setPitchShift(shift);
00207   }
00208 
00209 
00210   float
00211   MixerStream::getPitchShift() {
00212     SYNCHRONIZED(m_device.get());
00213     return m_source->getPitchShift();
00214   }
00215 
00216 
00217   bool
00218   MixerStream::isSeekable() {
00219     return m_source->isSeekable();
00220   }
00221 
00222 
00223   int
00224   MixerStream::getLength() {
00225     return m_source->getLength();
00226   }
00227 
00228 
00229   void
00230   MixerStream::setPosition(int position) {
00231     SYNCHRONIZED(m_device.get());
00232     m_source->setPosition(position);
00233   }
00234 
00235 
00236   int
00237   MixerStream::getPosition() {
00238     SYNCHRONIZED(m_device.get());
00239     return m_source->getPosition();
00240   }
00241 
00242 
00243   void
00244   MixerStream::read(int frame_count, s16* buffer) {
00245     unsigned read = m_source->read(frame_count, buffer);
00246     s16* out = buffer;
00247 
00248     // if we are done with the sample source, stop and reset it
00249     if (read == 0) {
00250       m_source->reset();
00251       if (m_is_playing) {
00252         m_is_playing = false;
00253         // let subscribers know that the sound was stopped
00254         m_device->fireStopEvent(this, StopEvent::STREAM_ENDED);
00255       } else {
00256         m_is_playing = false;
00257       }
00258     } else {
00259       // do panning and volume normalization
00260       int l_volume, r_volume;
00261       if (m_pan < 0) {
00262         l_volume = 255;
00263         r_volume = 255 + m_pan;
00264       } else {
00265         l_volume = 255 - m_pan;
00266         r_volume = 255;
00267       }
00268 
00269       l_volume *= m_volume;
00270       r_volume *= m_volume;
00271 
00272       for (unsigned i = 0; i < read; ++i) {
00273         *out = *out * l_volume / 255 / 255;
00274         ++out;
00275         *out = *out * r_volume / 255 / 255;
00276         ++out;
00277       }
00278     }
00279 
00280     // if we ready any frames, we can replace the old values
00281     // for the last left and right channel states
00282     int new_l = m_last_l;
00283     int new_r = m_last_r;
00284     if (read > 0) {
00285       new_l = out[-2];
00286       new_r = out[-1];
00287     }
00288 
00289     // and apply the last state to the rest of the buffer
00290     for (int i = read; i < frame_count; ++i) {
00291       *out++ = m_last_l;
00292       *out++ = m_last_r;
00293     }
00294 
00295     m_last_l = new_l;
00296     m_last_r = new_r;
00297   }
00298 
00299 }

Generated on Mon Feb 13 23:07:46 2006 for audiere by  doxygen 1.4.6