diff options
Diffstat (limited to 'src/audio')
-rw-r--r-- | src/audio/player.c | 29 | ||||
-rw-r--r-- | src/audio/player.h | 3 |
2 files changed, 29 insertions, 3 deletions
diff --git a/src/audio/player.c b/src/audio/player.c index 177613bb..2d6767ea 100644 --- a/src/audio/player.c +++ b/src/audio/player.c | |||
@@ -146,6 +146,7 @@ iDeclareType(ContentSpec) | |||
146 | struct Impl_ContentSpec { | 146 | struct Impl_ContentSpec { |
147 | SDL_AudioFormat inputFormat; | 147 | SDL_AudioFormat inputFormat; |
148 | SDL_AudioSpec output; | 148 | SDL_AudioSpec output; |
149 | uint64_t totalSamples; | ||
149 | iRanges wavData; | 150 | iRanges wavData; |
150 | }; | 151 | }; |
151 | 152 | ||
@@ -168,6 +169,8 @@ struct Impl_Decoder { | |||
168 | size_t inputPos; | 169 | size_t inputPos; |
169 | iSampleBuf output; | 170 | iSampleBuf output; |
170 | iMutex outputMutex; | 171 | iMutex outputMutex; |
172 | uint64_t currentSample; | ||
173 | uint64_t totalSamples; /* zero if unknown */ | ||
171 | iRanges wavData; | 174 | iRanges wavData; |
172 | }; | 175 | }; |
173 | 176 | ||
@@ -252,6 +255,7 @@ static enum iDecoderParseStatus parseWav_Decoder_(iDecoder *d, iRanges inputRang | |||
252 | } | 255 | } |
253 | } | 256 | } |
254 | iGuardMutex(&d->outputMutex, write_SampleBuf(&d->output, samples, n)); | 257 | iGuardMutex(&d->outputMutex, write_SampleBuf(&d->output, samples, n)); |
258 | d->currentSample += n; | ||
255 | free(samples); | 259 | free(samples); |
256 | return ok_DecoderParseStatus; | 260 | return ok_DecoderParseStatus; |
257 | } | 261 | } |
@@ -305,6 +309,8 @@ void init_Decoder(iDecoder *d, iInputBuf *input, const iContentSpec *spec) { | |||
305 | spec->output.format, | 309 | spec->output.format, |
306 | spec->output.channels, | 310 | spec->output.channels, |
307 | spec->output.samples * 2); | 311 | spec->output.samples * 2); |
312 | d->currentSample = 0; | ||
313 | d->totalSamples = spec->totalSamples; | ||
308 | init_Mutex(&d->outputMutex); | 314 | init_Mutex(&d->outputMutex); |
309 | d->thread = new_Thread(run_Decoder_); | 315 | d->thread = new_Thread(run_Decoder_); |
310 | setUserData_Thread(d->thread, d); | 316 | setUserData_Thread(d->thread, d); |
@@ -366,6 +372,7 @@ static iContentSpec contentSpec_Player_(const iPlayer *d) { | |||
366 | return content; | 372 | return content; |
367 | } | 373 | } |
368 | /* Read all the chunks. */ | 374 | /* Read all the chunks. */ |
375 | int16_t blockAlign = 0; | ||
369 | while (!atEnd_Buffer(buf)) { | 376 | while (!atEnd_Buffer(buf)) { |
370 | readData_Buffer(buf, 4, magic); | 377 | readData_Buffer(buf, 4, magic); |
371 | const size_t size = read32_Stream(is); | 378 | const size_t size = read32_Stream(is); |
@@ -381,7 +388,7 @@ static iContentSpec contentSpec_Player_(const iPlayer *d) { | |||
381 | const int16_t numChannels = read16_Stream(is); | 388 | const int16_t numChannels = read16_Stream(is); |
382 | const int32_t freq = read32_Stream(is); | 389 | const int32_t freq = read32_Stream(is); |
383 | const uint32_t bytesPerSecond = readU32_Stream(is); | 390 | const uint32_t bytesPerSecond = readU32_Stream(is); |
384 | const int16_t blockAlign = read16_Stream(is); | 391 | blockAlign = read16_Stream(is); |
385 | const int16_t bitsPerSample = read16_Stream(is); | 392 | const int16_t bitsPerSample = read16_Stream(is); |
386 | const uint16_t extSize = (size == 18 ? readU16_Stream(is) : 0); | 393 | const uint16_t extSize = (size == 18 ? readU16_Stream(is) : 0); |
387 | iUnused(bytesPerSecond); | 394 | iUnused(bytesPerSecond); |
@@ -418,7 +425,8 @@ static iContentSpec contentSpec_Player_(const iPlayer *d) { | |||
418 | } | 425 | } |
419 | } | 426 | } |
420 | else if (memcmp(magic, "data", 4) == 0) { | 427 | else if (memcmp(magic, "data", 4) == 0) { |
421 | content.wavData = (iRanges){ pos_Stream(is), pos_Stream(is) + size }; | 428 | content.wavData = (iRanges){ pos_Stream(is), pos_Stream(is) + size }; |
429 | content.totalSamples = (uint64_t) size_Range(&content.wavData) / blockAlign; | ||
422 | break; | 430 | break; |
423 | } | 431 | } |
424 | else { | 432 | else { |
@@ -465,11 +473,16 @@ iBool isStarted_Player(const iPlayer *d) { | |||
465 | return d->device != 0; | 473 | return d->device != 0; |
466 | } | 474 | } |
467 | 475 | ||
468 | void setFormatHint_Player(iPlayer *d, const char *hint) { | 476 | iBool isPaused_Player(const iPlayer *d) { |
477 | if (!d->device) return iTrue; | ||
478 | return SDL_GetAudioDeviceStatus(d->device) == SDL_AUDIO_PAUSED; | ||
479 | } | ||
469 | 480 | ||
481 | void setFormatHint_Player(iPlayer *d, const char *hint) { | ||
470 | } | 482 | } |
471 | 483 | ||
472 | void updateSourceData_Player(iPlayer *d, const iBlock *data, enum iPlayerUpdate update) { | 484 | void updateSourceData_Player(iPlayer *d, const iBlock *data, enum iPlayerUpdate update) { |
485 | /* TODO: Add MIME as argument */ | ||
473 | iInputBuf *input = d->data; | 486 | iInputBuf *input = d->data; |
474 | lock_Mutex(&input->mtx); | 487 | lock_Mutex(&input->mtx); |
475 | switch (update) { | 488 | switch (update) { |
@@ -527,3 +540,13 @@ void stop_Player(iPlayer *d) { | |||
527 | d->decoder = NULL; | 540 | d->decoder = NULL; |
528 | } | 541 | } |
529 | } | 542 | } |
543 | |||
544 | float time_Player(const iPlayer *d) { | ||
545 | if (!d->decoder) return 0; | ||
546 | return (float) ((double) d->decoder->currentSample / (double) d->spec.freq); | ||
547 | } | ||
548 | |||
549 | float duration_Player(const iPlayer *d) { | ||
550 | if (!d->decoder) return 0; | ||
551 | return (float) ((double) d->decoder->totalSamples / (double) d->spec.freq); | ||
552 | } | ||
diff --git a/src/audio/player.h b/src/audio/player.h index 2138c556..5c17ef6c 100644 --- a/src/audio/player.h +++ b/src/audio/player.h | |||
@@ -41,3 +41,6 @@ void setPaused_Player (iPlayer *, iBool isPaused); | |||
41 | void stop_Player (iPlayer *); | 41 | void stop_Player (iPlayer *); |
42 | 42 | ||
43 | iBool isStarted_Player (const iPlayer *); | 43 | iBool isStarted_Player (const iPlayer *); |
44 | iBool isPaused_Player (const iPlayer *); | ||
45 | float time_Player (const iPlayer *); | ||
46 | float duration_Player (const iPlayer *); | ||