diff options
author | Jeffrey Goode <jeffg7@gmail.com> | 2009-11-11 07:02:18 +0000 |
---|---|---|
committer | Jeffrey Goode <jeffg7@gmail.com> | 2009-11-11 07:02:18 +0000 |
commit | 0db3308cb56a1589b427f3b712d66480bc4d788f (patch) | |
tree | 85818b2e08662bc156ff5857834e3611f79e9911 | |
parent | db4cab0e665143a3eaa56bdd911a25f534db6caf (diff) | |
download | rockbox-0db3308cb56a1589b427f3b712d66480bc4d788f.tar.gz rockbox-0db3308cb56a1589b427f3b712d66480bc4d788f.zip |
pcmbuf: bug fix with pcmbuf flush, code cleanup, added comments
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23608 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/codec_thread.c | 12 | ||||
-rw-r--r-- | apps/codecs.h | 2 | ||||
-rw-r--r-- | apps/pcmbuf.c | 110 | ||||
-rw-r--r-- | apps/plugins/test_codec.c | 8 |
4 files changed, 64 insertions, 68 deletions
diff --git a/apps/codec_thread.c b/apps/codec_thread.c index dc6533dfc9..21d55a7779 100644 --- a/apps/codec_thread.c +++ b/apps/codec_thread.c | |||
@@ -168,7 +168,7 @@ static void* codec_get_buffer(size_t *size) | |||
168 | return &codecbuf[codec_size]; | 168 | return &codecbuf[codec_size]; |
169 | } | 169 | } |
170 | 170 | ||
171 | static bool codec_pcmbuf_insert_callback( | 171 | static void codec_pcmbuf_insert_callback( |
172 | const void *ch1, const void *ch2, int count) | 172 | const void *ch1, const void *ch2, int count) |
173 | { | 173 | { |
174 | const char *src[2] = { ch1, ch2 }; | 174 | const char *src[2] = { ch1, ch2 }; |
@@ -181,14 +181,14 @@ static bool codec_pcmbuf_insert_callback( | |||
181 | 181 | ||
182 | /* Prevent audio from a previous track from playing */ | 182 | /* Prevent audio from a previous track from playing */ |
183 | if (ci.new_track || ci.stop_codec) | 183 | if (ci.new_track || ci.stop_codec) |
184 | return true; | 184 | return; |
185 | 185 | ||
186 | while ((dest = pcmbuf_request_buffer(&out_count)) == NULL) | 186 | while ((dest = pcmbuf_request_buffer(&out_count)) == NULL) |
187 | { | 187 | { |
188 | cancel_cpu_boost(); | 188 | cancel_cpu_boost(); |
189 | sleep(1); | 189 | sleep(1); |
190 | if (ci.seek_time || ci.new_track || ci.stop_codec) | 190 | if (ci.seek_time || ci.new_track || ci.stop_codec) |
191 | return true; | 191 | return; |
192 | } | 192 | } |
193 | 193 | ||
194 | /* Get the real input_size for output_size bytes, guarding | 194 | /* Get the real input_size for output_size bytes, guarding |
@@ -196,7 +196,7 @@ static bool codec_pcmbuf_insert_callback( | |||
196 | inp_count = dsp_input_count(ci.dsp, out_count); | 196 | inp_count = dsp_input_count(ci.dsp, out_count); |
197 | 197 | ||
198 | if (inp_count <= 0) | 198 | if (inp_count <= 0) |
199 | return true; | 199 | return; |
200 | 200 | ||
201 | /* Input size has grown, no error, just don't write more than length */ | 201 | /* Input size has grown, no error, just don't write more than length */ |
202 | if (inp_count > count) | 202 | if (inp_count > count) |
@@ -205,14 +205,12 @@ static bool codec_pcmbuf_insert_callback( | |||
205 | out_count = dsp_process(ci.dsp, dest, src, inp_count); | 205 | out_count = dsp_process(ci.dsp, dest, src, inp_count); |
206 | 206 | ||
207 | if (out_count <= 0) | 207 | if (out_count <= 0) |
208 | return true; | 208 | return; |
209 | 209 | ||
210 | pcmbuf_write_complete(out_count); | 210 | pcmbuf_write_complete(out_count); |
211 | 211 | ||
212 | count -= inp_count; | 212 | count -= inp_count; |
213 | } | 213 | } |
214 | |||
215 | return true; | ||
216 | } /* codec_pcmbuf_insert_callback */ | 214 | } /* codec_pcmbuf_insert_callback */ |
217 | 215 | ||
218 | static void codec_set_elapsed_callback(unsigned long value) | 216 | static void codec_set_elapsed_callback(unsigned long value) |
diff --git a/apps/codecs.h b/apps/codecs.h index 39a8457666..f4e75dfdc3 100644 --- a/apps/codecs.h +++ b/apps/codecs.h | |||
@@ -121,7 +121,7 @@ struct codec_api { | |||
121 | void* (*codec_get_buffer)(size_t *size); | 121 | void* (*codec_get_buffer)(size_t *size); |
122 | /* Insert PCM data into audio buffer for playback. Playback will start | 122 | /* Insert PCM data into audio buffer for playback. Playback will start |
123 | automatically. */ | 123 | automatically. */ |
124 | bool (*pcmbuf_insert)(const void *ch1, const void *ch2, int count); | 124 | void (*pcmbuf_insert)(const void *ch1, const void *ch2, int count); |
125 | /* Set song position in WPS (value in ms). */ | 125 | /* Set song position in WPS (value in ms). */ |
126 | void (*set_elapsed)(unsigned long value); | 126 | void (*set_elapsed)(unsigned long value); |
127 | 127 | ||
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 580dc315a7..e62fc892cc 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -119,7 +119,7 @@ static struct chunkdesc *mix_chunk IDATA_ATTR; | |||
119 | static size_t pcmbuf_mix_sample IDATA_ATTR; | 119 | static size_t pcmbuf_mix_sample IDATA_ATTR; |
120 | 120 | ||
121 | static bool low_latency_mode = false; | 121 | static bool low_latency_mode = false; |
122 | static bool flush_pcmbuf; | 122 | static bool flush_pcmbuf = false; |
123 | 123 | ||
124 | #ifdef HAVE_PRIORITY_SCHEDULING | 124 | #ifdef HAVE_PRIORITY_SCHEDULING |
125 | static int codec_thread_priority = PRIORITY_PLAYBACK; | 125 | static int codec_thread_priority = PRIORITY_PLAYBACK; |
@@ -129,14 +129,14 @@ extern unsigned int codec_thread_id; | |||
129 | 129 | ||
130 | /* Helpful macros for use in conditionals this assumes some of the above | 130 | /* Helpful macros for use in conditionals this assumes some of the above |
131 | * static variable names */ | 131 | * static variable names */ |
132 | #define NEED_FLUSH(position) \ | 132 | #define COMMIT_IF_NEEDED if(pcmbuffer_fillpos > PCMBUF_TARGET_CHUNK || \ |
133 | (pcmbuffer_fillpos > PCMBUF_TARGET_CHUNK || position >= pcmbuf_size) | 133 | (pcmbuffer_pos + pcmbuffer_fillpos) >= pcmbuf_size) commit_chunk(false) |
134 | #define LOW_DATA(quarter_secs) \ | 134 | #define LOW_DATA(quarter_secs) \ |
135 | (pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs) | 135 | (pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs) |
136 | 136 | ||
137 | #ifdef HAVE_CROSSFADE | 137 | #ifdef HAVE_CROSSFADE |
138 | static void crossfade_start(void); | 138 | static void crossfade_start(void); |
139 | static void flush_crossfade(char *buf, size_t length); | 139 | static void write_to_crossfade(char *buf, size_t length); |
140 | static void pcmbuf_finish_crossfade_enable(void); | 140 | static void pcmbuf_finish_crossfade_enable(void); |
141 | #endif | 141 | #endif |
142 | 142 | ||
@@ -181,12 +181,10 @@ static bool show_desc(char *caller) | |||
181 | #endif | 181 | #endif |
182 | 182 | ||
183 | 183 | ||
184 | /* Commit PCM data */ | 184 | /** Accept new PCM data */ |
185 | 185 | ||
186 | /** | 186 | /* Commit PCM buffer samples as a new chunk for playback */ |
187 | * Commit samples waiting to the pcm buffer. | 187 | static void commit_chunk(bool flush_next_time) |
188 | */ | ||
189 | static void commit_chunk(void) | ||
190 | { | 188 | { |
191 | if (!pcmbuffer_fillpos) | 189 | if (!pcmbuffer_fillpos) |
192 | return; | 190 | return; |
@@ -219,7 +217,7 @@ static void commit_chunk(void) | |||
219 | { | 217 | { |
220 | if (flush_pcmbuf) | 218 | if (flush_pcmbuf) |
221 | { | 219 | { |
222 | /* flush! discard all data after the currently playing chunk, | 220 | /* Flush! Discard all data after the currently playing chunk, |
223 | and make the current chunk play next */ | 221 | and make the current chunk play next */ |
224 | write_end_chunk->link = read_chunk->link; | 222 | write_end_chunk->link = read_chunk->link; |
225 | read_chunk->link = pcmbuf_current; | 223 | read_chunk->link = pcmbuf_current; |
@@ -228,7 +226,6 @@ static void commit_chunk(void) | |||
228 | write_end_chunk = write_end_chunk->link; | 226 | write_end_chunk = write_end_chunk->link; |
229 | pcmbuf_unplayed_bytes -= write_end_chunk->size; | 227 | pcmbuf_unplayed_bytes -= write_end_chunk->size; |
230 | } | 228 | } |
231 | flush_pcmbuf = false; | ||
232 | } | 229 | } |
233 | /* If there is already a read buffer setup, add to it */ | 230 | /* If there is already a read buffer setup, add to it */ |
234 | else | 231 | else |
@@ -240,6 +237,11 @@ static void commit_chunk(void) | |||
240 | read_chunk = pcmbuf_current; | 237 | read_chunk = pcmbuf_current; |
241 | } | 238 | } |
242 | 239 | ||
240 | /* If flush_next_time is true, then the current chunk will be thrown out | ||
241 | * and the next chunk to be committed will be the next to be played. | ||
242 | * This is used to empty the PCM buffer for a track change. */ | ||
243 | flush_pcmbuf = flush_next_time; | ||
244 | |||
243 | /* This is now the last buffer to read */ | 245 | /* This is now the last buffer to read */ |
244 | read_end_chunk = pcmbuf_current; | 246 | read_end_chunk = pcmbuf_current; |
245 | 247 | ||
@@ -254,6 +256,7 @@ static void commit_chunk(void) | |||
254 | DISPLAY_DESC("commit_chunk"); | 256 | DISPLAY_DESC("commit_chunk"); |
255 | } | 257 | } |
256 | 258 | ||
259 | /* Set priority of the codec thread */ | ||
257 | #ifdef HAVE_PRIORITY_SCHEDULING | 260 | #ifdef HAVE_PRIORITY_SCHEDULING |
258 | static void boost_codec_thread(bool boost) | 261 | static void boost_codec_thread(bool boost) |
259 | { | 262 | { |
@@ -282,6 +285,8 @@ static void boost_codec_thread(bool boost) | |||
282 | #define boost_codec_thread(boost) do{}while(0) | 285 | #define boost_codec_thread(boost) do{}while(0) |
283 | #endif /* HAVE_PRIORITY_SCHEDULING */ | 286 | #endif /* HAVE_PRIORITY_SCHEDULING */ |
284 | 287 | ||
288 | /* Return true if the PCM buffer is able to receive new data. | ||
289 | * Also maintain buffer level above the watermark. */ | ||
285 | static bool prepare_insert(size_t length) | 290 | static bool prepare_insert(size_t length) |
286 | { | 291 | { |
287 | if (low_latency_mode) | 292 | if (low_latency_mode) |
@@ -295,7 +300,7 @@ static bool prepare_insert(size_t length) | |||
295 | if (pcmbuf_free() < length + PCMBUF_MIN_CHUNK) | 300 | if (pcmbuf_free() < length + PCMBUF_MIN_CHUNK) |
296 | return false; | 301 | return false; |
297 | 302 | ||
298 | /* boost CPU if needed to either fill to watermark or for pre-buffer */ | 303 | /* Maintain the buffer level above the watermark */ |
299 | if (pcm_is_playing()) | 304 | if (pcm_is_playing()) |
300 | { | 305 | { |
301 | /* Only codec thread initiates boost - voice boosts the cpu when playing | 306 | /* Only codec thread initiates boost - voice boosts the cpu when playing |
@@ -328,9 +333,10 @@ static bool prepare_insert(size_t length) | |||
328 | } | 333 | } |
329 | else /* pcm_is_playing */ | 334 | else /* pcm_is_playing */ |
330 | { | 335 | { |
336 | /* Boost CPU for pre-buffer */ | ||
331 | trigger_cpu_boost(); | 337 | trigger_cpu_boost(); |
332 | 338 | ||
333 | /* Pre-buffer up to watermark */ | 339 | /* If pre-buffered to the watermark, start playback */ |
334 | #if MEMORYSIZE > 2 | 340 | #if MEMORYSIZE > 2 |
335 | if (!LOW_DATA(4)) | 341 | if (!LOW_DATA(4)) |
336 | #else | 342 | #else |
@@ -346,18 +352,23 @@ static bool prepare_insert(size_t length) | |||
346 | return true; | 352 | return true; |
347 | } | 353 | } |
348 | 354 | ||
355 | /* Request space in the buffer for writing output samples */ | ||
349 | void *pcmbuf_request_buffer(int *count) | 356 | void *pcmbuf_request_buffer(int *count) |
350 | { | 357 | { |
351 | #ifdef HAVE_CROSSFADE | 358 | #ifdef HAVE_CROSSFADE |
359 | /* we're going to crossfade to a new track, which is now on its way */ | ||
352 | if (crossfade_track_change_started) | 360 | if (crossfade_track_change_started) |
353 | crossfade_start(); | 361 | crossfade_start(); |
354 | 362 | ||
355 | if (crossfade_active) { | 363 | /* crossfade has begun, put the new track samples in fadebuf */ |
364 | if (crossfade_active) | ||
365 | { | ||
356 | *count = MIN(*count, PCMBUF_MIX_CHUNK/4); | 366 | *count = MIN(*count, PCMBUF_MIX_CHUNK/4); |
357 | return fadebuf; | 367 | return fadebuf; |
358 | } | 368 | } |
359 | else | 369 | else |
360 | #endif | 370 | #endif |
371 | /* if possible, reserve room in the PCM buffer for new samples */ | ||
361 | { | 372 | { |
362 | if(prepare_insert(*count << 2)) | 373 | if(prepare_insert(*count << 2)) |
363 | { | 374 | { |
@@ -369,38 +380,34 @@ void *pcmbuf_request_buffer(int *count) | |||
369 | } | 380 | } |
370 | else | 381 | else |
371 | { | 382 | { |
372 | /* Flush and wrap the buffer */ | 383 | /* Wrap the buffer, the new samples go at the beginning */ |
373 | commit_chunk(); | 384 | commit_chunk(false); |
374 | pcmbuffer_pos = 0; | 385 | pcmbuffer_pos = 0; |
375 | return &pcmbuffer[0]; | 386 | return &pcmbuffer[0]; |
376 | } | 387 | } |
377 | } | 388 | } |
378 | } | 389 | } |
390 | /* PCM buffer not ready to receive new data yet */ | ||
379 | return NULL; | 391 | return NULL; |
380 | } | 392 | } |
381 | 393 | ||
394 | /* Handle new samples to the buffer */ | ||
382 | void pcmbuf_write_complete(int count) | 395 | void pcmbuf_write_complete(int count) |
383 | { | 396 | { |
384 | size_t length = (size_t)(unsigned int)count << 2; | 397 | size_t length = (size_t)(unsigned int)count << 2; |
385 | #ifdef HAVE_CROSSFADE | 398 | #ifdef HAVE_CROSSFADE |
386 | if (crossfade_active) | 399 | if (crossfade_active) |
387 | { | 400 | write_to_crossfade(fadebuf, length); |
388 | flush_crossfade(fadebuf, length); | ||
389 | if (!(crossfade_fade_in_rem || crossfade_chunk)) | ||
390 | crossfade_active = false; | ||
391 | } | ||
392 | else | 401 | else |
393 | #endif | 402 | #endif |
394 | { | 403 | { |
395 | pcmbuffer_fillpos += length; | 404 | pcmbuffer_fillpos += length; |
396 | 405 | COMMIT_IF_NEEDED; | |
397 | if (NEED_FLUSH(pcmbuffer_pos + pcmbuffer_fillpos)) | ||
398 | commit_chunk(); | ||
399 | } | 406 | } |
400 | } | 407 | } |
401 | 408 | ||
402 | 409 | ||
403 | /* Init */ | 410 | /** Init */ |
404 | 411 | ||
405 | static inline void init_pcmbuffers(void) | 412 | static inline void init_pcmbuffers(void) |
406 | { | 413 | { |
@@ -466,14 +473,13 @@ size_t pcmbuf_init(unsigned char *bufend) | |||
466 | } | 473 | } |
467 | 474 | ||
468 | 475 | ||
469 | /* Track change */ | 476 | /** Track change */ |
470 | 477 | ||
471 | void pcmbuf_start_track_change(bool auto_skip) | 478 | void pcmbuf_start_track_change(bool auto_skip) |
472 | { | 479 | { |
473 | bool crossfade = false; | 480 | bool crossfade = false; |
474 | #ifdef HAVE_CROSSFADE | 481 | #ifdef HAVE_CROSSFADE |
475 | /* Determine whether this track change needs to crossfade */ | 482 | /* Determine whether this track change needs to crossfade */ |
476 | |||
477 | if(crossfade_enabled && !pcmbuf_is_crossfade_active()) | 483 | if(crossfade_enabled && !pcmbuf_is_crossfade_active()) |
478 | { | 484 | { |
479 | switch(global_settings.crossfade) | 485 | switch(global_settings.crossfade) |
@@ -524,8 +530,7 @@ void pcmbuf_start_track_change(bool auto_skip) | |||
524 | /* Not enough data, or not crossfading, flush the old data instead */ | 530 | /* Not enough data, or not crossfading, flush the old data instead */ |
525 | if (LOW_DATA(2) || !crossfade || low_latency_mode) | 531 | if (LOW_DATA(2) || !crossfade || low_latency_mode) |
526 | { | 532 | { |
527 | flush_pcmbuf = true; | 533 | commit_chunk(true); |
528 | commit_chunk(); | ||
529 | return; | 534 | return; |
530 | } | 535 | } |
531 | 536 | ||
@@ -536,7 +541,7 @@ void pcmbuf_start_track_change(bool auto_skip) | |||
536 | crossfade_track_change_started = crossfade; | 541 | crossfade_track_change_started = crossfade; |
537 | #endif | 542 | #endif |
538 | } | 543 | } |
539 | else /* automatic and not crossfading, so gapless track change */ | 544 | else /* automatic and not crossfading, so do gapless track change */ |
540 | { | 545 | { |
541 | /* The codec is moving on to the next track, but the current track will | 546 | /* The codec is moving on to the next track, but the current track will |
542 | * continue to play. Set a flag to make sure the elapsed time of the | 547 | * continue to play. Set a flag to make sure the elapsed time of the |
@@ -549,9 +554,9 @@ void pcmbuf_start_track_change(bool auto_skip) | |||
549 | } | 554 | } |
550 | 555 | ||
551 | 556 | ||
552 | /* Playback */ | 557 | /** Playback */ |
553 | 558 | ||
554 | /** PCM driver callback | 559 | /* PCM driver callback |
555 | * This function has 3 major logical parts (separated by brackets both for | 560 | * This function has 3 major logical parts (separated by brackets both for |
556 | * readability and variable scoping). The first part performs the | 561 | * readability and variable scoping). The first part performs the |
557 | * operations related to finishing off the last chunk we fed to the DMA. | 562 | * operations related to finishing off the last chunk we fed to the DMA. |
@@ -598,7 +603,7 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size) | |||
598 | if (pcmbuffer_fillpos && !read_chunk) | 603 | if (pcmbuffer_fillpos && !read_chunk) |
599 | { | 604 | { |
600 | logf("pcmbuf_pcm_callback: commit last samples"); | 605 | logf("pcmbuf_pcm_callback: commit last samples"); |
601 | commit_chunk(); | 606 | commit_chunk(false); |
602 | } | 607 | } |
603 | } | 608 | } |
604 | 609 | ||
@@ -625,7 +630,7 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size) | |||
625 | DISPLAY_DESC("callback"); | 630 | DISPLAY_DESC("callback"); |
626 | } | 631 | } |
627 | 632 | ||
628 | /* Force playback. */ | 633 | /* Force playback */ |
629 | void pcmbuf_play_start(void) | 634 | void pcmbuf_play_start(void) |
630 | { | 635 | { |
631 | if (!pcm_is_playing() && pcmbuf_unplayed_bytes && read_chunk != NULL) | 636 | if (!pcm_is_playing() && pcmbuf_unplayed_bytes && read_chunk != NULL) |
@@ -658,7 +663,6 @@ void pcmbuf_play_stop(void) | |||
658 | #endif | 663 | #endif |
659 | end_of_track = false; | 664 | end_of_track = false; |
660 | track_transition = false; | 665 | track_transition = false; |
661 | flush_pcmbuf = false; | ||
662 | DISPLAY_DESC("play_stop"); | 666 | DISPLAY_DESC("play_stop"); |
663 | 667 | ||
664 | /* Can unboost the codec thread here no matter who's calling */ | 668 | /* Can unboost the codec thread here no matter who's calling */ |
@@ -675,7 +679,7 @@ void pcmbuf_pause(bool pause) | |||
675 | } | 679 | } |
676 | 680 | ||
677 | 681 | ||
678 | /* Crossfade */ | 682 | /** Crossfade */ |
679 | 683 | ||
680 | /* Clip sample to signed 16 bit range */ | 684 | /* Clip sample to signed 16 bit range */ |
681 | static inline int32_t clip_sample_16(int32_t sample) | 685 | static inline int32_t clip_sample_16(int32_t sample) |
@@ -686,9 +690,7 @@ static inline int32_t clip_sample_16(int32_t sample) | |||
686 | } | 690 | } |
687 | 691 | ||
688 | #ifdef HAVE_CROSSFADE | 692 | #ifdef HAVE_CROSSFADE |
689 | /** | 693 | /* Completely process the crossfade fade-out effect with current PCM buffer */ |
690 | * Completely process the crossfade fade out effect with current pcm buffer. | ||
691 | */ | ||
692 | static void crossfade_process_buffer(size_t fade_in_delay, | 694 | static void crossfade_process_buffer(size_t fade_in_delay, |
693 | size_t fade_out_delay, size_t fade_out_rem) | 695 | size_t fade_out_delay, size_t fade_out_rem) |
694 | { | 696 | { |
@@ -747,8 +749,8 @@ static void crossfade_process_buffer(size_t fade_in_delay, | |||
747 | logf("process done!"); | 749 | logf("process done!"); |
748 | } | 750 | } |
749 | 751 | ||
750 | /* Initializes crossfader, calculates all necessary parameters and | 752 | /* Initializes crossfader, calculates all necessary parameters and performs |
751 | * performs fade-out with the pcm buffer. */ | 753 | * fade-out with the PCM buffer. */ |
752 | static void crossfade_start(void) | 754 | static void crossfade_start(void) |
753 | { | 755 | { |
754 | size_t crossfade_rem; | 756 | size_t crossfade_rem; |
@@ -766,7 +768,7 @@ static void crossfade_start(void) | |||
766 | } | 768 | } |
767 | 769 | ||
768 | logf("crossfade_start"); | 770 | logf("crossfade_start"); |
769 | commit_chunk(); | 771 | commit_chunk(false); |
770 | crossfade_active = true; | 772 | crossfade_active = true; |
771 | 773 | ||
772 | /* Initialize the crossfade buffer size to all of the buffered data that | 774 | /* Initialize the crossfade buffer size to all of the buffered data that |
@@ -854,7 +856,8 @@ static size_t crossfade_mix(int factor, const char *buf, size_t length) | |||
854 | return 0; | 856 | return 0; |
855 | } | 857 | } |
856 | 858 | ||
857 | static void flush_crossfade(char *buf, size_t length) | 859 | /* Perform fade-in of new track */ |
860 | static void write_to_crossfade(char *buf, size_t length) | ||
858 | { | 861 | { |
859 | if (length) | 862 | if (length) |
860 | { | 863 | { |
@@ -904,17 +907,13 @@ static void flush_crossfade(char *buf, size_t length) | |||
904 | return; | 907 | return; |
905 | } | 908 | } |
906 | 909 | ||
907 | /* Flush samples to the buffer */ | 910 | /* Commit samples to the buffer */ |
908 | while (!prepare_insert(length)) | 911 | while (!prepare_insert(length)) |
909 | sleep(1); | 912 | sleep(1); |
910 | while (length > 0) | 913 | while (length > 0) |
911 | { | 914 | { |
915 | COMMIT_IF_NEEDED; | ||
912 | size_t pcmbuffer_index = pcmbuffer_pos + pcmbuffer_fillpos; | 916 | size_t pcmbuffer_index = pcmbuffer_pos + pcmbuffer_fillpos; |
913 | if (NEED_FLUSH(pcmbuffer_index)) | ||
914 | { | ||
915 | commit_chunk(); | ||
916 | pcmbuffer_index = pcmbuffer_pos + pcmbuffer_fillpos; | ||
917 | } | ||
918 | size_t copy_n = MIN(length, pcmbuf_size - pcmbuffer_index); | 917 | size_t copy_n = MIN(length, pcmbuf_size - pcmbuffer_index); |
919 | memcpy(&pcmbuffer[pcmbuffer_index], buf, copy_n); | 918 | memcpy(&pcmbuffer[pcmbuffer_index], buf, copy_n); |
920 | buf += copy_n; | 919 | buf += copy_n; |
@@ -922,6 +921,9 @@ static void flush_crossfade(char *buf, size_t length) | |||
922 | length -= copy_n; | 921 | length -= copy_n; |
923 | } | 922 | } |
924 | } | 923 | } |
924 | /* if no more fading-in to do, stop the crossfade */ | ||
925 | if (!(crossfade_fade_in_rem || crossfade_chunk)) | ||
926 | crossfade_active = false; | ||
925 | } | 927 | } |
926 | 928 | ||
927 | static void pcmbuf_finish_crossfade_enable(void) | 929 | static void pcmbuf_finish_crossfade_enable(void) |
@@ -962,7 +964,7 @@ bool pcmbuf_is_same_size(void) | |||
962 | #endif /* HAVE_CROSSFADE */ | 964 | #endif /* HAVE_CROSSFADE */ |
963 | 965 | ||
964 | 966 | ||
965 | /* Voice */ | 967 | /** Voice */ |
966 | 968 | ||
967 | /* Returns pcm buffer usage in percents (0 to 100). */ | 969 | /* Returns pcm buffer usage in percents (0 to 100). */ |
968 | static int pcmbuf_usage(void) | 970 | static int pcmbuf_usage(void) |
@@ -1058,7 +1060,7 @@ void pcmbuf_write_voice_complete(int count) | |||
1058 | } | 1060 | } |
1059 | 1061 | ||
1060 | 1062 | ||
1061 | /* Debug menu, other metrics */ | 1063 | /** Debug menu, other metrics */ |
1062 | 1064 | ||
1063 | /* Amount of bytes left in the buffer. */ | 1065 | /* Amount of bytes left in the buffer. */ |
1064 | size_t pcmbuf_free(void) | 1066 | size_t pcmbuf_free(void) |
@@ -1072,7 +1074,7 @@ size_t pcmbuf_free(void) | |||
1072 | else | 1074 | else |
1073 | return (size_t) (read - write); | 1075 | return (size_t) (read - write); |
1074 | } | 1076 | } |
1075 | return pcmbuf_size; | 1077 | return pcmbuf_size - pcmbuffer_fillpos; |
1076 | } | 1078 | } |
1077 | 1079 | ||
1078 | size_t pcmbuf_get_bufsize(void) | 1080 | size_t pcmbuf_get_bufsize(void) |
@@ -1097,7 +1099,7 @@ int pcmbuf_descs(void) | |||
1097 | } | 1099 | } |
1098 | 1100 | ||
1099 | #ifdef ROCKBOX_HAS_LOGF | 1101 | #ifdef ROCKBOX_HAS_LOGF |
1100 | unsigned char * pcmbuf_get_meminfo(size_t *length) | 1102 | unsigned char *pcmbuf_get_meminfo(size_t *length) |
1101 | { | 1103 | { |
1102 | *length = pcmbuf_bufend - pcmbuffer; | 1104 | *length = pcmbuf_bufend - pcmbuffer; |
1103 | return pcmbuffer; | 1105 | return pcmbuffer; |
@@ -1105,7 +1107,7 @@ unsigned char * pcmbuf_get_meminfo(size_t *length) | |||
1105 | #endif | 1107 | #endif |
1106 | 1108 | ||
1107 | 1109 | ||
1108 | /* Misc */ | 1110 | /** Misc */ |
1109 | 1111 | ||
1110 | bool pcmbuf_is_lowdata(void) | 1112 | bool pcmbuf_is_lowdata(void) |
1111 | { | 1113 | { |
diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index 6f758639d1..156852a7b0 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c | |||
@@ -239,14 +239,12 @@ static int process_dsp(const void *ch1, const void *ch2, int count) | |||
239 | } | 239 | } |
240 | 240 | ||
241 | /* Null output */ | 241 | /* Null output */ |
242 | static bool pcmbuf_insert_null(const void *ch1, const void *ch2, int count) | 242 | static void pcmbuf_insert_null(const void *ch1, const void *ch2, int count) |
243 | { | 243 | { |
244 | if (use_dsp) process_dsp(ch1, ch2, count); | 244 | if (use_dsp) process_dsp(ch1, ch2, count); |
245 | 245 | ||
246 | /* Prevent idle poweroff */ | 246 | /* Prevent idle poweroff */ |
247 | rb->reset_poweroff_timer(); | 247 | rb->reset_poweroff_timer(); |
248 | |||
249 | return true; | ||
250 | } | 248 | } |
251 | 249 | ||
252 | static inline int32_t clip_sample(int32_t sample) | 250 | static inline int32_t clip_sample(int32_t sample) |
@@ -259,7 +257,7 @@ static inline int32_t clip_sample(int32_t sample) | |||
259 | 257 | ||
260 | 258 | ||
261 | /* WAV output */ | 259 | /* WAV output */ |
262 | static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | 260 | static void pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) |
263 | { | 261 | { |
264 | const int16_t* data1_16; | 262 | const int16_t* data1_16; |
265 | const int16_t* data2_16; | 263 | const int16_t* data2_16; |
@@ -360,8 +358,6 @@ static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | |||
360 | wavinfo.totalsamples += count; | 358 | wavinfo.totalsamples += count; |
361 | rb->write(wavinfo.fd, wavbuffer, p - wavbuffer); | 359 | rb->write(wavinfo.fd, wavbuffer, p - wavbuffer); |
362 | } /* else */ | 360 | } /* else */ |
363 | |||
364 | return true; | ||
365 | } | 361 | } |
366 | 362 | ||
367 | /* Set song position in WPS (value in ms). */ | 363 | /* Set song position in WPS (value in ms). */ |