summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-02-07 00:51:50 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-02-07 00:51:50 +0000
commitaba6ca0881d1481b4047b2d7834d70ca2eb5c64b (patch)
tree6635b98840dcf4936b3c1ca641c00c32ea1b3e7f
parentdd50c863e60488662dee8f28f7292389ade42bac (diff)
downloadrockbox-aba6ca0881d1481b4047b2d7834d70ca2eb5c64b.tar.gz
rockbox-aba6ca0881d1481b4047b2d7834d70ca2eb5c64b.zip
Fix resampling clicking as much as possible at the moment. 1) Upsampling clicked because of size inaccuracies returned by DSP. Fix by simplifying audio system to use per-channel sample count from codec to pcm buffer. 2) Downsampling affected by 1) and was often starting passed the end of the data when not enough was available to generate an output sample. Fix by clamping input range to last sample in buffer and using the last sample value in the buffer. A perfect fix will require a double buffering scheme on the resampler to sufficient data during small data transients on both ends at all times of the down ratio on input and the up ratio on output.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12218 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs.c1
-rw-r--r--apps/codecs.h7
-rw-r--r--apps/codecs/a52.c7
-rw-r--r--apps/codecs/aac.c8
-rw-r--r--apps/codecs/adx.c7
-rw-r--r--apps/codecs/aiff.c17
-rw-r--r--apps/codecs/alac.c5
-rw-r--r--apps/codecs/flac.c7
-rw-r--r--apps/codecs/mpa.c10
-rw-r--r--apps/codecs/mpc.c7
-rw-r--r--apps/codecs/nsf.c4
-rw-r--r--apps/codecs/shorten.c7
-rw-r--r--apps/codecs/sid.c3
-rw-r--r--apps/codecs/vorbis.c5
-rw-r--r--apps/codecs/wav.c25
-rw-r--r--apps/codecs/wavpack.c3
-rw-r--r--apps/dsp.c130
-rw-r--r--apps/dsp.h6
-rw-r--r--apps/pcmbuf.c30
-rw-r--r--apps/pcmbuf.h8
-rw-r--r--apps/playback.c129
21 files changed, 170 insertions, 256 deletions
diff --git a/apps/codecs.c b/apps/codecs.c
index 3af5158fbb..09fd6e522e 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -78,7 +78,6 @@ struct codec_api ci = {
78 0, /* seek_time */ 78 0, /* seek_time */
79 NULL, /* get_codec_memory */ 79 NULL, /* get_codec_memory */
80 NULL, /* pcmbuf_insert */ 80 NULL, /* pcmbuf_insert */
81 NULL, /* pcmbuf_insert_split */
82 NULL, /* set_elapsed */ 81 NULL, /* set_elapsed */
83 NULL, /* read_filebuf */ 82 NULL, /* read_filebuf */
84 NULL, /* request_buffer */ 83 NULL, /* request_buffer */
diff --git a/apps/codecs.h b/apps/codecs.h
index e474c7a6bb..993ef3fecb 100644
--- a/apps/codecs.h
+++ b/apps/codecs.h
@@ -90,12 +90,12 @@
90#define CODEC_ENC_MAGIC 0x52454E43 /* RENC */ 90#define CODEC_ENC_MAGIC 0x52454E43 /* RENC */
91 91
92/* increase this every time the api struct changes */ 92/* increase this every time the api struct changes */
93#define CODEC_API_VERSION 12 93#define CODEC_API_VERSION 13
94 94
95/* update this to latest version if a change to the api struct breaks 95/* update this to latest version if a change to the api struct breaks
96 backwards compatibility (and please take the opportunity to sort in any 96 backwards compatibility (and please take the opportunity to sort in any
97 new function which are "waiting" at the end of the function table) */ 97 new function which are "waiting" at the end of the function table) */
98#define CODEC_MIN_API_VERSION 12 98#define CODEC_MIN_API_VERSION 13
99 99
100/* codec return codes */ 100/* codec return codes */
101enum codec_status { 101enum codec_status {
@@ -133,8 +133,7 @@ struct codec_api {
133 void* (*get_codec_memory)(size_t *size); 133 void* (*get_codec_memory)(size_t *size);
134 /* Insert PCM data into audio buffer for playback. Playback will start 134 /* Insert PCM data into audio buffer for playback. Playback will start
135 automatically. */ 135 automatically. */
136 bool (*pcmbuf_insert)(const char *data, size_t length); 136 bool (*pcmbuf_insert)(const void *ch1, const void *ch2, int count);
137 bool (*pcmbuf_insert_split)(const void *ch1, const void *ch2, size_t length);
138 /* Set song position in WPS (value in ms). */ 137 /* Set song position in WPS (value in ms). */
139 void (*set_elapsed)(unsigned int value); 138 void (*set_elapsed)(unsigned int value);
140 139
diff --git a/apps/codecs/a52.c b/apps/codecs/a52.c
index 4f41bfeaf5..028dff6db5 100644
--- a/apps/codecs/a52.c
+++ b/apps/codecs/a52.c
@@ -35,12 +35,9 @@ unsigned long frequency;
35/* used outside liba52 */ 35/* used outside liba52 */
36static uint8_t buf[3840] IBSS_ATTR; 36static uint8_t buf[3840] IBSS_ATTR;
37 37
38void output_audio(sample_t *samples) 38static inline void output_audio(sample_t *samples)
39{ 39{
40 do { 40 ci->pcmbuf_insert(&samples[0], &samples[256], 256);
41 ci->yield();
42 } while (!ci->pcmbuf_insert_split(&samples[0], &samples[256],
43 256*sizeof(sample_t)));
44} 41}
45 42
46void a52_decode_data(uint8_t *start, uint8_t *end) 43void a52_decode_data(uint8_t *start, uint8_t *end)
diff --git a/apps/codecs/aac.c b/apps/codecs/aac.c
index 4695caab4a..7656c416fe 100644
--- a/apps/codecs/aac.c
+++ b/apps/codecs/aac.c
@@ -183,12 +183,8 @@ next_track:
183 183
184 /* Output the audio */ 184 /* Output the audio */
185 ci->yield(); 185 ci->yield();
186 while (!ci->pcmbuf_insert_split(decoder->time_out[0], 186 ci->pcmbuf_insert(decoder->time_out[0], decoder->time_out[1],
187 decoder->time_out[1], 187 frame_info.samples >> 1);
188 frame_info.samples * 2))
189 {
190 ci->sleep(1);
191 }
192 188
193 /* Update the elapsed-time indicator */ 189 /* Update the elapsed-time indicator */
194 sound_samples_done += sample_duration; 190 sound_samples_done += sample_duration;
diff --git a/apps/codecs/adx.c b/apps/codecs/adx.c
index 608d9f0a3f..85e55a4c38 100644
--- a/apps/codecs/adx.c
+++ b/apps/codecs/adx.c
@@ -320,9 +320,10 @@ next_track:
320 } 320 }
321 } 321 }
322 322
323 /* 2 bytes per sample */ 323 if (channels == 2)
324 while (!ci->pcmbuf_insert((char *)samples, sampleswritten*2)) 324 sampleswritten >>= 1; /* make samples/channel */
325 ci->yield(); 325
326 ci->pcmbuf_insert(samples, NULL, sampleswritten);
326 327
327 ci->set_elapsed( 328 ci->set_elapsed(
328 ((end_adr-start_adr)*loop_count + bufoff-chanstart)* 329 ((end_adr-start_adr)*loop_count + bufoff-chanstart)*
diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c
index d1bb14aa64..628f9948ea 100644
--- a/apps/codecs/aiff.c
+++ b/apps/codecs/aiff.c
@@ -51,7 +51,8 @@ enum codec_status codec_main(void)
51 uint16_t sample_size = 0; 51 uint16_t sample_size = 0;
52 uint32_t sample_rate = 0; 52 uint32_t sample_rate = 0;
53 uint32_t i; 53 uint32_t i;
54 size_t n, bufsize; 54 size_t n;
55 int bufcount;
55 int endofstream; 56 int endofstream;
56 unsigned char *buf; 57 unsigned char *buf;
57 uint8_t *aifbuf; 58 uint8_t *aifbuf;
@@ -229,25 +230,27 @@ next_track:
229 samples[i/4] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13) 230 samples[i/4] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13)
230 |(aifbuf[i + 2]<<5)|(aifbuf[i + 3]>>3); 231 |(aifbuf[i + 2]<<5)|(aifbuf[i + 3]>>3);
231 } 232 }
232 bufsize = n; 233 bufcount = n >> 2;
233 } else if (sample_size > 16) { 234 } else if (sample_size > 16) {
234 for (i = 0; i < n; i += 3) { 235 for (i = 0; i < n; i += 3) {
235 samples[i/3] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13) 236 samples[i/3] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13)
236 |(aifbuf[i + 2]<<5); 237 |(aifbuf[i + 2]<<5);
237 } 238 }
238 bufsize = n*4/3; 239 bufcount = n/3;
239 } else if (sample_size > 8) { 240 } else if (sample_size > 8) {
240 for (i = 0; i < n; i += 2) 241 for (i = 0; i < n; i += 2)
241 samples[i/2] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13); 242 samples[i/2] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13);
242 bufsize = n*2; 243 bufcount = n >> 1;
243 } else { 244 } else {
244 for (i = 0; i < n; i++) 245 for (i = 0; i < n; i++)
245 samples[i] = SE(aifbuf[i]) << 21; 246 samples[i] = SE(aifbuf[i]) << 21;
246 bufsize = n*4; 247 bufcount = n;
247 } 248 }
248 249
249 while (!ci->pcmbuf_insert((char *)samples, bufsize)) 250 if (num_channels == 2)
250 ci->yield(); 251 bufcount >>= 1;
252
253 ci->pcmbuf_insert(samples, NULL, bufcount);
251 254
252 ci->advance_buffer(n); 255 ci->advance_buffer(n);
253 bytesdone += n; 256 bytesdone += n;
diff --git a/apps/codecs/alac.c b/apps/codecs/alac.c
index 1c1b14a0da..cfa713a29a 100644
--- a/apps/codecs/alac.c
+++ b/apps/codecs/alac.c
@@ -121,10 +121,7 @@ enum codec_status codec_main(void)
121 121
122 /* Output the audio */ 122 /* Output the audio */
123 ci->yield(); 123 ci->yield();
124 while(!ci->pcmbuf_insert_split(outputbuffer[0], 124 ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded);
125 outputbuffer[1],
126 samplesdecoded*sizeof(int32_t)))
127 ci->yield();
128 125
129 /* Update the elapsed-time indicator */ 126 /* Update the elapsed-time indicator */
130 samplesdone+=sample_duration; 127 samplesdone+=sample_duration;
diff --git a/apps/codecs/flac.c b/apps/codecs/flac.c
index 649c26a6bb..738e4bb391 100644
--- a/apps/codecs/flac.c
+++ b/apps/codecs/flac.c
@@ -489,11 +489,8 @@ enum codec_status codec_main(void)
489 frame++; 489 frame++;
490 490
491 ci->yield(); 491 ci->yield();
492 while(!ci->pcmbuf_insert_split((char*)&decoded0[fc.sample_skip], 492 ci->pcmbuf_insert(&decoded0[fc.sample_skip], &decoded1[fc.sample_skip],
493 (char*)&decoded1[fc.sample_skip], 493 fc.blocksize - fc.sample_skip);
494 (fc.blocksize-fc.sample_skip)*4)) {
495 ci->yield();
496 }
497 494
498 fc.sample_skip = 0; 495 fc.sample_skip = 0;
499 496
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c
index 6e474c1abb..4c99778071 100644
--- a/apps/codecs/mpa.c
+++ b/apps/codecs/mpa.c
@@ -199,9 +199,9 @@ next_track:
199 loop we will need to process the final frame that was decoded. */ 199 loop we will need to process the final frame that was decoded. */
200 if (framelength > 0) { 200 if (framelength > 0) {
201 /* In case of a mono file, the second array will be ignored. */ 201 /* In case of a mono file, the second array will be ignored. */
202 ci->pcmbuf_insert_split(&synth.pcm.samples[0][samples_to_skip], 202 ci->pcmbuf_insert(&synth.pcm.samples[0][samples_to_skip],
203 &synth.pcm.samples[1][samples_to_skip], 203 &synth.pcm.samples[1][samples_to_skip],
204 framelength * 4); 204 framelength);
205 205
206 /* Only skip samples for the first frame added. */ 206 /* Only skip samples for the first frame added. */
207 samples_to_skip = 0; 207 samples_to_skip = 0;
@@ -244,8 +244,8 @@ next_track:
244 /* Finish the remaining decoded frame. 244 /* Finish the remaining decoded frame.
245 Cut the required samples from the end. */ 245 Cut the required samples from the end. */
246 if (framelength > stop_skip) 246 if (framelength > stop_skip)
247 ci->pcmbuf_insert_split(synth.pcm.samples[0], synth.pcm.samples[1], 247 ci->pcmbuf_insert(synth.pcm.samples[0], synth.pcm.samples[1],
248 (framelength - stop_skip) * 4); 248 framelength - stop_skip);
249 249
250 stream.error = 0; 250 stream.error = 0;
251 251
diff --git a/apps/codecs/mpc.c b/apps/codecs/mpc.c
index 1075d88aa1..8aba8e50c2 100644
--- a/apps/codecs/mpc.c
+++ b/apps/codecs/mpc.c
@@ -168,10 +168,9 @@ next_track:
168 retval = CODEC_ERROR; 168 retval = CODEC_ERROR;
169 goto done; 169 goto done;
170 } else { 170 } else {
171 while (!ci->pcmbuf_insert_split(sample_buffer, 171 ci->pcmbuf_insert(sample_buffer,
172 sample_buffer + MPC_FRAME_LENGTH, 172 sample_buffer + MPC_FRAME_LENGTH,
173 status*sizeof(MPC_SAMPLE_FORMAT))) 173 status);
174 ci->yield();
175 samplesdone += status; 174 samplesdone += status;
176 ci->set_elapsed(samplesdone/frequency); 175 ci->set_elapsed(samplesdone/frequency);
177 } 176 }
diff --git a/apps/codecs/nsf.c b/apps/codecs/nsf.c
index 77043b60ce..f138fa1e01 100644
--- a/apps/codecs/nsf.c
+++ b/apps/codecs/nsf.c
@@ -4445,9 +4445,7 @@ init_nsf:
4445 goto init_nsf; 4445 goto init_nsf;
4446 } 4446 }
4447 4447
4448 while (!ci->pcmbuf_insert((char *)samples, written)) 4448 ci->pcmbuf_insert(samples, NULL, written >> 1);
4449 ci->yield();
4450
4451 } 4449 }
4452 4450
4453 print_timers(last_path,track); 4451 print_timers(last_path,track);
diff --git a/apps/codecs/shorten.c b/apps/codecs/shorten.c
index 1b9563a676..3c099bc031 100644
--- a/apps/codecs/shorten.c
+++ b/apps/codecs/shorten.c
@@ -134,11 +134,8 @@ seek_start:
134 /* Insert decoded samples in pcmbuf */ 134 /* Insert decoded samples in pcmbuf */
135 if (nsamples) { 135 if (nsamples) {
136 ci->yield(); 136 ci->yield();
137 while (!ci->pcmbuf_insert_split((char*)(decoded0 + sc.nwrap), 137 ci->pcmbuf_insert(decoded0 + sc.nwrap, decoded1 + sc.nwrap,
138 (char*)(decoded1 + sc.nwrap), 138 nsamples);
139 4*nsamples)) {
140 ci->yield();
141 }
142 139
143 /* Update the elapsed-time indicator */ 140 /* Update the elapsed-time indicator */
144 samplesdone += nsamples; 141 samplesdone += nsamples;
diff --git a/apps/codecs/sid.c b/apps/codecs/sid.c
index 58eb725057..59683e9b6a 100644
--- a/apps/codecs/sid.c
+++ b/apps/codecs/sid.c
@@ -1309,8 +1309,7 @@ next_track:
1309 } 1309 }
1310 } 1310 }
1311 1311
1312 while (!ci->pcmbuf_insert((char *)samples, CHUNK_SIZE*4)) 1312 ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE);
1313 ci->yield();
1314 } 1313 }
1315 1314
1316 if (ci->request_next_track()) 1315 if (ci->request_next_track())
diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c
index a6a90654b5..8ab4a95faa 100644
--- a/apps/codecs/vorbis.c
+++ b/apps/codecs/vorbis.c
@@ -217,10 +217,7 @@ next_track:
217 } else if (n < 0) { 217 } else if (n < 0) {
218 DEBUGF("Error decoding frame\n"); 218 DEBUGF("Error decoding frame\n");
219 } else { 219 } else {
220 while (!ci->pcmbuf_insert_split(pcm[0], pcm[1], 220 ci->pcmbuf_insert(pcm[0], pcm[1], n);
221 n*sizeof(ogg_int32_t))) {
222 ci->sleep(1);
223 }
224 ci->set_offset(ov_raw_tell(&vf)); 221 ci->set_offset(ov_raw_tell(&vf));
225 ci->set_elapsed(ov_time_tell(&vf)); 222 ci->set_elapsed(ov_time_tell(&vf));
226 } 223 }
diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c
index 26cbf7f6a1..ec268a3a2b 100644
--- a/apps/codecs/wav.c
+++ b/apps/codecs/wav.c
@@ -212,7 +212,8 @@ enum codec_status codec_main(void)
212 int bytespersample = 0; 212 int bytespersample = 0;
213 uint16_t bitspersample; 213 uint16_t bitspersample;
214 uint32_t i; 214 uint32_t i;
215 size_t n, bufsize; 215 size_t n;
216 int bufcount;
216 int endofstream; 217 int endofstream;
217 unsigned char *buf; 218 unsigned char *buf;
218 uint8_t *wavbuf; 219 uint8_t *wavbuf;
@@ -466,34 +467,39 @@ next_track:
466 (wavbuf[i + 1]<<5)|(wavbuf[i + 2]<<13)| 467 (wavbuf[i + 1]<<5)|(wavbuf[i + 2]<<13)|
467 (SE(wavbuf[i + 3])<<21); 468 (SE(wavbuf[i + 3])<<21);
468 } 469 }
469 bufsize = n; 470 bufcount = n >> 2;
470 } else if (bitspersample > 16) { 471 } else if (bitspersample > 16) {
471 for (i = 0; i < n; i += 3) { 472 for (i = 0; i < n; i += 3) {
472 samples[i/3] = (wavbuf[i]<<5)| 473 samples[i/3] = (wavbuf[i]<<5)|
473 (wavbuf[i + 1]<<13)|(SE(wavbuf[i + 2])<<21); 474 (wavbuf[i + 1]<<13)|(SE(wavbuf[i + 2])<<21);
474 } 475 }
475 bufsize = n*4/3; 476 bufcount = n/3;
476 } else if (bitspersample > 8) { 477 } else if (bitspersample > 8) {
477 for (i = 0; i < n; i += 2) { 478 for (i = 0; i < n; i += 2) {
478 samples[i/2] = (wavbuf[i]<<13)|(SE(wavbuf[i + 1])<<21); 479 samples[i/2] = (wavbuf[i]<<13)|(SE(wavbuf[i + 1])<<21);
479 } 480 }
480 bufsize = n*2; 481 bufcount = n >> 1;
481 } else { 482 } else {
482 for (i = 0; i < n; i++) { 483 for (i = 0; i < n; i++) {
483 samples[i] = (wavbuf[i] - 0x80)<<21; 484 samples[i] = (wavbuf[i] - 0x80)<<21;
484 } 485 }
485 bufsize = n*4; 486 bufcount = n;
486 } 487 }
488
489 if (channels == 2)
490 bufcount >>= 1;
487 } else if (formattag == WAVE_FORMAT_ALAW 491 } else if (formattag == WAVE_FORMAT_ALAW
488 || formattag == IBM_FORMAT_ALAW) { 492 || formattag == IBM_FORMAT_ALAW) {
489 for (i = 0; i < n; i++) 493 for (i = 0; i < n; i++)
490 samples[i] = alaw2linear16[wavbuf[i]] << 13; 494 samples[i] = alaw2linear16[wavbuf[i]] << 13;
491 bufsize = n*4; 495
496 bufcount = (channels == 2) ? (n >> 1) : n;
492 } else if (formattag == WAVE_FORMAT_MULAW 497 } else if (formattag == WAVE_FORMAT_MULAW
493 || formattag == IBM_FORMAT_MULAW) { 498 || formattag == IBM_FORMAT_MULAW) {
494 for (i = 0; i < n; i++) 499 for (i = 0; i < n; i++)
495 samples[i] = ulaw2linear16[wavbuf[i]] << 13; 500 samples[i] = ulaw2linear16[wavbuf[i]] << 13;
496 bufsize = n*4; 501
502 bufcount = (channels == 2) ? (n >> 1) : n;
497 } 503 }
498 else if (formattag == WAVE_FORMAT_DVI_ADPCM) { 504 else if (formattag == WAVE_FORMAT_DVI_ADPCM) {
499 unsigned int nblocks = chunksize/blockalign; 505 unsigned int nblocks = chunksize/blockalign;
@@ -508,15 +514,14 @@ next_track:
508 goto done; 514 goto done;
509 } 515 }
510 } 516 }
511 bufsize = nblocks*samplesperblock*channels*4; 517 bufcount = nblocks*samplesperblock;
512 } else { 518 } else {
513 DEBUGF("CODEC_ERROR: unsupported format %x\n", formattag); 519 DEBUGF("CODEC_ERROR: unsupported format %x\n", formattag);
514 i = CODEC_ERROR; 520 i = CODEC_ERROR;
515 goto done; 521 goto done;
516 } 522 }
517 523
518 while (!ci->pcmbuf_insert((char *)samples, bufsize)) 524 ci->pcmbuf_insert(samples, NULL, bufcount);
519 ci->yield();
520 525
521 ci->advance_buffer(n); 526 ci->advance_buffer(n);
522 bytesdone += n; 527 bytesdone += n;
diff --git a/apps/codecs/wavpack.c b/apps/codecs/wavpack.c
index e2c19c82e4..34616d75e9 100644
--- a/apps/codecs/wavpack.c
+++ b/apps/codecs/wavpack.c
@@ -118,8 +118,7 @@ enum codec_status codec_main(void)
118 if (ci->stop_codec || ci->new_track) 118 if (ci->stop_codec || ci->new_track)
119 break; 119 break;
120 120
121 while (!ci->pcmbuf_insert ((char *) temp_buffer, nsamples * nchans * 4)) 121 ci->pcmbuf_insert (temp_buffer, NULL, nsamples);
122 ci->sleep (1);
123 122
124 ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); 123 ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
125 ci->yield (); 124 ci->yield ();
diff --git a/apps/dsp.c b/apps/dsp.c
index c4630ada77..f7eb48ed03 100644
--- a/apps/dsp.c
+++ b/apps/dsp.c
@@ -40,8 +40,8 @@
40#define WORD_FRACBITS 27 40#define WORD_FRACBITS 27
41 41
42#define NATIVE_DEPTH 16 42#define NATIVE_DEPTH 16
43#define SAMPLE_BUF_SIZE 256 43#define SAMPLE_BUF_COUNT 256
44#define RESAMPLE_BUF_SIZE (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ 44#define RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/
45#define DEFAULT_GAIN 0x01000000 45#define DEFAULT_GAIN 0x01000000
46 46
47struct dsp_config 47struct dsp_config
@@ -116,8 +116,8 @@ static struct dsp_config *dsp;
116 * of copying needed is minimized for that case. 116 * of copying needed is minimized for that case.
117 */ 117 */
118 118
119static int32_t sample_buf[SAMPLE_BUF_SIZE] IBSS_ATTR; 119static int32_t sample_buf[SAMPLE_BUF_COUNT] IBSS_ATTR;
120static int32_t resample_buf[RESAMPLE_BUF_SIZE] IBSS_ATTR; 120static int32_t resample_buf[RESAMPLE_BUF_COUNT] IBSS_ATTR;
121 121
122int sound_get_pitch(void) 122int sound_get_pitch(void)
123{ 123{
@@ -139,14 +139,14 @@ void sound_set_pitch(int permille)
139 */ 139 */
140static int convert_to_internal(const char* src[], int count, int32_t* dst[]) 140static int convert_to_internal(const char* src[], int count, int32_t* dst[])
141{ 141{
142 count = MIN(SAMPLE_BUF_SIZE / 2, count); 142 count = MIN(SAMPLE_BUF_COUNT / 2, count);
143 143
144 if ((dsp->sample_depth <= NATIVE_DEPTH) 144 if ((dsp->sample_depth <= NATIVE_DEPTH)
145 || (dsp->stereo_mode == STEREO_INTERLEAVED)) 145 || (dsp->stereo_mode == STEREO_INTERLEAVED))
146 { 146 {
147 dst[0] = &sample_buf[0]; 147 dst[0] = &sample_buf[0];
148 dst[1] = (dsp->stereo_mode == STEREO_MONO) 148 dst[1] = (dsp->stereo_mode == STEREO_MONO)
149 ? dst[0] : &sample_buf[SAMPLE_BUF_SIZE / 2]; 149 ? dst[0] : &sample_buf[SAMPLE_BUF_COUNT / 2];
150 } 150 }
151 else 151 else
152 { 152 {
@@ -231,7 +231,7 @@ static void resampler_set_delta(int frequency)
231 231
232/* TODO: we really should have a separate set of resample functions for both 232/* TODO: we really should have a separate set of resample functions for both
233 mono and stereo to avoid all this internal branching and looping. */ 233 mono and stereo to avoid all this internal branching and looping. */
234static long downsample(int32_t **dst, int32_t **src, int count, 234static int downsample(int32_t **dst, int32_t **src, int count,
235 struct resample_data *r) 235 struct resample_data *r)
236{ 236{
237 long phase = r->phase; 237 long phase = r->phase;
@@ -246,11 +246,14 @@ static long downsample(int32_t **dst, int32_t **src, int count,
246 last_sample = r->last_sample[j]; 246 last_sample = r->last_sample[j];
247 /* Do we need last sample of previous frame for interpolation? */ 247 /* Do we need last sample of previous frame for interpolation? */
248 if (pos > 0) 248 if (pos > 0)
249 {
250 last_sample = src[j][pos - 1]; 249 last_sample = src[j][pos - 1];
251 } 250
252 *d[j]++ = last_sample + FRACMUL((phase & 0xffff) << 15, 251 /* Be sure starting position isn't passed the available data */
253 src[j][pos] - last_sample); 252 if (pos < count)
253 *d[j]++ = last_sample + FRACMUL((phase & 0xffff) << 15,
254 src[j][pos] - last_sample);
255 else /* This is kinda nasty but works somewhat well for now */
256 *d[j]++ = src[j][count - 1];
254 } 257 }
255 phase += delta; 258 phase += delta;
256 259
@@ -316,7 +319,7 @@ static inline int resample(int32_t* src[], int count)
316 319
317 if (dsp->frequency != NATIVE_FREQUENCY) 320 if (dsp->frequency != NATIVE_FREQUENCY)
318 { 321 {
319 int32_t* dst[2] = {&resample_buf[0], &resample_buf[RESAMPLE_BUF_SIZE / 2]}; 322 int32_t* dst[2] = {&resample_buf[0], &resample_buf[RESAMPLE_BUF_COUNT / 2]};
320 323
321 if (dsp->frequency < NATIVE_FREQUENCY) 324 if (dsp->frequency < NATIVE_FREQUENCY)
322 { 325 {
@@ -619,7 +622,7 @@ static void apply_gain(int32_t* _src[], int _count)
619 622
620 if (s0 != s1) 623 if (s0 != s1)
621 { 624 {
622 d = &sample_buf[SAMPLE_BUF_SIZE / 2]; 625 d = &sample_buf[SAMPLE_BUF_COUNT / 2];
623 src[1] = d; 626 src[1] = d;
624 s = *s1++; 627 s = *s1++;
625 628
@@ -736,18 +739,17 @@ static void write_samples(short* dst, int32_t* src[], int count)
736} 739}
737 740
738/* Process and convert src audio to dst based on the DSP configuration, 741/* Process and convert src audio to dst based on the DSP configuration,
739 * reading size bytes of audio data. dst is assumed to be large enough; use 742 * reading count number of audio samples. dst is assumed to be large
740 * dst_get_dest_size() to get the required size. src is an array of 743 * enough; use dsp_output_count() to get the required number. src is an
741 * pointers; for mono and interleaved stereo, it contains one pointer to the 744 * array of pointers; for mono and interleaved stereo, it contains one
742 * start of the audio data; for non-interleaved stereo, it contains two 745 * pointer to the start of the audio data and the other is ignored; for
743 * pointers, one for each audio channel. Returns number of bytes written to 746 * non-interleaved stereo, it contains two pointers, one for each audio
744 * dest. 747 * channel. Returns number of bytes written to dst.
745 */ 748 */
746long dsp_process(char* dst, const char* src[], long size) 749int dsp_process(char *dst, const char *src[], int count)
747{ 750{
748 int32_t* tmp[2]; 751 int32_t* tmp[2];
749 long written = 0; 752 int written = 0;
750 long factor;
751 int samples; 753 int samples;
752 754
753 #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) 755 #if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
@@ -759,14 +761,12 @@ long dsp_process(char* dst, const char* src[], long size)
759 761
760 dsp = &dsp_conf[current_codec]; 762 dsp = &dsp_conf[current_codec];
761 763
762 factor = (dsp->stereo_mode != STEREO_MONO) ? 2 : 1;
763 size /= dsp->sample_bytes * factor;
764 dsp_set_replaygain(false); 764 dsp_set_replaygain(false);
765 765
766 while (size > 0) 766 while (count > 0)
767 { 767 {
768 samples = convert_to_internal(src, size, tmp); 768 samples = convert_to_internal(src, count, tmp);
769 size -= samples; 769 count -= samples;
770 apply_gain(tmp, samples); 770 apply_gain(tmp, samples);
771 samples = resample(tmp, samples); 771 samples = resample(tmp, samples);
772 if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO) 772 if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO)
@@ -780,85 +780,61 @@ long dsp_process(char* dst, const char* src[], long size)
780 dst += samples * sizeof(short) * 2; 780 dst += samples * sizeof(short) * 2;
781 yield(); 781 yield();
782 } 782 }
783
783 #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) 784 #if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
784 /* set old macsr again */ 785 /* set old macsr again */
785 coldfire_set_macsr(old_macsr); 786 coldfire_set_macsr(old_macsr);
786 #endif 787 #endif
787 return written * sizeof(short) * 2; 788 return written;
788} 789}
789 790
790/* Given size bytes of input data, calculate the maximum number of bytes of 791/* Given count number of input samples, calculate the maximum number of
791 * output data that would be generated (the calculation is not entirely 792 * samples of output data that would be generated (the calculation is not
792 * exact and rounds upwards to be on the safe side; during resampling, 793 * entirely exact and rounds upwards to be on the safe side; during
793 * the number of samples generated depends on the current state of the 794 * resampling, the number of samples generated depends on the current state
794 * resampler). 795 * of the resampler).
795 */ 796 */
796/* dsp_input_size MUST be called afterwards */ 797/* dsp_input_size MUST be called afterwards */
797long dsp_output_size(long size) 798int dsp_output_count(int count)
798{ 799{
799 dsp = &dsp_conf[current_codec]; 800 dsp = &dsp_conf[current_codec];
800 801
801 if (dsp->sample_depth > NATIVE_DEPTH)
802 {
803 size /= 2;
804 }
805
806 if (dsp->frequency != NATIVE_FREQUENCY) 802 if (dsp->frequency != NATIVE_FREQUENCY)
807 { 803 {
808 size = (long) ((((unsigned long) size * NATIVE_FREQUENCY) 804 count = (int)(((unsigned long)count * NATIVE_FREQUENCY
809 + (dsp->frequency - 1)) / dsp->frequency); 805 + (dsp->frequency - 1)) / dsp->frequency);
810 }
811
812 /* round to the next multiple of 2 (these are shorts) */
813 size = (size + 1) & ~1;
814
815 if (dsp->stereo_mode == STEREO_MONO)
816 {
817 size *= 2;
818 } 806 }
819 807
820 /* now we have the size in bytes for two resampled channels, 808 /* Now we have the resampled sample count which must not exceed
821 * and the size in (short) must not exceed RESAMPLE_BUF_SIZE to 809 * RESAMPLE_BUF_COUNT/2 to avoid resample buffer overflow. One
822 * avoid resample buffer overflow. One must call dsp_input_size() 810 * must call dsp_input_count() to get the correct input sample
823 * to get the correct input buffer size. */ 811 * count.
824 if (size > RESAMPLE_BUF_SIZE*2) 812 */
825 size = RESAMPLE_BUF_SIZE*2; 813 if (count > RESAMPLE_BUF_COUNT/2)
814 count = RESAMPLE_BUF_COUNT/2;
826 815
827 return size; 816 return count;
828} 817}
829 818
830/* Given size bytes of output buffer, calculate number of bytes of input 819/* Given count output samples, calculate number of input samples
831 * data that would be consumed in order to fill the output buffer. 820 * that would be consumed in order to fill the output buffer.
832 */ 821 */
833long dsp_input_size(long size) 822int dsp_input_count(int count)
834{ 823{
835 dsp = &dsp_conf[current_codec]; 824 dsp = &dsp_conf[current_codec];
836
837 /* convert to number of output stereo samples. */
838 size /= 2;
839 825
840 /* Mono means we need half input samples to fill the output buffer */ 826 /* count is now the number of resampled input samples. Convert to
841 if (dsp->stereo_mode == STEREO_MONO)
842 size /= 2;
843
844 /* size is now the number of resampled input samples. Convert to
845 original input samples. */ 827 original input samples. */
846 if (dsp->frequency != NATIVE_FREQUENCY) 828 if (dsp->frequency != NATIVE_FREQUENCY)
847 { 829 {
848 /* Use the real resampling delta = 830 /* Use the real resampling delta =
849 * (unsigned long) dsp->frequency * 65536 / NATIVE_FREQUENCY, and 831 * dsp->frequency * 65536 / NATIVE_FREQUENCY, and
850 * round towards zero to avoid buffer overflows. */ 832 * round towards zero to avoid buffer overflows. */
851 size = ((unsigned long)size * 833 count = (int)(((unsigned long)count *
852 resample_data[current_codec].delta) >> 16; 834 resample_data[current_codec].delta) >> 16);
853 } 835 }
854 836
855 /* Convert back to bytes. */ 837 return count;
856 if (dsp->sample_depth > NATIVE_DEPTH)
857 size *= 4;
858 else
859 size *= 2;
860
861 return size;
862} 838}
863 839
864int dsp_stereo_mode(void) 840int dsp_stereo_mode(void)
diff --git a/apps/dsp.h b/apps/dsp.h
index ccea8cba34..5217224797 100644
--- a/apps/dsp.h
+++ b/apps/dsp.h
@@ -206,9 +206,9 @@ enum {
206 206
207#define DIV64(x, y, z) (long)(((long long)(x) << (z))/(y)) 207#define DIV64(x, y, z) (long)(((long long)(x) << (z))/(y))
208 208
209long dsp_process(char *dest, const char *src[], long size); 209int dsp_process(char *dest, const char *src[], int count);
210long dsp_input_size(long size); 210int dsp_input_count(int count);
211long dsp_output_size(long size); 211int dsp_output_count(int count);
212int dsp_stereo_mode(void); 212int dsp_stereo_mode(void);
213bool dsp_configure(int setting, void *value); 213bool dsp_configure(int setting, void *value);
214void dsp_set_replaygain(bool always); 214void dsp_set_replaygain(bool always);
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index f9d60e9b58..e2b1d7f87b 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -791,21 +791,20 @@ static bool prepare_insert(size_t length)
791 return true; 791 return true;
792} 792}
793 793
794void* pcmbuf_request_buffer(size_t length, size_t *realsize) 794void* pcmbuf_request_buffer(int *count)
795{ 795{
796 if (crossfade_init) 796 if (crossfade_init)
797 crossfade_start(); 797 crossfade_start();
798 798
799 if (crossfade_active) { 799 if (crossfade_active) {
800 *realsize = MIN(length, PCMBUF_MIX_CHUNK); 800 *count = MIN(*count, PCMBUF_MIX_CHUNK/4);
801 return fadebuf; 801 return fadebuf;
802 } 802 }
803 else 803 else
804 { 804 {
805 if(prepare_insert(length)) 805 if(prepare_insert(*count << 2))
806 { 806 {
807 size_t audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; 807 size_t audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos;
808 *realsize = length;
809 if (pcmbuf_size - audiobuffer_index >= PCMBUF_MIN_CHUNK) 808 if (pcmbuf_size - audiobuffer_index >= PCMBUF_MIN_CHUNK)
810 { 809 {
811 /* Usual case, there's space here */ 810 /* Usual case, there's space here */
@@ -821,34 +820,31 @@ void* pcmbuf_request_buffer(size_t length, size_t *realsize)
821 } 820 }
822 else 821 else
823 { 822 {
824 *realsize = 0;
825 return NULL; 823 return NULL;
826 } 824 }
827 } 825 }
828} 826}
829 827
830void* pcmbuf_request_voice_buffer(size_t length, size_t *realsize, bool mix) 828void* pcmbuf_request_voice_buffer(int *count, bool mix)
831{ 829{
832 if (mix) 830 if (mix)
833 { 831 {
834 if (pcmbuf_read == NULL) 832 if (pcmbuf_read == NULL)
835 { 833 {
836 *realsize = 0;
837 return NULL; 834 return NULL;
838 } 835 }
839 else if (pcmbuf_mix_chunk || pcmbuf_read->link) 836 else if (pcmbuf_mix_chunk || pcmbuf_read->link)
840 { 837 {
841 *realsize = MIN(length, PCMBUF_MIX_CHUNK); 838 *count = MIN(*count, PCMBUF_MIX_CHUNK/4);
842 return voicebuf; 839 return voicebuf;
843 } 840 }
844 else 841 else
845 { 842 {
846 *realsize = 0;
847 return NULL; 843 return NULL;
848 } 844 }
849 } 845 }
850 else 846 else
851 return pcmbuf_request_buffer(length, realsize); 847 return pcmbuf_request_buffer(count);
852} 848}
853 849
854bool pcmbuf_is_crossfade_active(void) 850bool pcmbuf_is_crossfade_active(void)
@@ -856,8 +852,10 @@ bool pcmbuf_is_crossfade_active(void)
856 return crossfade_active || crossfade_init; 852 return crossfade_active || crossfade_init;
857} 853}
858 854
859void pcmbuf_write_complete(size_t length) 855void pcmbuf_write_complete(int count)
860{ 856{
857 size_t length = (size_t)(unsigned int)count << 2;
858
861 if (crossfade_active) 859 if (crossfade_active)
862 { 860 {
863 flush_crossfade(fadebuf, length); 861 flush_crossfade(fadebuf, length);
@@ -874,8 +872,10 @@ void pcmbuf_write_complete(size_t length)
874} 872}
875 873
876#if 0 874#if 0
877bool pcmbuf_insert_buffer(char *buf, size_t length) 875bool pcmbuf_insert_buffer(char *buf, int count)
878{ 876{
877 size_t length = (size_t)(unsigned int)count << 2;
878
879 if (crossfade_active) 879 if (crossfade_active)
880 { 880 {
881 flush_crossfade(buf, length); 881 flush_crossfade(buf, length);
@@ -980,7 +980,7 @@ int pcmbuf_mix_free(void)
980 return 100; 980 return 100;
981} 981}
982 982
983void pcmbuf_mix_voice(size_t length) 983void pcmbuf_mix_voice(int count)
984{ 984{
985 short *ibuf = (short *)voicebuf; 985 short *ibuf = (short *)voicebuf;
986 short *obuf; 986 short *obuf;
@@ -998,9 +998,9 @@ void pcmbuf_mix_voice(size_t length)
998 obuf = (short *)pcmbuf_mix_chunk->addr; 998 obuf = (short *)pcmbuf_mix_chunk->addr;
999 chunk_samples = pcmbuf_mix_chunk->size / 2; 999 chunk_samples = pcmbuf_mix_chunk->size / 2;
1000 1000
1001 length /= 2; 1001 count <<= 1;
1002 1002
1003 while (length-- > 0) { 1003 while (count-- > 0) {
1004 int sample = *ibuf++; 1004 int sample = *ibuf++;
1005 if (pcmbuf_mix_sample >= chunk_samples) 1005 if (pcmbuf_mix_sample >= chunk_samples)
1006 { 1006 {
diff --git a/apps/pcmbuf.h b/apps/pcmbuf.h
index a408cdae42..5c35ecc291 100644
--- a/apps/pcmbuf.h
+++ b/apps/pcmbuf.h
@@ -63,16 +63,16 @@ void pcmbuf_set_position_callback(void (*callback)(size_t size));
63size_t pcmbuf_free(void); 63size_t pcmbuf_free(void);
64unsigned int pcmbuf_get_latency(void); 64unsigned int pcmbuf_get_latency(void);
65void pcmbuf_set_low_latency(bool state); 65void pcmbuf_set_low_latency(bool state);
66void pcmbuf_write_complete(size_t length); 66void pcmbuf_write_complete(int count);
67void* pcmbuf_request_buffer(size_t length, size_t *realsize); 67void* pcmbuf_request_buffer(int *count);
68void* pcmbuf_request_voice_buffer(size_t length, size_t *realsize, bool mix); 68void* pcmbuf_request_voice_buffer(int *count, bool mix);
69bool pcmbuf_is_crossfade_enabled(void); 69bool pcmbuf_is_crossfade_enabled(void);
70void pcmbuf_crossfade_enable(bool on_off); 70void pcmbuf_crossfade_enable(bool on_off);
71 71
72int pcmbuf_usage(void); 72int pcmbuf_usage(void);
73int pcmbuf_mix_free(void); 73int pcmbuf_mix_free(void);
74void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude); 74void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude);
75void pcmbuf_mix_voice(size_t length); 75void pcmbuf_mix_voice(int count);
76 76
77int pcmbuf_used_descs(void); 77int pcmbuf_used_descs(void);
78int pcmbuf_descs(void); 78int pcmbuf_descs(void);
diff --git a/apps/playback.c b/apps/playback.c
index ff681bb85c..939643890e 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -1022,81 +1022,60 @@ static const char * get_codec_filename(int cod_spec)
1022 1022
1023#ifdef PLAYBACK_VOICE 1023#ifdef PLAYBACK_VOICE
1024 1024
1025static bool voice_pcmbuf_insert_split_callback( 1025static bool voice_pcmbuf_insert_callback(
1026 const void *ch1, const void *ch2, size_t length) 1026 const void *ch1, const void *ch2, int count)
1027{ 1027{
1028 const char* src[2]; 1028 const char *src[2] = { ch1, ch2 };
1029 char *dest;
1030 long input_size;
1031 size_t output_size;
1032 1029
1033 src[0] = ch1; 1030 while (count > 0)
1034 src[1] = ch2;
1035
1036 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
1037 length *= 2; /* Length is per channel */
1038
1039 while (length)
1040 { 1031 {
1041 long est_output_size = dsp_output_size(length); 1032 int out_count = dsp_output_count(count);
1042 1033 int inp_count;
1043 while ((dest = pcmbuf_request_voice_buffer(est_output_size, 1034 char *dest;
1044 &output_size, playing)) == NULL) 1035
1036 while ((dest = pcmbuf_request_voice_buffer(
1037 &out_count, playing)) == NULL)
1045 { 1038 {
1046 if (playing && audio_codec_loaded) 1039 if (playing && audio_codec_loaded)
1047 swap_codec(); 1040 swap_codec();
1048 else 1041 else
1049 yield(); 1042 yield();
1050 } 1043 }
1051 1044
1052 /* Get the real input_size for output_size bytes, guarding 1045 /* Get the real input_size for output_size bytes, guarding
1053 * against resampling buffer overflows. */ 1046 * against resampling buffer overflows. */
1054 input_size = dsp_input_size(output_size); 1047 inp_count = dsp_input_count(out_count);
1055 1048
1056 if (input_size <= 0) 1049 if (inp_count <= 0)
1057 { 1050 {
1058 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n", 1051 DEBUGF("Error: dsp_input_count(%ld=dsp_output_count(%ld))=%ld<=0\n",
1059 output_size, length, input_size); 1052 out_count, count, inp_count);
1060 /* If this happens, there are samples of codec data that don't 1053 /* If this happens, there are samples of codec data that don't
1061 * become a number of pcm samples, and something is broken */ 1054 * become a number of pcm samples, and something is broken */
1062 return false; 1055 return false;
1063 } 1056 }
1064 1057
1065 /* Input size has grown, no error, just don't write more than length */ 1058 /* Input size has grown, no error, just don't write more than length */
1066 if ((size_t)input_size > length) 1059 if (inp_count > count)
1067 input_size = length; 1060 inp_count = count;
1068 1061
1069 output_size = dsp_process(dest, src, input_size); 1062 out_count = dsp_process(dest, src, inp_count);
1070 1063
1071 if (playing) 1064 if (playing)
1072 { 1065 {
1073 pcmbuf_mix_voice(output_size); 1066 pcmbuf_mix_voice(out_count);
1074 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) && 1067 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1075 audio_codec_loaded) 1068 audio_codec_loaded)
1076 swap_codec(); 1069 swap_codec();
1077 } 1070 }
1078 else 1071 else
1079 pcmbuf_write_complete(output_size); 1072 pcmbuf_write_complete(out_count);
1080 1073
1081 length -= input_size; 1074 count -= inp_count;
1082 } 1075 }
1083 1076
1084 return true; 1077 return true;
1085} /* voice_pcmbuf_insert_split_callback */ 1078} /* voice_pcmbuf_insert_callback */
1086
1087static bool voice_pcmbuf_insert_callback(const char *buf, size_t length)
1088{
1089 /* TODO: The audiobuffer API should probably be updated, and be based on
1090 * pcmbuf_insert_split(). */
1091 long real_length = length;
1092
1093 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
1094 length /= 2; /* Length is per channel */
1095
1096 /* Second channel is only used for non-interleaved stereo. */
1097 return voice_pcmbuf_insert_split_callback(buf, buf + (real_length / 2),
1098 length);
1099}
1100 1079
1101static void* voice_get_memory_callback(size_t *size) 1080static void* voice_get_memory_callback(size_t *size)
1102{ 1081{
@@ -1321,30 +1300,22 @@ static void voice_thread(void)
1321#endif /* PLAYBACK_VOICE */ 1300#endif /* PLAYBACK_VOICE */
1322 1301
1323/* --- Codec thread --- */ 1302/* --- Codec thread --- */
1324 1303static bool codec_pcmbuf_insert_callback(
1325static bool codec_pcmbuf_insert_split_callback( 1304 const void *ch1, const void *ch2, int count)
1326 const void *ch1, const void *ch2, size_t length)
1327{ 1305{
1328 const char* src[2]; 1306 const char *src[2] = { ch1, ch2 };
1329 char *dest;
1330 long input_size;
1331 size_t output_size;
1332
1333 src[0] = ch1;
1334 src[1] = ch2;
1335
1336 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
1337 length *= 2; /* Length is per channel */
1338 1307
1339 while (length) 1308 while (count > 0)
1340 { 1309 {
1341 long est_output_size = dsp_output_size(length); 1310 int out_count = dsp_output_count(count);
1311 int inp_count;
1312 char *dest;
1313
1342 /* Prevent audio from a previous track from playing */ 1314 /* Prevent audio from a previous track from playing */
1343 if (ci.new_track || ci.stop_codec) 1315 if (ci.new_track || ci.stop_codec)
1344 return true; 1316 return true;
1345 1317
1346 while ((dest = pcmbuf_request_buffer(est_output_size, 1318 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1347 &output_size)) == NULL)
1348 { 1319 {
1349 sleep(1); 1320 sleep(1);
1350 if (ci.seek_time || ci.new_track || ci.stop_codec) 1321 if (ci.seek_time || ci.new_track || ci.stop_codec)
@@ -1353,24 +1324,24 @@ static bool codec_pcmbuf_insert_split_callback(
1353 1324
1354 /* Get the real input_size for output_size bytes, guarding 1325 /* Get the real input_size for output_size bytes, guarding
1355 * against resampling buffer overflows. */ 1326 * against resampling buffer overflows. */
1356 input_size = dsp_input_size(output_size); 1327 inp_count = dsp_input_count(out_count);
1357 1328
1358 if (input_size <= 0) 1329 if (inp_count <= 0)
1359 { 1330 {
1360 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n", 1331 DEBUGF("Error: dsp_input_count(%ld=dsp_output_count(%ld))=%ld<=0\n",
1361 output_size, length, input_size); 1332 out_count, count, inp_count);
1362 /* If this happens, there are samples of codec data that don't 1333 /* If this happens, there are samples of codec data that don't
1363 * become a number of pcm samples, and something is broken */ 1334 * become a number of pcm samples, and something is broken */
1364 return false; 1335 return false;
1365 } 1336 }
1366 1337
1367 /* Input size has grown, no error, just don't write more than length */ 1338 /* Input size has grown, no error, just don't write more than length */
1368 if ((size_t)input_size > length) 1339 if (inp_count > count)
1369 input_size = length; 1340 inp_count = count;
1370 1341
1371 output_size = dsp_process(dest, src, input_size); 1342 out_count = dsp_process(dest, src, inp_count);
1372 1343
1373 pcmbuf_write_complete(output_size); 1344 pcmbuf_write_complete(out_count);
1374 1345
1375#ifdef PLAYBACK_VOICE 1346#ifdef PLAYBACK_VOICE
1376 if ((voice_is_playing || voice_thread_start) 1347 if ((voice_is_playing || voice_thread_start)
@@ -1381,26 +1352,12 @@ static bool codec_pcmbuf_insert_split_callback(
1381 swap_codec(); 1352 swap_codec();
1382 } 1353 }
1383#endif 1354#endif
1384 1355
1385 length -= input_size; 1356 count -= inp_count;
1386 } 1357 }
1387 1358
1388 return true; 1359 return true;
1389} /* codec_pcmbuf_insert_split_callback */ 1360} /* codec_pcmbuf_insert_callback */
1390
1391static bool codec_pcmbuf_insert_callback(const char *buf, size_t length)
1392{
1393 /* TODO: The audiobuffer API should probably be updated, and be based on
1394 * pcmbuf_insert_split(). */
1395 long real_length = length;
1396
1397 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
1398 length /= 2; /* Length is per channel */
1399
1400 /* Second channel is only used for non-interleaved stereo. */
1401 return codec_pcmbuf_insert_split_callback(buf, buf + (real_length / 2),
1402 length);
1403}
1404 1361
1405static void* codec_get_memory_callback(size_t *size) 1362static void* codec_get_memory_callback(size_t *size)
1406{ 1363{
@@ -3523,7 +3480,6 @@ static void audio_playback_init(void)
3523 /* Initialize codec api. */ 3480 /* Initialize codec api. */
3524 ci.read_filebuf = codec_filebuf_callback; 3481 ci.read_filebuf = codec_filebuf_callback;
3525 ci.pcmbuf_insert = codec_pcmbuf_insert_callback; 3482 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3526 ci.pcmbuf_insert_split = codec_pcmbuf_insert_split_callback;
3527 ci.get_codec_memory = codec_get_memory_callback; 3483 ci.get_codec_memory = codec_get_memory_callback;
3528 ci.request_buffer = codec_request_buffer_callback; 3484 ci.request_buffer = codec_request_buffer_callback;
3529 ci.advance_buffer = codec_advance_buffer_callback; 3485 ci.advance_buffer = codec_advance_buffer_callback;
@@ -3543,7 +3499,6 @@ static void audio_playback_init(void)
3543 memset(&id3_voice, 0, sizeof(struct mp3entry)); 3499 memset(&id3_voice, 0, sizeof(struct mp3entry));
3544 ci_voice.read_filebuf = voice_filebuf_callback; 3500 ci_voice.read_filebuf = voice_filebuf_callback;
3545 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback; 3501 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3546 ci_voice.pcmbuf_insert_split = voice_pcmbuf_insert_split_callback;
3547 ci_voice.get_codec_memory = voice_get_memory_callback; 3502 ci_voice.get_codec_memory = voice_get_memory_callback;
3548 ci_voice.request_buffer = voice_request_buffer_callback; 3503 ci_voice.request_buffer = voice_request_buffer_callback;
3549 ci_voice.advance_buffer = voice_advance_buffer_callback; 3504 ci_voice.advance_buffer = voice_advance_buffer_callback;