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