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

mixer.cpp

Go to the documentation of this file.
00001 #include <algorithm>
00002 #include "audiere.h"
00003 #include "mixer.hpp"
00004 #include "output.hpp"
00005 #include "resampler.hpp"
00006 
00007 
00009 
00010 Mixer::Mixer()
00011 {
00012 }
00013 
00015 
00016 Mixer::~Mixer()
00017 {
00018   // assume all streams have been removed
00019 }
00020 
00022 
00023 void
00024 Mixer::GetFormat(int& channel_count, int& sample_rate, int& bits_per_sample)
00025 {
00026   channel_count = 2;
00027   sample_rate = 44100;
00028   bits_per_sample = 16;
00029 }
00030 
00032 
00033 int
00034 Mixer::Read(const int sample_count, void* samples)
00035 {
00036   // are any sources playing?
00037   bool any_playing = false;
00038   SourceMap::iterator i = m_sources.begin();
00039   while (i != m_sources.end()) {
00040     any_playing |= i->second.is_playing;
00041     ++i;
00042   }
00043   
00044   // if not, return zeroed samples
00045   if (!any_playing) {
00046     memset(samples, 0, 4 * sample_count);
00047     return sample_count;
00048   }
00049 
00050   static const int BUFFER_SIZE = 4096;
00051 
00052   // create buffers in which to mix
00053   adr_s32 mix_buffer[BUFFER_SIZE];
00054   adr_s16 stream_buffer[BUFFER_SIZE * 2];
00055   std::fill(mix_buffer, mix_buffer + BUFFER_SIZE, 0);
00056 
00057   adr_s16* out = (adr_s16*)samples;
00058   int left = sample_count;
00059   while (left > 0) {
00060     int playing = 0;
00061     int to_mix = std::min(BUFFER_SIZE, left);
00062 
00063     SourceMap::iterator s = m_sources.begin();
00064     for (; s != m_sources.end(); ++s) {
00065       if (s->second.is_playing) {
00066         Read(s->first, s->second, to_mix, stream_buffer);
00067         for (int i = 0; i < to_mix * 2; ++i) {
00068           mix_buffer[i] += stream_buffer[i];
00069         }
00070         ++playing;
00071       }
00072     }
00073 
00074     // do the division
00075     if (playing != 0) {
00076       for (int i = 0; i < to_mix * 2; ++i) {
00077         *out++ = mix_buffer[i] / playing;
00078       }
00079     }
00080 
00081     left -= to_mix;
00082   }
00083 
00084   return sample_count;
00085 }
00086 
00088 
00089 bool
00090 Mixer::Reset()
00091 {
00092   return true;
00093 }
00094 
00096 
00097 void
00098 Mixer::AddSource(ISampleSource* source)
00099 {
00100   // initial source attributes
00101   SourceAttributes sa;
00102   sa.resampler = new Resampler(source);
00103   sa.last_l = 0;
00104   sa.last_r = 0;
00105   sa.is_playing = true;
00106   sa.volume = ADR_VOLUME_MAX;
00107 
00108   m_sources[source] = sa;
00109 }
00110 
00112 
00113 void
00114 Mixer::RemoveSource(ISampleSource* source)
00115 {
00116   delete m_sources[source].resampler;
00117   m_sources.erase(source);
00118 }
00119 
00121 
00122 bool
00123 Mixer::IsPlaying(ISampleSource* source)
00124 {
00125   return m_sources[source].is_playing;
00126 }
00127 
00129 
00130 void
00131 Mixer::SetPlaying(ISampleSource* source, bool is_playing)
00132 {
00133   m_sources[source].is_playing = is_playing;
00134 }
00135 
00137 
00138 int
00139 Mixer::GetVolume(ISampleSource* source)
00140 {
00141   return m_sources[source].volume;
00142 }
00143 
00145 
00146 void
00147 Mixer::SetVolume(ISampleSource* source, int volume)
00148 {
00149   m_sources[source].volume = volume;
00150 }
00151 
00153 
00154 void
00155 Mixer::Read(ISampleSource* source,
00156             SourceAttributes& attr,
00157             int to_mix,
00158             adr_s16* buffer)  // size = to_mix * 4
00159 {
00160   unsigned read = attr.resampler->Read(to_mix, buffer);
00161 
00162   if (read == 0) {
00163     attr.is_playing = false;
00164   }
00165 
00166   // grab them early so we don't lose optimizations due to aliasing
00167   adr_s16 l = attr.last_l;
00168   adr_s16 r = attr.last_r;
00169 
00170   adr_s16* out = buffer;
00171   for (int i = 0; i < read; ++i) {
00172     *out = *out * attr.volume / 255;
00173     ++out;
00174     *out = *out * attr.volume / 255;
00175     ++out;
00176   }
00177 
00178   if (read >= 0) {
00179     l = out[-2];
00180     r = out[-1];
00181   }
00182 
00183   for (int i = read; i < to_mix; ++i) {
00184     *out++ = l;
00185     *out++ = r;
00186   }
00187 
00188   attr.last_l = l;
00189   attr.last_r = r;
00190 }
00191 

Generated at Mon Jun 10 02:55:12 2002 for audiere by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001