00001 #include "device_ds_stream.h"
00002 #include "device_ds.h"
00003 #include "debug.h"
00004
00005
00006 namespace audiere {
00007
00008 DSOutputStream::DSOutputStream(
00009 DSAudioDevice* device,
00010 IDirectSoundBuffer* buffer,
00011 int buffer_length,
00012 SampleSource* source)
00013 {
00014 ADR_GUARD("DSOutputStream::DSOutputStream");
00015
00016 m_device = device;
00017
00018 m_buffer = buffer;
00019 m_buffer_length = buffer_length;
00020 m_next_read = 0;
00021 m_last_play = 0;
00022
00023 DWORD frequency;
00024 m_buffer->GetFrequency(&frequency);
00025 m_base_frequency = frequency;
00026
00027 m_is_playing = false;
00028
00029 m_source = new RepeatableStream(source);
00030
00031 int channel_count, sample_rate;
00032 SampleFormat sample_format;
00033 source->getFormat(channel_count, sample_rate, sample_format);
00034 m_sample_size = GetSampleSize(sample_format) * channel_count;
00035
00036 m_total_read = 0;
00037 m_total_written = 0;
00038
00039 m_last_sample = new BYTE[m_sample_size];
00040
00041 setVolume(1);
00042 setPan(0);
00043
00044
00045 fillStream();
00046 }
00047
00048
00049 DSOutputStream::~DSOutputStream() {
00050 ADR_GUARD("DSOutputStream::~DSOutputStream");
00051
00052 m_device->removeStream(this);
00053
00054
00055 m_buffer->Release();
00056 delete[] m_last_sample;
00057 }
00058
00059
00060 void
00061 DSOutputStream::play() {
00062 ADR_GUARD("DSOutputStream::play");
00063 m_buffer->Play(0, 0, DSBPLAY_LOOPING);
00064 m_is_playing = true;
00065 }
00066
00067
00068 void
00069 DSOutputStream::stop() {
00070 ADR_GUARD("DSOutputStream::stop");
00071 m_buffer->Stop();
00072 m_is_playing = false;
00073 }
00074
00075
00076 bool
00077 DSOutputStream::isPlaying() {
00078 return m_is_playing;
00079 }
00080
00081
00082 void
00083 DSOutputStream::reset() {
00084 ADR_GUARD("DSOutputStream::reset");
00085 SYNCHRONIZED(this);
00086
00087
00088 bool is_playing = isPlaying();
00089
00090
00091 if (is_playing) {
00092 stop();
00093 }
00094
00095 m_buffer->SetCurrentPosition(0);
00096 m_last_play = 0;
00097
00098 m_source->reset();
00099 m_total_read = 0;
00100 m_total_written = 0;
00101 m_next_read = 0;
00102 fillStream();
00103
00104
00105 if (is_playing) {
00106 play();
00107 }
00108 }
00109
00110
00111 void
00112 DSOutputStream::setRepeat(bool repeat) {
00113 SYNCHRONIZED(this);
00114 m_source->setRepeat(repeat);
00115 }
00116
00117
00118 bool
00119 DSOutputStream::getRepeat() {
00120 SYNCHRONIZED(this);
00121 return m_source->getRepeat();
00122 }
00123
00124
00125 void
00126 DSOutputStream::setVolume(float volume) {
00127 m_volume = volume;
00128 m_buffer->SetVolume(DSAudioDevice::Volume_AudiereToDirectSound(volume));
00129 }
00130
00131
00132 float
00133 DSOutputStream::getVolume() {
00134 return m_volume;
00135 }
00136
00137
00138 void
00139 DSOutputStream::setPan(float pan) {
00140 m_pan = pan;
00141 m_buffer->SetPan(DSAudioDevice::Pan_AudiereToDirectSound(pan));
00142 }
00143
00144
00145 float
00146 DSOutputStream::getPan() {
00147 return m_pan;
00148 }
00149
00150
00151 void
00152 DSOutputStream::setPitchShift(float shift) {
00153 m_buffer->SetFrequency(DWORD(m_base_frequency * shift));
00154 }
00155
00156
00157 float
00158 DSOutputStream::getPitchShift() {
00159 DWORD frequency;
00160 m_buffer->GetFrequency(&frequency);
00161 return float(frequency) / m_base_frequency;
00162 }
00163
00164
00165 bool
00166 DSOutputStream::isSeekable() {
00167 SYNCHRONIZED(this);
00168 return m_source->isSeekable();
00169 }
00170
00171
00172 int
00173 DSOutputStream::getLength() {
00174 SYNCHRONIZED(this);
00175 return m_source->getLength();
00176 }
00177
00178
00179 void
00180 DSOutputStream::setPosition(int position) {
00181 SYNCHRONIZED(this);
00182
00183
00184 bool is_playing = isPlaying();
00185
00186
00187 if (is_playing) {
00188 stop();
00189 }
00190
00191 m_source->setPosition(position);
00192 m_last_play = 0;
00193
00194 m_source->setPosition(position);
00195 m_total_read = 0;
00196 m_total_written = 0;
00197 m_next_read = 0;
00198 fillStream();
00199
00200
00201 if (is_playing) {
00202 play();
00203 }
00204 }
00205
00206
00207 int
00208 DSOutputStream::getPosition() {
00209 SYNCHRONIZED(this);
00210 int pos = m_source->getPosition() - (m_total_read - m_total_written);
00211 if (pos < 0) {
00212 pos += m_source->getLength();
00213 }
00214 return pos;
00215 }
00216
00217
00218 void
00219 DSOutputStream::fillStream() {
00220 ADR_GUARD("DSOutputStream::fillStream");
00221
00222
00223
00224 void* buffer = NULL;
00225 DWORD buffer_length = 0;
00226
00227
00228 HRESULT result = m_buffer->Lock(
00229 0,
00230 m_buffer_length * m_sample_size,
00231 &buffer,
00232 &buffer_length,
00233 NULL,
00234 NULL,
00235 0);
00236 if (FAILED(result) || !buffer) {
00237 ADR_LOG("FillStream failed!");
00238 return;
00239 }
00240
00241 ADR_IF_DEBUG {
00242 char str[80];
00243 sprintf(str, "Buffer Length = %d", buffer_length);
00244 ADR_LOG(str);
00245 }
00246
00247
00248 int samples_to_read = buffer_length / m_sample_size;
00249 int samples_read = streamRead(samples_to_read, buffer);
00250 if (samples_read != samples_to_read) {
00251 m_next_read = samples_read;
00252 } else {
00253 m_next_read = 0;
00254 }
00255
00256
00257 m_buffer->Unlock(buffer, buffer_length, NULL, 0);
00258 }
00259
00260
00261 void
00262 DSOutputStream::update() {
00263 SYNCHRONIZED(this);
00264
00265
00266 if (!isPlaying()) {
00267 return;
00268 }
00269
00270 ADR_GUARD("DSOutputStream::update");
00271
00272
00273
00274
00275 DWORD play, write;
00276 HRESULT result = m_buffer->GetCurrentPosition(&play, &write);
00277 if (FAILED(result)) {
00278 ADR_LOG("GetCurrentPosition failed");
00279 return;
00280 }
00281
00282 ADR_IF_DEBUG {
00283 char str[160];
00284 sprintf(str,
00285 "play: %d write: %d nextread: %d",
00286 play, write, m_next_read);
00287 ADR_LOG(str);
00288 }
00289
00290
00291 play /= m_sample_size;
00292 write /= m_sample_size;
00293
00294
00295 if (play < m_last_play) {
00296 m_total_written += play + m_buffer_length - m_last_play;
00297 } else {
00298 m_total_written += play - m_last_play;
00299 }
00300 m_last_play = play;
00301
00302
00303 int read_length = play - m_next_read;
00304 if (read_length < 0) {
00305 read_length += m_buffer_length;
00306 }
00307
00308 if (read_length == 0) {
00309 return;
00310 }
00311
00312
00313 void* buffer1;
00314 void* buffer2;
00315 DWORD buffer1_length;
00316 DWORD buffer2_length;
00317 result = m_buffer->Lock(
00318 m_next_read * m_sample_size,
00319 read_length * m_sample_size,
00320 &buffer1, &buffer1_length,
00321 &buffer2, &buffer2_length,
00322 0);
00323 if (FAILED(result)) {
00324 ADR_LOG("Lock() failed!");
00325 return;
00326 }
00327
00328 ADR_IF_DEBUG {
00329 char str[160];
00330 sprintf(str, "buffer1: %d buffer2: %d", buffer1_length, buffer2_length);
00331 ADR_LOG(str);
00332 }
00333
00334
00335 int length1 = buffer1_length / m_sample_size;
00336 int length2 = buffer2_length / m_sample_size;
00337 int read = streamRead(length1, buffer1);
00338 if (length1 == read) {
00339 read += streamRead(length2, buffer2);
00340 }
00341
00342 ADR_IF_DEBUG {
00343 char str[80];
00344 sprintf(str, "read: %d", read);
00345 ADR_LOG(str);
00346 }
00347
00348 m_next_read = (m_next_read + read) % m_buffer_length;
00349
00350
00351 m_buffer->Unlock(buffer1, buffer1_length, buffer2, buffer2_length);
00352
00353
00354
00355 if (m_total_written > m_total_read) {
00356 ADR_LOG("Stopping stream!");
00357
00358 stop();
00359 m_buffer->SetCurrentPosition(0);
00360 m_last_play = 0;
00361
00362 m_source->reset();
00363
00364 m_total_written = 0;
00365 m_total_read = 0;
00366 m_next_read = 0;
00367 fillStream();
00368
00369 return;
00370 }
00371 }
00372
00373
00374
00375 int
00376 DSOutputStream::streamRead(int sample_count, void* samples) {
00377 ADR_GUARD("streamRead");
00378
00379
00380 int samples_read = m_source->read(sample_count, samples);
00381
00382
00383 if (samples_read > 0) {
00384 memcpy(
00385 m_last_sample,
00386 (BYTE*)samples + (samples_read - 1) * m_sample_size,
00387 m_sample_size);
00388 }
00389
00390
00391 BYTE* out = (BYTE*)samples + m_sample_size * samples_read;
00392 int c = sample_count - samples_read;
00393 while (c--) {
00394 memcpy(out, m_last_sample, m_sample_size);
00395 out += m_sample_size;
00396 }
00397
00398 m_total_read += samples_read;
00399 return samples_read;
00400 }
00401
00402 }