Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

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         s16 o;
00090         if (mixed < -32768) {
00091           o = -32768;
00092         } else if (mixed > 32767) {
00093           o = 32767;
00094         } else {
00095           o = mixed;
00096         }
00097         *out++ = o;
00098       }
00099 
00100       left -= to_mix;
00101     }
00102 
00103     return sample_count;
00104   }
00105 
00106 
00107   MixerStream::MixerStream(
00108     MixerDevice* device,
00109     SampleSource* source,
00110     int rate)
00111   {
00112     m_device     = device;
00113     m_resampler  = new Resampler(source, rate);
00114     m_source     = new RepeatableStream(m_resampler.get());
00115     m_last_l     = 0;
00116     m_last_r     = 0;
00117     m_is_playing = false;
00118     m_volume     = 255;
00119     m_pan        = 0;
00120 
00121     SYNCHRONIZED(m_device.get());
00122     m_device->m_streams.push_back(this);
00123   }
00124 
00125 
00126   MixerStream::~MixerStream() {
00127     SYNCHRONIZED(m_device.get());
00128     m_device->m_streams.remove(this);
00129   }
00130 
00131 
00132   void
00133   MixerStream::play() {
00134     SYNCHRONIZED(m_device.get());
00135     m_is_playing = true;
00136   }
00137 
00138 
00139   void
00140   MixerStream::stop() {
00141     SYNCHRONIZED(m_device.get());
00142     m_is_playing = false;
00143   }
00144 
00145 
00146   bool
00147   MixerStream::isPlaying() {
00148     SYNCHRONIZED(m_device.get());
00149     return m_is_playing;
00150   }
00151 
00152 
00153   void
00154   MixerStream::reset() {
00155     SYNCHRONIZED(m_device.get());
00156     m_source->reset();
00157   }
00158 
00159 
00160   void
00161   MixerStream::setRepeat(bool repeat) {
00162     SYNCHRONIZED(m_device.get());
00163     m_source->setRepeat(repeat);
00164   }
00165 
00166 
00167   bool
00168   MixerStream::getRepeat() {
00169     SYNCHRONIZED(m_device.get());
00170     return m_source->getRepeat();
00171   }
00172 
00173 
00174   void
00175   MixerStream::setVolume(float volume) {
00176     SYNCHRONIZED(m_device.get());
00177     m_volume = int(volume * 255.0f + 0.5f);
00178   }
00179 
00180 
00181   float
00182   MixerStream::getVolume() {
00183     SYNCHRONIZED(m_device.get());
00184     return (m_volume / 255.0f);
00185   }
00186 
00187 
00188   void
00189   MixerStream::setPan(float pan) {
00190     SYNCHRONIZED(m_device.get());
00191     m_pan = int(pan * 255.0f);
00192   }
00193 
00194 
00195   float
00196   MixerStream::getPan() {
00197     SYNCHRONIZED(m_device.get());
00198     return m_pan / 255.0f;
00199   }
00200 
00201 
00202   void
00203   MixerStream::setPitchShift(float shift) {
00204     SYNCHRONIZED(m_device.get());
00205     m_resampler->setPitchShift(shift);
00206   }
00207 
00208 
00209   float
00210   MixerStream::getPitchShift() {
00211     SYNCHRONIZED(m_device.get());
00212     return m_resampler->getPitchShift();
00213   }
00214 
00215 
00216   bool
00217   MixerStream::isSeekable() {
00218     return m_source->isSeekable();
00219   }
00220 
00221 
00222   int
00223   MixerStream::getLength() {
00224     return m_source->getLength();
00225   }
00226 
00227 
00228   void
00229   MixerStream::setPosition(int position) {
00230     SYNCHRONIZED(m_device.get());
00231     m_source->setPosition(position);
00232   }
00233 
00234 
00235   int
00236   MixerStream::getPosition() {
00237     SYNCHRONIZED(m_device.get());
00238     return m_source->getPosition();
00239   }
00240 
00241 
00242   void
00243   MixerStream::read(int frame_count, s16* buffer) {
00244     unsigned read = m_source->read(frame_count, buffer);
00245 
00246     // if we are done with the sample source, stop and reset it
00247     if (read == 0) {
00248       m_is_playing = false;
00249       m_source->reset();
00250     }
00251 
00252     int l_volume, r_volume;
00253     if (m_pan < 0) {
00254       l_volume = 255;
00255       r_volume = 255 + m_pan;
00256     } else {
00257       l_volume = 255 - m_pan;
00258       r_volume = 255;
00259     }
00260 
00261     l_volume *= m_volume;
00262     r_volume *= m_volume;
00263 
00264     s16* out = buffer;
00265     for (int i = 0; i < read; ++i) {
00266       *out = *out * l_volume / 255 / 255;
00267       ++out;
00268       *out = *out * r_volume / 255 / 255;
00269       ++out;
00270     }
00271 
00272     int l = m_last_l;
00273     int r = m_last_r;
00274 
00275     if (read > 0) {
00276       l = out[-2];
00277       r = out[-1];
00278     }
00279 
00280     for (int i = read; i < frame_count; ++i) {
00281       *out++ = m_last_l;
00282       *out++ = m_last_r;
00283     }
00284 
00285     m_last_l = l;
00286     m_last_r = r;
00287   }
00288 
00289 }

Generated on Sat Oct 12 01:43:02 2002 for audiere by doxygen1.2.17