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
00039
00040 SYNCHRONIZED(this);
00041
00042
00043
00044
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
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
00062 static const int BUFFER_SIZE = 4096;
00063
00064
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
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
00249 if (read == 0) {
00250 m_source->reset();
00251 if (m_is_playing) {
00252 m_is_playing = false;
00253
00254 m_device->fireStopEvent(this, StopEvent::STREAM_ENDED);
00255 } else {
00256 m_is_playing = false;
00257 }
00258 } else {
00259
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
00281
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
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 }