summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorJeffrey Goode <jeffg7@gmail.com>2009-11-09 05:45:05 +0000
committerJeffrey Goode <jeffg7@gmail.com>2009-11-09 05:45:05 +0000
commit8edac6ec827529d1117bd59ba3ca338d16243460 (patch)
tree3e69db4de6a0d69f5eecae8c794edd22a91720fd /apps
parent20db9cc39e3019343ef94527c6d98414a55efd79 (diff)
downloadrockbox-8edac6ec827529d1117bd59ba3ca338d16243460.tar.gz
rockbox-8edac6ec827529d1117bd59ba3ca338d16243460.zip
pcmbuf: refactoring, renamed confusing variables, moved some code around, but still no functional changes
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23577 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/pcmbuf.c369
1 files changed, 180 insertions, 189 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index 4a7608fcec..f1fee37452 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -34,12 +34,9 @@
34#include "cpu.h" 34#include "cpu.h"
35#endif 35#endif
36#include <string.h> 36#include <string.h>
37#include "buffer.h"
38#include "settings.h" 37#include "settings.h"
39#include "audio.h" 38#include "audio.h"
40#include "voice_thread.h"
41#include "dsp.h" 39#include "dsp.h"
42#include "thread.h"
43 40
44#define PCMBUF_TARGET_CHUNK 32768 /* This is the target fill size of chunks 41#define PCMBUF_TARGET_CHUNK 32768 /* This is the target fill size of chunks
45 on the pcm buffer */ 42 on the pcm buffer */
@@ -61,28 +58,28 @@
61 58
62/* Structure we can use to queue pcm chunks in memory to be played 59/* Structure we can use to queue pcm chunks in memory to be played
63 * by the driver code. */ 60 * by the driver code. */
64struct pcmbufdesc 61struct chunkdesc
65{ 62{
66 void *addr; 63 void *addr;
67 size_t size; 64 size_t size;
68 struct pcmbufdesc* link; 65 struct chunkdesc* link;
69 /* true if last chunk in the track */ 66 /* true if last chunk in the track */
70 bool end_of_track; 67 bool end_of_track;
71}; 68};
72 69
73#define PCMBUF_DESCS(bufsize) \ 70#define CHUNK_DESCS(bufsize) \
74 ((bufsize) / PCMBUF_MINAVG_CHUNK) 71 ((bufsize) / PCMBUF_MINAVG_CHUNK)
75#define PCMBUF_DESCS_SIZE(bufsize) \ 72#define CHUNK_DESCS_SIZE(bufsize) \
76 (PCMBUF_DESCS(bufsize)*sizeof(struct pcmbufdesc)) 73 (CHUNK_DESCS(bufsize)*sizeof(struct chunkdesc))
77 74
78/* Size of the PCM buffer. */ 75/* Size of the PCM buffer. */
79static size_t pcmbuf_size IDATA_ATTR = 0; 76static size_t pcmbuf_size IDATA_ATTR = 0;
80static char *pcmbuf_bufend IDATA_ATTR; 77static char *pcmbuf_bufend IDATA_ATTR;
81static char *audiobuffer IDATA_ATTR; 78static char *pcmbuffer IDATA_ATTR;
82/* Current audio buffer write index. */ 79/* Current PCM buffer write index. */
83static size_t audiobuffer_pos IDATA_ATTR; 80static size_t pcmbuffer_pos IDATA_ATTR;
84/* Amount audiobuffer_pos will be increased.*/ 81/* Amount pcmbuffer_pos will be increased.*/
85static size_t audiobuffer_fillpos IDATA_ATTR; 82static size_t pcmbuffer_fillpos IDATA_ATTR;
86static char *fadebuf IDATA_ATTR; 83static char *fadebuf IDATA_ATTR;
87static char *voicebuf IDATA_ATTR; 84static char *voicebuf IDATA_ATTR;
88 85
@@ -91,13 +88,13 @@ bool track_transition IDATA_ATTR;
91 88
92/* Crossfade related state */ 89/* Crossfade related state */
93static bool crossfade_enabled; 90static bool crossfade_enabled;
94static bool crossfade_enabled_pending; 91static bool crossfade_enable_request;
95static bool crossfade_mixmode; 92static bool crossfade_mixmode;
96static bool crossfade_active IDATA_ATTR; 93static bool crossfade_active IDATA_ATTR;
97static bool crossfade_init IDATA_ATTR; 94static bool crossfade_init IDATA_ATTR;
98 95
99/* Track the current location for processing crossfade */ 96/* Track the current location for processing crossfade */
100static struct pcmbufdesc *crossfade_chunk IDATA_ATTR; 97static struct chunkdesc *crossfade_chunk IDATA_ATTR;
101#ifdef HAVE_CROSSFADE 98#ifdef HAVE_CROSSFADE
102static size_t crossfade_sample IDATA_ATTR; 99static size_t crossfade_sample IDATA_ATTR;
103 100
@@ -106,16 +103,16 @@ static size_t crossfade_fade_in_total IDATA_ATTR;
106static size_t crossfade_fade_in_rem IDATA_ATTR; 103static size_t crossfade_fade_in_rem IDATA_ATTR;
107#endif 104#endif
108 105
109static struct pcmbufdesc *pcmbuf_read IDATA_ATTR; 106static struct chunkdesc *read_chunk IDATA_ATTR;
110static struct pcmbufdesc *pcmbuf_read_end IDATA_ATTR; 107static struct chunkdesc *read_end_chunk IDATA_ATTR;
111static struct pcmbufdesc *pcmbuf_write IDATA_ATTR; 108static struct chunkdesc *write_chunk IDATA_ATTR;
112static struct pcmbufdesc *pcmbuf_write_end IDATA_ATTR; 109static struct chunkdesc *write_end_chunk IDATA_ATTR;
113static size_t last_chunksize IDATA_ATTR; 110static size_t last_chunksize IDATA_ATTR;
114 111
115static size_t pcmbuf_unplayed_bytes IDATA_ATTR; 112static size_t pcmbuf_unplayed_bytes IDATA_ATTR;
116static size_t pcmbuf_watermark IDATA_ATTR; 113static size_t pcmbuf_watermark IDATA_ATTR;
117 114
118static struct pcmbufdesc *pcmbuf_mix_chunk IDATA_ATTR; 115static struct chunkdesc *mix_chunk IDATA_ATTR;
119static size_t pcmbuf_mix_sample IDATA_ATTR; 116static size_t pcmbuf_mix_sample IDATA_ATTR;
120 117
121static bool low_latency_mode = false; 118static bool low_latency_mode = false;
@@ -130,7 +127,7 @@ extern unsigned int codec_thread_id;
130/* Helpful macros for use in conditionals this assumes some of the above 127/* Helpful macros for use in conditionals this assumes some of the above
131 * static variable names */ 128 * static variable names */
132#define NEED_FLUSH(position) \ 129#define NEED_FLUSH(position) \
133 (audiobuffer_fillpos > PCMBUF_TARGET_CHUNK || position >= pcmbuf_size) 130 (pcmbuffer_fillpos > PCMBUF_TARGET_CHUNK || position >= pcmbuf_size)
134#define LOW_DATA(quarter_secs) \ 131#define LOW_DATA(quarter_secs) \
135 (pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs) 132 (pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs)
136 133
@@ -146,14 +143,14 @@ static bool pcmbuf_is_crossfade_enabled(void);
146 143
147/**************************************/ 144/**************************************/
148 145
149/* define this to show detailed pcmbufdesc usage information on the sim console */ 146/* define this to show detailed chunkdesc usage information on the sim console */
150/*#define DESC_DEBUG*/ 147/*#define DESC_DEBUG*/
151 148
152#ifndef SIMULATOR 149#ifndef SIMULATOR
153#undef DESC_DEBUG 150#undef DESC_DEBUG
154#endif 151#endif
155#ifdef DESC_DEBUG 152#ifdef DESC_DEBUG
156static struct pcmbufdesc *first_desc; 153static struct chunkdesc *first_desc;
157static bool show_desc_in_use = false; 154static bool show_desc_in_use = false;
158#define DISPLAY_DESC(caller) while(!show_desc(caller)) 155#define DISPLAY_DESC(caller) while(!show_desc(caller))
159#define DESC_IDX(desc) (desc ? desc - first_desc : -1) 156#define DESC_IDX(desc) (desc ? desc - first_desc : -1)
@@ -170,11 +167,11 @@ static bool show_desc(char *caller)
170 if (show_desc_in_use) return false; 167 if (show_desc_in_use) return false;
171 show_desc_in_use = true; 168 show_desc_in_use = true;
172 DEBUGF("%-14s\t", caller); 169 DEBUGF("%-14s\t", caller);
173 DESC_SHOW("r", pcmbuf_read); 170 DESC_SHOW("r", read_chunk);
174 DESC_SHOW("re", pcmbuf_read_end); 171 DESC_SHOW("re", read_end_chunk);
175 DEBUGF(" "); 172 DEBUGF(" ");
176 DESC_SHOW("w", pcmbuf_write); 173 DESC_SHOW("w", write_chunk);
177 DESC_SHOW("we", pcmbuf_write_end); 174 DESC_SHOW("we", write_end_chunk);
178 DEBUGF("\n"); 175 DEBUGF("\n");
179 show_desc_in_use = false; 176 show_desc_in_use = false;
180 return true; 177 return true;
@@ -186,109 +183,50 @@ static bool show_desc(char *caller)
186 183
187/* Commit PCM data */ 184/* Commit PCM data */
188 185
189#ifdef HAVE_PRIORITY_SCHEDULING
190static void boost_codec_thread(bool boost)
191{
192 /* Keep voice and codec threads at the same priority or else voice
193 * will starve if the codec thread's priority is boosted. */
194 if (boost)
195 {
196 int priority = (PRIORITY_PLAYBACK - PRIORITY_PLAYBACK_MAX)*pcmbuf_unplayed_bytes
197 / (2*NATIVE_FREQUENCY) + PRIORITY_PLAYBACK_MAX;
198
199 if (priority != codec_thread_priority)
200 {
201 codec_thread_priority = priority;
202 thread_set_priority(codec_thread_id, priority);
203 voice_thread_set_priority(priority);
204 }
205 }
206 else if (codec_thread_priority != PRIORITY_PLAYBACK)
207 {
208 thread_set_priority(codec_thread_id, PRIORITY_PLAYBACK);
209 voice_thread_set_priority(PRIORITY_PLAYBACK);
210 codec_thread_priority = PRIORITY_PLAYBACK;
211 }
212}
213#endif /* HAVE_PRIORITY_SCHEDULING */
214
215static void pcmbuf_under_watermark(bool under)
216{
217 /* Only codec thread initiates boost - voice boosts the cpu when playing
218 a clip */
219#ifndef SIMULATOR
220 if (thread_get_current() == codec_thread_id)
221#endif /* SIMULATOR */
222 {
223 if (under)
224 {
225 /* Fill audio buffer by boosting cpu */
226 trigger_cpu_boost();
227#ifdef HAVE_PRIORITY_SCHEDULING
228 /* If buffer is critically low, override UI priority, else
229 set back to the original priority. */
230 boost_codec_thread(LOW_DATA(2) && pcm_is_playing());
231#endif
232 }
233 else
234 {
235#ifdef HAVE_PRIORITY_SCHEDULING
236 boost_codec_thread(false);
237#endif
238 }
239 }
240
241 /* Disable crossfade if < .5s of audio */
242 if (LOW_DATA(2))
243 {
244 crossfade_active = false;
245 }
246}
247
248/* This is really just part of pcmbuf_flush_fillpos, but is easier to keep 186/* This is really just part of pcmbuf_flush_fillpos, but is easier to keep
249 * in a separate function for the moment */ 187 * in a separate function for the moment */
250static inline void pcmbuf_add_chunk(void) 188static inline void pcmbuf_add_chunk(void)
251{ 189{
252 register size_t size = audiobuffer_fillpos; 190 register size_t size = pcmbuffer_fillpos;
253 /* Grab the next description to write, and change the write pointer */ 191 /* Grab the next description to write, and change the write pointer */
254 register struct pcmbufdesc *pcmbuf_current = pcmbuf_write; 192 register struct chunkdesc *pcmbuf_current = write_chunk;
255 pcmbuf_write = pcmbuf_current->link; 193 write_chunk = pcmbuf_current->link;
256 /* Fill in the values in the new buffer chunk */ 194 /* Fill in the values in the new buffer chunk */
257 pcmbuf_current->addr = &audiobuffer[audiobuffer_pos]; 195 pcmbuf_current->addr = &pcmbuffer[pcmbuffer_pos];
258 pcmbuf_current->size = size; 196 pcmbuf_current->size = size;
259 pcmbuf_current->end_of_track = end_of_track; 197 pcmbuf_current->end_of_track = end_of_track;
260 pcmbuf_current->link = NULL; 198 pcmbuf_current->link = NULL;
261 end_of_track = false; /* This is single use only */ 199 end_of_track = false; /* This is single use only */
262 if (pcmbuf_read != NULL) { 200 if (read_chunk != NULL) {
263 if (pcmbuf_flush) 201 if (pcmbuf_flush)
264 { 202 {
265 pcmbuf_write_end->link = pcmbuf_read->link; 203 write_end_chunk->link = read_chunk->link;
266 pcmbuf_read->link = pcmbuf_current; 204 read_chunk->link = pcmbuf_current;
267 while (pcmbuf_write_end->link) 205 while (write_end_chunk->link)
268 { 206 {
269 pcmbuf_write_end = pcmbuf_write_end->link; 207 write_end_chunk = write_end_chunk->link;
270 pcmbuf_unplayed_bytes -= pcmbuf_write_end->size; 208 pcmbuf_unplayed_bytes -= write_end_chunk->size;
271 } 209 }
272 pcmbuf_flush = false; 210 pcmbuf_flush = false;
273 } 211 }
274 /* If there is already a read buffer setup, add to it */ 212 /* If there is already a read buffer setup, add to it */
275 else 213 else
276 pcmbuf_read_end->link = pcmbuf_current; 214 read_end_chunk->link = pcmbuf_current;
277 } else { 215 } else {
278 /* Otherwise create the buffer */ 216 /* Otherwise create the buffer */
279 pcmbuf_read = pcmbuf_current; 217 read_chunk = pcmbuf_current;
280 } 218 }
281 /* This is now the last buffer to read */ 219 /* This is now the last buffer to read */
282 pcmbuf_read_end = pcmbuf_current; 220 read_end_chunk = pcmbuf_current;
283 221
284 /* Update bytes counters */ 222 /* Update bytes counters */
285 pcmbuf_unplayed_bytes += size; 223 pcmbuf_unplayed_bytes += size;
286 224
287 audiobuffer_pos += size; 225 pcmbuffer_pos += size;
288 if (audiobuffer_pos >= pcmbuf_size) 226 if (pcmbuffer_pos >= pcmbuf_size)
289 audiobuffer_pos -= pcmbuf_size; 227 pcmbuffer_pos -= pcmbuf_size;
290 228
291 audiobuffer_fillpos = 0; 229 pcmbuffer_fillpos = 0;
292 DISPLAY_DESC("add_chunk"); 230 DISPLAY_DESC("add_chunk");
293} 231}
294 232
@@ -297,9 +235,9 @@ static inline void pcmbuf_add_chunk(void)
297 */ 235 */
298static bool pcmbuf_flush_fillpos(void) 236static bool pcmbuf_flush_fillpos(void)
299{ 237{
300 if (audiobuffer_fillpos) { 238 if (pcmbuffer_fillpos) {
301 /* Never use the last buffer descriptor */ 239 /* Never use the last buffer descriptor */
302 while (pcmbuf_write == pcmbuf_write_end) { 240 while (write_chunk == write_end_chunk) {
303 /* If this happens, something is being stupid */ 241 /* If this happens, something is being stupid */
304 if (!pcm_is_playing()) { 242 if (!pcm_is_playing()) {
305 logf("pcmbuf_flush_fillpos error"); 243 logf("pcmbuf_flush_fillpos error");
@@ -314,6 +252,34 @@ static bool pcmbuf_flush_fillpos(void)
314 return false; 252 return false;
315} 253}
316 254
255#ifdef HAVE_PRIORITY_SCHEDULING
256static void boost_codec_thread(bool boost)
257{
258 /* Keep voice and codec threads at the same priority or else voice
259 * will starve if the codec thread's priority is boosted. */
260 if (boost)
261 {
262 int priority = (PRIORITY_PLAYBACK - PRIORITY_PLAYBACK_MAX)*pcmbuf_unplayed_bytes
263 / (2*NATIVE_FREQUENCY) + PRIORITY_PLAYBACK_MAX;
264
265 if (priority != codec_thread_priority)
266 {
267 codec_thread_priority = priority;
268 thread_set_priority(codec_thread_id, priority);
269 voice_thread_set_priority(priority);
270 }
271 }
272 else if (codec_thread_priority != PRIORITY_PLAYBACK)
273 {
274 thread_set_priority(codec_thread_id, PRIORITY_PLAYBACK);
275 voice_thread_set_priority(PRIORITY_PLAYBACK);
276 codec_thread_priority = PRIORITY_PLAYBACK;
277 }
278}
279#else
280#define boost_codec_thread(boost) do{}while(0)
281#endif /* HAVE_PRIORITY_SCHEDULING */
282
317static bool prepare_insert(size_t length) 283static bool prepare_insert(size_t length)
318{ 284{
319 if (low_latency_mode) 285 if (low_latency_mode)
@@ -327,7 +293,36 @@ static bool prepare_insert(size_t length)
327 if (pcmbuf_free() < length + PCMBUF_MIN_CHUNK) 293 if (pcmbuf_free() < length + PCMBUF_MIN_CHUNK)
328 return false; 294 return false;
329 295
330 if (!pcm_is_playing()) 296 /* boost CPU if needed to either fill to watermark or for pre-buffer */
297 if (pcm_is_playing())
298 {
299 /* Only codec thread initiates boost - voice boosts the cpu when playing
300 a clip */
301#ifndef SIMULATOR
302 if (thread_get_current() == codec_thread_id)
303#endif /* SIMULATOR */
304 {
305 if (pcmbuf_unplayed_bytes <= pcmbuf_watermark)
306 {
307 /* Fill PCM buffer by boosting cpu */
308 trigger_cpu_boost();
309 /* If buffer is critically low, override UI priority, else
310 set back to the original priority. */
311 boost_codec_thread(LOW_DATA(2));
312 }
313 else
314 {
315 boost_codec_thread(false);
316 }
317 }
318
319 /* Disable crossfade if < .5s of audio */
320 if (LOW_DATA(2))
321 {
322 crossfade_active = false;
323 }
324 }
325 else /* pcm_is_playing */
331 { 326 {
332 trigger_cpu_boost(); 327 trigger_cpu_boost();
333 328
@@ -343,8 +338,6 @@ static bool prepare_insert(size_t length)
343 pcmbuf_play_start(); 338 pcmbuf_play_start();
344 } 339 }
345 } 340 }
346 else
347 pcmbuf_under_watermark(pcmbuf_unplayed_bytes <= pcmbuf_watermark);
348 341
349 return true; 342 return true;
350} 343}
@@ -364,18 +357,18 @@ void *pcmbuf_request_buffer(int *count)
364 { 357 {
365 if(prepare_insert(*count << 2)) 358 if(prepare_insert(*count << 2))
366 { 359 {
367 size_t audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; 360 size_t pcmbuffer_index = pcmbuffer_pos + pcmbuffer_fillpos;
368 if (pcmbuf_size - audiobuffer_index >= PCMBUF_MIN_CHUNK) 361 if (pcmbuf_size - pcmbuffer_index >= PCMBUF_MIN_CHUNK)
369 { 362 {
370 /* Usual case, there's space here */ 363 /* Usual case, there's space here */
371 return &audiobuffer[audiobuffer_index]; 364 return &pcmbuffer[pcmbuffer_index];
372 } 365 }
373 else 366 else
374 { 367 {
375 /* Flush and wrap the buffer */ 368 /* Flush and wrap the buffer */
376 pcmbuf_flush_fillpos(); 369 pcmbuf_flush_fillpos();
377 audiobuffer_pos = 0; 370 pcmbuffer_pos = 0;
378 return &audiobuffer[0]; 371 return &pcmbuffer[0];
379 } 372 }
380 } 373 }
381 else 374 else
@@ -398,9 +391,9 @@ void pcmbuf_write_complete(int count)
398 else 391 else
399#endif 392#endif
400 { 393 {
401 audiobuffer_fillpos += length; 394 pcmbuffer_fillpos += length;
402 395
403 if (NEED_FLUSH(audiobuffer_pos + audiobuffer_fillpos)) 396 if (NEED_FLUSH(pcmbuffer_pos + pcmbuffer_fillpos))
404 pcmbuf_flush_fillpos(); 397 pcmbuf_flush_fillpos();
405 } 398 }
406} 399}
@@ -411,14 +404,14 @@ void pcmbuf_write_complete(int count)
411static void pcmbuf_init_pcmbuffers(void) 404static void pcmbuf_init_pcmbuffers(void)
412{ 405{
413#ifdef DESC_DEBUG 406#ifdef DESC_DEBUG
414 first_desc = pcmbuf_write; 407 first_desc = write_chunk;
415#endif 408#endif
416 struct pcmbufdesc *next = pcmbuf_write; 409 struct chunkdesc *next = write_chunk;
417 next++; 410 next++;
418 pcmbuf_write_end = pcmbuf_write; 411 write_end_chunk = write_chunk;
419 while ((void *)next < (void *)pcmbuf_bufend) { 412 while ((void *)next < (void *)pcmbuf_bufend) {
420 pcmbuf_write_end->link=next; 413 write_end_chunk->link=next;
421 pcmbuf_write_end=next; 414 write_end_chunk=next;
422 next++; 415 next++;
423 } 416 }
424 DISPLAY_DESC("init"); 417 DISPLAY_DESC("init");
@@ -428,7 +421,7 @@ static size_t pcmbuf_get_next_required_pcmbuf_size(void)
428{ 421{
429 size_t seconds = 1; 422 size_t seconds = 1;
430 423
431 if (crossfade_enabled_pending) 424 if (crossfade_enable_request)
432 seconds += global_settings.crossfade_fade_out_delay 425 seconds += global_settings.crossfade_fade_out_delay
433 + global_settings.crossfade_fade_out_duration; 426 + global_settings.crossfade_fade_out_duration;
434 427
@@ -440,10 +433,10 @@ static size_t pcmbuf_get_next_required_pcmbuf_size(void)
440 return seconds * (NATIVE_FREQUENCY*4); /* 2 channels + 2 bytes/sample */ 433 return seconds * (NATIVE_FREQUENCY*4); /* 2 channels + 2 bytes/sample */
441} 434}
442 435
443static char *pcmbuf_calc_audiobuffer_ptr(size_t bufsize) 436static char *pcmbuf_calc_pcmbuffer_ptr(size_t bufsize)
444{ 437{
445 return pcmbuf_bufend - (bufsize + PCMBUF_MIX_CHUNK * 2 + 438 return pcmbuf_bufend - (bufsize + PCMBUF_MIX_CHUNK * 2 +
446 PCMBUF_DESCS_SIZE(bufsize)); 439 CHUNK_DESCS_SIZE(bufsize));
447} 440}
448 441
449/* Initialize the pcmbuffer the structure looks like this: 442/* Initialize the pcmbuffer the structure looks like this:
@@ -452,10 +445,10 @@ size_t pcmbuf_init(unsigned char *bufend)
452{ 445{
453 pcmbuf_bufend = bufend; 446 pcmbuf_bufend = bufend;
454 pcmbuf_size = pcmbuf_get_next_required_pcmbuf_size(); 447 pcmbuf_size = pcmbuf_get_next_required_pcmbuf_size();
455 audiobuffer = pcmbuf_calc_audiobuffer_ptr(pcmbuf_size); 448 pcmbuffer = pcmbuf_calc_pcmbuffer_ptr(pcmbuf_size);
456 fadebuf = &audiobuffer[pcmbuf_size]; 449 fadebuf = &pcmbuffer[pcmbuf_size];
457 voicebuf = &fadebuf[PCMBUF_MIX_CHUNK]; 450 voicebuf = &fadebuf[PCMBUF_MIX_CHUNK];
458 pcmbuf_write = (struct pcmbufdesc *)&voicebuf[PCMBUF_MIX_CHUNK]; 451 write_chunk = (struct chunkdesc *)&voicebuf[PCMBUF_MIX_CHUNK];
459 452
460 pcmbuf_init_pcmbuffers(); 453 pcmbuf_init_pcmbuffers();
461 454
@@ -467,7 +460,7 @@ size_t pcmbuf_init(unsigned char *bufend)
467 460
468 pcmbuf_play_stop(); 461 pcmbuf_play_stop();
469 462
470 return pcmbuf_bufend - audiobuffer; 463 return pcmbuf_bufend - pcmbuffer;
471} 464}
472 465
473 466
@@ -485,9 +478,9 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size) ICODE_ATTR;
485static void pcmbuf_pcm_callback(unsigned char** start, size_t* size) 478static void pcmbuf_pcm_callback(unsigned char** start, size_t* size)
486{ 479{
487 { 480 {
488 struct pcmbufdesc *pcmbuf_current = pcmbuf_read; 481 struct chunkdesc *pcmbuf_current = read_chunk;
489 /* Take the finished buffer out of circulation */ 482 /* Take the finished buffer out of circulation */
490 pcmbuf_read = pcmbuf_current->link; 483 read_chunk = pcmbuf_current->link;
491 484
492 /* if during a track transition, update the elapsed time */ 485 /* if during a track transition, update the elapsed time */
493 if (track_transition) 486 if (track_transition)
@@ -498,20 +491,20 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size)
498 pcmbuf_finish_track_change(); 491 pcmbuf_finish_track_change();
499 492
500 /* Put the finished buffer back into circulation */ 493 /* Put the finished buffer back into circulation */
501 pcmbuf_write_end->link = pcmbuf_current; 494 write_end_chunk->link = pcmbuf_current;
502 pcmbuf_write_end = pcmbuf_current; 495 write_end_chunk = pcmbuf_current;
503 496
504 /* If we've read over the mix chunk while it's still mixing there */ 497 /* If we've read over the mix chunk while it's still mixing there */
505 if (pcmbuf_current == pcmbuf_mix_chunk) 498 if (pcmbuf_current == mix_chunk)
506 pcmbuf_mix_chunk = NULL; 499 mix_chunk = NULL;
507 /* If we've read over the crossfade chunk while it's still fading */ 500 /* If we've read over the crossfade chunk while it's still fading */
508 if (pcmbuf_current == crossfade_chunk) 501 if (pcmbuf_current == crossfade_chunk)
509 crossfade_chunk = pcmbuf_read; 502 crossfade_chunk = read_chunk;
510 } 503 }
511 504
512 { 505 {
513 /* Commit last samples at end of playlist */ 506 /* Commit last samples at end of playlist */
514 if (audiobuffer_fillpos && !pcmbuf_read) 507 if (pcmbuffer_fillpos && !read_chunk)
515 { 508 {
516 logf("pcmbuf_pcm_callback: commit last samples"); 509 logf("pcmbuf_pcm_callback: commit last samples");
517 pcmbuf_flush_fillpos(); 510 pcmbuf_flush_fillpos();
@@ -520,7 +513,7 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size)
520 513
521 { 514 {
522 /* Send the new buffer to the pcm */ 515 /* Send the new buffer to the pcm */
523 struct pcmbufdesc *pcmbuf_new = pcmbuf_read; 516 struct chunkdesc *pcmbuf_new = read_chunk;
524 size_t *realsize = size; 517 size_t *realsize = size;
525 unsigned char** realstart = start; 518 unsigned char** realstart = start;
526 if(pcmbuf_new) 519 if(pcmbuf_new)
@@ -548,12 +541,12 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size)
548/* Force playback. */ 541/* Force playback. */
549void pcmbuf_play_start(void) 542void pcmbuf_play_start(void)
550{ 543{
551 if (!pcm_is_playing() && pcmbuf_unplayed_bytes && pcmbuf_read != NULL) 544 if (!pcm_is_playing() && pcmbuf_unplayed_bytes && read_chunk != NULL)
552 { 545 {
553 last_chunksize = pcmbuf_read->size; 546 last_chunksize = read_chunk->size;
554 pcmbuf_unplayed_bytes -= last_chunksize; 547 pcmbuf_unplayed_bytes -= last_chunksize;
555 pcm_play_data(pcmbuf_pcm_callback, 548 pcm_play_data(pcmbuf_pcm_callback,
556 (unsigned char *)pcmbuf_read->addr, last_chunksize); 549 (unsigned char *)read_chunk->addr, last_chunksize);
557 } 550 }
558} 551}
559 552
@@ -562,23 +555,21 @@ void pcmbuf_play_stop(void)
562 pcm_play_stop(); 555 pcm_play_stop();
563 556
564 pcmbuf_unplayed_bytes = 0; 557 pcmbuf_unplayed_bytes = 0;
565 pcmbuf_mix_chunk = NULL; 558 mix_chunk = NULL;
566 if (pcmbuf_read) { 559 if (read_chunk) {
567 pcmbuf_write_end->link = pcmbuf_read; 560 write_end_chunk->link = read_chunk;
568 pcmbuf_write_end = pcmbuf_read_end; 561 write_end_chunk = read_end_chunk;
569 pcmbuf_read = pcmbuf_read_end = NULL; 562 read_chunk = read_end_chunk = NULL;
570 } 563 }
571 audiobuffer_pos = 0; 564 pcmbuffer_pos = 0;
572 audiobuffer_fillpos = 0; 565 pcmbuffer_fillpos = 0;
573 crossfade_init = false; 566 crossfade_init = false;
574 crossfade_active = false; 567 crossfade_active = false;
575 pcmbuf_flush = false; 568 pcmbuf_flush = false;
576 DISPLAY_DESC("play_stop"); 569 DISPLAY_DESC("play_stop");
577 570
578#ifdef HAVE_PRIORITY_SCHEDULING
579 /* Can unboost the codec thread here no matter who's calling */ 571 /* Can unboost the codec thread here no matter who's calling */
580 boost_codec_thread(false); 572 boost_codec_thread(false);
581#endif
582} 573}
583 574
584void pcmbuf_pause(bool pause) 575void pcmbuf_pause(bool pause)
@@ -681,7 +672,7 @@ static void crossfade_process_buffer(size_t fade_in_delay,
681 /* Fade out the specified amount of the already processed audio */ 672 /* Fade out the specified amount of the already processed audio */
682 size_t total_fade_out = fade_out_rem; 673 size_t total_fade_out = fade_out_rem;
683 size_t fade_out_sample; 674 size_t fade_out_sample;
684 struct pcmbufdesc *fade_out_chunk = crossfade_chunk; 675 struct chunkdesc *fade_out_chunk = crossfade_chunk;
685 676
686 /* Find the right chunk to start fading out */ 677 /* Find the right chunk to start fading out */
687 fade_out_delay += crossfade_sample * 2; 678 fade_out_delay += crossfade_sample * 2;
@@ -756,7 +747,7 @@ static void crossfade_start(void)
756 /* Initialize the crossfade buffer size to all of the buffered data that 747 /* Initialize the crossfade buffer size to all of the buffered data that
757 * has not yet been sent to the DMA */ 748 * has not yet been sent to the DMA */
758 crossfade_rem = pcmbuf_unplayed_bytes; 749 crossfade_rem = pcmbuf_unplayed_bytes;
759 crossfade_chunk = pcmbuf_read->link; 750 crossfade_chunk = read_chunk->link;
760 crossfade_sample = 0; 751 crossfade_sample = 0;
761 752
762 /* Get fade out delay from settings. */ 753 /* Get fade out delay from settings. */
@@ -893,16 +884,16 @@ static void flush_crossfade(char *buf, size_t length)
893 sleep(1); 884 sleep(1);
894 while (length > 0) 885 while (length > 0)
895 { 886 {
896 size_t audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; 887 size_t pcmbuffer_index = pcmbuffer_pos + pcmbuffer_fillpos;
897 if (NEED_FLUSH(audiobuffer_index)) 888 if (NEED_FLUSH(pcmbuffer_index))
898 { 889 {
899 pcmbuf_flush_fillpos(); 890 pcmbuf_flush_fillpos();
900 audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; 891 pcmbuffer_index = pcmbuffer_pos + pcmbuffer_fillpos;
901 } 892 }
902 size_t copy_n = MIN(length, pcmbuf_size - audiobuffer_index); 893 size_t copy_n = MIN(length, pcmbuf_size - pcmbuffer_index);
903 memcpy(&audiobuffer[audiobuffer_index], buf, copy_n); 894 memcpy(&pcmbuffer[pcmbuffer_index], buf, copy_n);
904 buf += copy_n; 895 buf += copy_n;
905 audiobuffer_fillpos += copy_n; 896 pcmbuffer_fillpos += copy_n;
906 length -= copy_n; 897 length -= copy_n;
907 } 898 }
908 } 899 }
@@ -943,7 +934,7 @@ static bool pcmbuf_crossfade_init(bool manual_skip)
943static void pcmbuf_finish_crossfade_enable(void) 934static void pcmbuf_finish_crossfade_enable(void)
944{ 935{
945 /* Copy the pending setting over now */ 936 /* Copy the pending setting over now */
946 crossfade_enabled = crossfade_enabled_pending; 937 crossfade_enabled = crossfade_enable_request;
947 938
948 pcmbuf_watermark = (crossfade_enabled && pcmbuf_size) ? 939 pcmbuf_watermark = (crossfade_enabled && pcmbuf_size) ?
949 /* If crossfading, try to keep the buffer full other than 1 second */ 940 /* If crossfading, try to keep the buffer full other than 1 second */
@@ -968,19 +959,19 @@ bool pcmbuf_is_crossfade_active(void)
968void pcmbuf_request_crossfade_enable(bool on_off) 959void pcmbuf_request_crossfade_enable(bool on_off)
969{ 960{
970 /* Next setting to be used, not applied now */ 961 /* Next setting to be used, not applied now */
971 crossfade_enabled_pending = on_off; 962 crossfade_enable_request = on_off;
972} 963}
973 964
974bool pcmbuf_is_same_size(void) 965bool pcmbuf_is_same_size(void)
975{ 966{
976 bool same_size; 967 bool same_size;
977 968
978 if (audiobuffer == NULL) 969 if (pcmbuffer == NULL)
979 same_size = true; /* Not set up yet even once so always */ 970 same_size = true; /* Not set up yet even once so always */
980 else 971 else
981 { 972 {
982 size_t bufsize = pcmbuf_get_next_required_pcmbuf_size(); 973 size_t bufsize = pcmbuf_get_next_required_pcmbuf_size();
983 same_size = pcmbuf_calc_audiobuffer_ptr(bufsize) == audiobuffer; 974 same_size = pcmbuf_calc_pcmbuffer_ptr(bufsize) == pcmbuffer;
984 } 975 }
985 976
986 if (same_size) 977 if (same_size)
@@ -1000,11 +991,11 @@ static int pcmbuf_usage(void)
1000 991
1001static int pcmbuf_mix_free(void) 992static int pcmbuf_mix_free(void)
1002{ 993{
1003 if (pcmbuf_mix_chunk) 994 if (mix_chunk)
1004 { 995 {
1005 size_t my_mix_end = 996 size_t my_mix_end =
1006 (size_t)&((int16_t *)pcmbuf_mix_chunk->addr)[pcmbuf_mix_sample]; 997 (size_t)&((int16_t *)mix_chunk->addr)[pcmbuf_mix_sample];
1007 size_t my_write_pos = (size_t)&audiobuffer[audiobuffer_pos]; 998 size_t my_write_pos = (size_t)&pcmbuffer[pcmbuffer_pos];
1008 if (my_write_pos < my_mix_end) 999 if (my_write_pos < my_mix_end)
1009 my_write_pos += pcmbuf_size; 1000 my_write_pos += pcmbuf_size;
1010 return (my_write_pos - my_mix_end) * 100 / pcmbuf_unplayed_bytes; 1001 return (my_write_pos - my_mix_end) * 100 / pcmbuf_unplayed_bytes;
@@ -1018,12 +1009,12 @@ void *pcmbuf_request_voice_buffer(int *count)
1018 completion) */ 1009 completion) */
1019 if (audio_status() & AUDIO_STATUS_PLAY) 1010 if (audio_status() & AUDIO_STATUS_PLAY)
1020 { 1011 {
1021 if (pcmbuf_read == NULL) 1012 if (read_chunk == NULL)
1022 { 1013 {
1023 return NULL; 1014 return NULL;
1024 } 1015 }
1025 else if (pcmbuf_usage() >= 10 && pcmbuf_mix_free() >= 30 && 1016 else if (pcmbuf_usage() >= 10 && pcmbuf_mix_free() >= 30 &&
1026 (pcmbuf_mix_chunk || pcmbuf_read->link)) 1017 (mix_chunk || read_chunk->link))
1027 { 1018 {
1028 *count = MIN(*count, PCMBUF_MIX_CHUNK/4); 1019 *count = MIN(*count, PCMBUF_MIX_CHUNK/4);
1029 return voicebuf; 1020 return voicebuf;
@@ -1052,18 +1043,18 @@ void pcmbuf_write_voice_complete(int count)
1052 int16_t *obuf; 1043 int16_t *obuf;
1053 size_t chunk_samples; 1044 size_t chunk_samples;
1054 1045
1055 if (pcmbuf_mix_chunk == NULL && pcmbuf_read != NULL) 1046 if (mix_chunk == NULL && read_chunk != NULL)
1056 { 1047 {
1057 pcmbuf_mix_chunk = pcmbuf_read->link; 1048 mix_chunk = read_chunk->link;
1058 /* Start 1/8s into the next chunk */ 1049 /* Start 1/8s into the next chunk */
1059 pcmbuf_mix_sample = NATIVE_FREQUENCY * 4 / 16; 1050 pcmbuf_mix_sample = NATIVE_FREQUENCY * 4 / 16;
1060 } 1051 }
1061 1052
1062 if (!pcmbuf_mix_chunk) 1053 if (!mix_chunk)
1063 return; 1054 return;
1064 1055
1065 obuf = (int16_t *)pcmbuf_mix_chunk->addr; 1056 obuf = (int16_t *)mix_chunk->addr;
1066 chunk_samples = pcmbuf_mix_chunk->size / sizeof (int16_t); 1057 chunk_samples = mix_chunk->size / sizeof (int16_t);
1067 1058
1068 count <<= 1; 1059 count <<= 1;
1069 1060
@@ -1073,12 +1064,12 @@ void pcmbuf_write_voice_complete(int count)
1073 1064
1074 if (pcmbuf_mix_sample >= chunk_samples) 1065 if (pcmbuf_mix_sample >= chunk_samples)
1075 { 1066 {
1076 pcmbuf_mix_chunk = pcmbuf_mix_chunk->link; 1067 mix_chunk = mix_chunk->link;
1077 if (!pcmbuf_mix_chunk) 1068 if (!mix_chunk)
1078 return; 1069 return;
1079 pcmbuf_mix_sample = 0; 1070 pcmbuf_mix_sample = 0;
1080 obuf = pcmbuf_mix_chunk->addr; 1071 obuf = mix_chunk->addr;
1081 chunk_samples = pcmbuf_mix_chunk->size / 2; 1072 chunk_samples = mix_chunk->size / 2;
1082 } 1073 }
1083 sample += obuf[pcmbuf_mix_sample] >> 2; 1074 sample += obuf[pcmbuf_mix_sample] >> 2;
1084 obuf[pcmbuf_mix_sample++] = clip_sample_16(sample); 1075 obuf[pcmbuf_mix_sample++] = clip_sample_16(sample);
@@ -1091,10 +1082,10 @@ void pcmbuf_write_voice_complete(int count)
1091/* Amount of bytes left in the buffer. */ 1082/* Amount of bytes left in the buffer. */
1092size_t pcmbuf_free(void) 1083size_t pcmbuf_free(void)
1093{ 1084{
1094 if (pcmbuf_read != NULL) 1085 if (read_chunk != NULL)
1095 { 1086 {
1096 void *read = pcmbuf_read->addr; 1087 void *read = read_chunk->addr;
1097 void *write = &audiobuffer[audiobuffer_pos + audiobuffer_fillpos]; 1088 void *write = &pcmbuffer[pcmbuffer_pos + pcmbuffer_fillpos];
1098 if (read < write) 1089 if (read < write)
1099 return (size_t)(read - write) + pcmbuf_size; 1090 return (size_t)(read - write) + pcmbuf_size;
1100 else 1091 else
@@ -1110,10 +1101,10 @@ size_t pcmbuf_get_bufsize(void)
1110 1101
1111int pcmbuf_used_descs(void) 1102int pcmbuf_used_descs(void)
1112{ 1103{
1113 struct pcmbufdesc *pcmbuf_temp = pcmbuf_read; 1104 struct chunkdesc *temp = read_chunk;
1114 unsigned int i = 0; 1105 unsigned int i = 0;
1115 while (pcmbuf_temp) { 1106 while (temp) {
1116 pcmbuf_temp = pcmbuf_temp->link; 1107 temp = temp->link;
1117 i++; 1108 i++;
1118 } 1109 }
1119 return i; 1110 return i;
@@ -1121,14 +1112,14 @@ int pcmbuf_used_descs(void)
1121 1112
1122int pcmbuf_descs(void) 1113int pcmbuf_descs(void)
1123{ 1114{
1124 return PCMBUF_DESCS(pcmbuf_size); 1115 return CHUNK_DESCS(pcmbuf_size);
1125} 1116}
1126 1117
1127#ifdef ROCKBOX_HAS_LOGF 1118#ifdef ROCKBOX_HAS_LOGF
1128unsigned char * pcmbuf_get_meminfo(size_t *length) 1119unsigned char * pcmbuf_get_meminfo(size_t *length)
1129{ 1120{
1130 *length = pcmbuf_bufend - audiobuffer; 1121 *length = pcmbuf_bufend - pcmbuffer;
1131 return audiobuffer; 1122 return pcmbuffer;
1132} 1123}
1133#endif 1124#endif
1134 1125
@@ -1175,10 +1166,10 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
1175 int16_t *bufptr, *bufstart, *bufend; 1166 int16_t *bufptr, *bufstart, *bufend;
1176 int32_t sample; 1167 int32_t sample;
1177 int nsamples = NATIVE_FREQUENCY / 1000 * duration; 1168 int nsamples = NATIVE_FREQUENCY / 1000 * duration;
1178 bool mix = pcmbuf_read != NULL && pcmbuf_read->link != NULL; 1169 bool mix = read_chunk != NULL && read_chunk->link != NULL;
1179 int i; 1170 int i;
1180 1171
1181 bufend = SKIPBYTES((int16_t *)audiobuffer, pcmbuf_size); 1172 bufend = SKIPBYTES((int16_t *)pcmbuffer, pcmbuf_size);
1182 1173
1183 /* Find the insertion point and set bufstart to the start of it */ 1174 /* Find the insertion point and set bufstart to the start of it */
1184 if (mix) 1175 if (mix)
@@ -1215,8 +1206,8 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
1215 } 1206 }
1216 else if (audio_buffer_state() != AUDIOBUF_STATE_TRASHED) 1207 else if (audio_buffer_state() != AUDIOBUF_STATE_TRASHED)
1217 { 1208 {
1218 /* Use audiobuffer */ 1209 /* Use pcmbuffer */
1219 bufstart = (int16_t *)audiobuffer; 1210 bufstart = (int16_t *)pcmbuffer;
1220 } 1211 }
1221 else 1212 else
1222 { 1213 {
@@ -1233,11 +1224,11 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
1233 sample = mix ? *bufptr : 0; 1224 sample = mix ? *bufptr : 0;
1234 *bufptr++ = clip_sample_16(sample + amp); 1225 *bufptr++ = clip_sample_16(sample + amp);
1235 if (bufptr >= bufend) 1226 if (bufptr >= bufend)
1236 bufptr = (int16_t *)audiobuffer; 1227 bufptr = (int16_t *)pcmbuffer;
1237 sample = mix ? *bufptr : 0; 1228 sample = mix ? *bufptr : 0;
1238 *bufptr++ = clip_sample_16(sample + amp); 1229 *bufptr++ = clip_sample_16(sample + amp);
1239 if (bufptr >= bufend) 1230 if (bufptr >= bufend)
1240 bufptr = (int16_t *)audiobuffer; 1231 bufptr = (int16_t *)pcmbuffer;
1241 1232
1242 phase += step; 1233 phase += step;
1243 } 1234 }