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 = { 0, /* seek_time */ NULL, /* get_codec_memory */ NULL, /* pcmbuf_insert */ - NULL, /* pcmbuf_insert_split */ NULL, /* set_elapsed */ NULL, /* read_filebuf */ 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 @@ #define CODEC_ENC_MAGIC 0x52454E43 /* RENC */ /* increase this every time the api struct changes */ -#define CODEC_API_VERSION 12 +#define CODEC_API_VERSION 13 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any new function which are "waiting" at the end of the function table) */ -#define CODEC_MIN_API_VERSION 12 +#define CODEC_MIN_API_VERSION 13 /* codec return codes */ enum codec_status { @@ -133,8 +133,7 @@ struct codec_api { void* (*get_codec_memory)(size_t *size); /* Insert PCM data into audio buffer for playback. Playback will start automatically. */ - bool (*pcmbuf_insert)(const char *data, size_t length); - bool (*pcmbuf_insert_split)(const void *ch1, const void *ch2, size_t length); + bool (*pcmbuf_insert)(const void *ch1, const void *ch2, int count); /* Set song position in WPS (value in ms). */ void (*set_elapsed)(unsigned int value); 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; /* used outside liba52 */ static uint8_t buf[3840] IBSS_ATTR; -void output_audio(sample_t *samples) +static inline void output_audio(sample_t *samples) { - do { - ci->yield(); - } while (!ci->pcmbuf_insert_split(&samples[0], &samples[256], - 256*sizeof(sample_t))); + ci->pcmbuf_insert(&samples[0], &samples[256], 256); } void 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: /* Output the audio */ ci->yield(); - while (!ci->pcmbuf_insert_split(decoder->time_out[0], - decoder->time_out[1], - frame_info.samples * 2)) - { - ci->sleep(1); - } + ci->pcmbuf_insert(decoder->time_out[0], decoder->time_out[1], + frame_info.samples >> 1); /* Update the elapsed-time indicator */ 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: } } - /* 2 bytes per sample */ - while (!ci->pcmbuf_insert((char *)samples, sampleswritten*2)) - ci->yield(); + if (channels == 2) + sampleswritten >>= 1; /* make samples/channel */ + + ci->pcmbuf_insert(samples, NULL, sampleswritten); ci->set_elapsed( ((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) uint16_t sample_size = 0; uint32_t sample_rate = 0; uint32_t i; - size_t n, bufsize; + size_t n; + int bufcount; int endofstream; unsigned char *buf; uint8_t *aifbuf; @@ -229,25 +230,27 @@ next_track: samples[i/4] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13) |(aifbuf[i + 2]<<5)|(aifbuf[i + 3]>>3); } - bufsize = n; + bufcount = n >> 2; } else if (sample_size > 16) { for (i = 0; i < n; i += 3) { samples[i/3] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13) |(aifbuf[i + 2]<<5); } - bufsize = n*4/3; + bufcount = n/3; } else if (sample_size > 8) { for (i = 0; i < n; i += 2) samples[i/2] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13); - bufsize = n*2; + bufcount = n >> 1; } else { for (i = 0; i < n; i++) samples[i] = SE(aifbuf[i]) << 21; - bufsize = n*4; + bufcount = n; } - while (!ci->pcmbuf_insert((char *)samples, bufsize)) - ci->yield(); + if (num_channels == 2) + bufcount >>= 1; + + ci->pcmbuf_insert(samples, NULL, bufcount); ci->advance_buffer(n); 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) /* Output the audio */ ci->yield(); - while(!ci->pcmbuf_insert_split(outputbuffer[0], - outputbuffer[1], - samplesdecoded*sizeof(int32_t))) - ci->yield(); + ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded); /* Update the elapsed-time indicator */ 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) frame++; ci->yield(); - while(!ci->pcmbuf_insert_split((char*)&decoded0[fc.sample_skip], - (char*)&decoded1[fc.sample_skip], - (fc.blocksize-fc.sample_skip)*4)) { - ci->yield(); - } + ci->pcmbuf_insert(&decoded0[fc.sample_skip], &decoded1[fc.sample_skip], + fc.blocksize - fc.sample_skip); fc.sample_skip = 0; 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: loop we will need to process the final frame that was decoded. */ if (framelength > 0) { /* In case of a mono file, the second array will be ignored. */ - ci->pcmbuf_insert_split(&synth.pcm.samples[0][samples_to_skip], - &synth.pcm.samples[1][samples_to_skip], - framelength * 4); + ci->pcmbuf_insert(&synth.pcm.samples[0][samples_to_skip], + &synth.pcm.samples[1][samples_to_skip], + framelength); /* Only skip samples for the first frame added. */ samples_to_skip = 0; @@ -244,8 +244,8 @@ next_track: /* Finish the remaining decoded frame. Cut the required samples from the end. */ if (framelength > stop_skip) - ci->pcmbuf_insert_split(synth.pcm.samples[0], synth.pcm.samples[1], - (framelength - stop_skip) * 4); + ci->pcmbuf_insert(synth.pcm.samples[0], synth.pcm.samples[1], + framelength - stop_skip); stream.error = 0; 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: retval = CODEC_ERROR; goto done; } else { - while (!ci->pcmbuf_insert_split(sample_buffer, - sample_buffer + MPC_FRAME_LENGTH, - status*sizeof(MPC_SAMPLE_FORMAT))) - ci->yield(); + ci->pcmbuf_insert(sample_buffer, + sample_buffer + MPC_FRAME_LENGTH, + status); samplesdone += status; ci->set_elapsed(samplesdone/frequency); } 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: goto init_nsf; } - while (!ci->pcmbuf_insert((char *)samples, written)) - ci->yield(); - + ci->pcmbuf_insert(samples, NULL, written >> 1); } 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: /* Insert decoded samples in pcmbuf */ if (nsamples) { ci->yield(); - while (!ci->pcmbuf_insert_split((char*)(decoded0 + sc.nwrap), - (char*)(decoded1 + sc.nwrap), - 4*nsamples)) { - ci->yield(); - } + ci->pcmbuf_insert(decoded0 + sc.nwrap, decoded1 + sc.nwrap, + nsamples); /* Update the elapsed-time indicator */ 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: } } - while (!ci->pcmbuf_insert((char *)samples, CHUNK_SIZE*4)) - ci->yield(); + ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE); } 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: } else if (n < 0) { DEBUGF("Error decoding frame\n"); } else { - while (!ci->pcmbuf_insert_split(pcm[0], pcm[1], - n*sizeof(ogg_int32_t))) { - ci->sleep(1); - } + ci->pcmbuf_insert(pcm[0], pcm[1], n); ci->set_offset(ov_raw_tell(&vf)); ci->set_elapsed(ov_time_tell(&vf)); } 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) int bytespersample = 0; uint16_t bitspersample; uint32_t i; - size_t n, bufsize; + size_t n; + int bufcount; int endofstream; unsigned char *buf; uint8_t *wavbuf; @@ -466,34 +467,39 @@ next_track: (wavbuf[i + 1]<<5)|(wavbuf[i + 2]<<13)| (SE(wavbuf[i + 3])<<21); } - bufsize = n; + bufcount = n >> 2; } else if (bitspersample > 16) { for (i = 0; i < n; i += 3) { samples[i/3] = (wavbuf[i]<<5)| (wavbuf[i + 1]<<13)|(SE(wavbuf[i + 2])<<21); } - bufsize = n*4/3; + bufcount = n/3; } else if (bitspersample > 8) { for (i = 0; i < n; i += 2) { samples[i/2] = (wavbuf[i]<<13)|(SE(wavbuf[i + 1])<<21); } - bufsize = n*2; + bufcount = n >> 1; } else { for (i = 0; i < n; i++) { samples[i] = (wavbuf[i] - 0x80)<<21; } - bufsize = n*4; + bufcount = n; } + + if (channels == 2) + bufcount >>= 1; } else if (formattag == WAVE_FORMAT_ALAW || formattag == IBM_FORMAT_ALAW) { for (i = 0; i < n; i++) samples[i] = alaw2linear16[wavbuf[i]] << 13; - bufsize = n*4; + + bufcount = (channels == 2) ? (n >> 1) : n; } else if (formattag == WAVE_FORMAT_MULAW || formattag == IBM_FORMAT_MULAW) { for (i = 0; i < n; i++) samples[i] = ulaw2linear16[wavbuf[i]] << 13; - bufsize = n*4; + + bufcount = (channels == 2) ? (n >> 1) : n; } else if (formattag == WAVE_FORMAT_DVI_ADPCM) { unsigned int nblocks = chunksize/blockalign; @@ -508,15 +514,14 @@ next_track: goto done; } } - bufsize = nblocks*samplesperblock*channels*4; + bufcount = nblocks*samplesperblock; } else { DEBUGF("CODEC_ERROR: unsupported format %x\n", formattag); i = CODEC_ERROR; goto done; } - while (!ci->pcmbuf_insert((char *)samples, bufsize)) - ci->yield(); + ci->pcmbuf_insert(samples, NULL, bufcount); ci->advance_buffer(n); 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) if (ci->stop_codec || ci->new_track) break; - while (!ci->pcmbuf_insert ((char *) temp_buffer, nsamples * nchans * 4)) - ci->sleep (1); + ci->pcmbuf_insert (temp_buffer, NULL, nsamples); ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); 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 @@ #define WORD_FRACBITS 27 #define NATIVE_DEPTH 16 -#define SAMPLE_BUF_SIZE 256 -#define RESAMPLE_BUF_SIZE (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ +#define SAMPLE_BUF_COUNT 256 +#define RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ #define DEFAULT_GAIN 0x01000000 struct dsp_config @@ -116,8 +116,8 @@ static struct dsp_config *dsp; * of copying needed is minimized for that case. */ -static int32_t sample_buf[SAMPLE_BUF_SIZE] IBSS_ATTR; -static int32_t resample_buf[RESAMPLE_BUF_SIZE] IBSS_ATTR; +static int32_t sample_buf[SAMPLE_BUF_COUNT] IBSS_ATTR; +static int32_t resample_buf[RESAMPLE_BUF_COUNT] IBSS_ATTR; int sound_get_pitch(void) { @@ -139,14 +139,14 @@ void sound_set_pitch(int permille) */ static int convert_to_internal(const char* src[], int count, int32_t* dst[]) { - count = MIN(SAMPLE_BUF_SIZE / 2, count); + count = MIN(SAMPLE_BUF_COUNT / 2, count); if ((dsp->sample_depth <= NATIVE_DEPTH) || (dsp->stereo_mode == STEREO_INTERLEAVED)) { dst[0] = &sample_buf[0]; dst[1] = (dsp->stereo_mode == STEREO_MONO) - ? dst[0] : &sample_buf[SAMPLE_BUF_SIZE / 2]; + ? dst[0] : &sample_buf[SAMPLE_BUF_COUNT / 2]; } else { @@ -231,7 +231,7 @@ static void resampler_set_delta(int frequency) /* TODO: we really should have a separate set of resample functions for both mono and stereo to avoid all this internal branching and looping. */ -static long downsample(int32_t **dst, int32_t **src, int count, +static int downsample(int32_t **dst, int32_t **src, int count, struct resample_data *r) { long phase = r->phase; @@ -246,11 +246,14 @@ static long downsample(int32_t **dst, int32_t **src, int count, last_sample = r->last_sample[j]; /* Do we need last sample of previous frame for interpolation? */ if (pos > 0) - { last_sample = src[j][pos - 1]; - } - *d[j]++ = last_sample + FRACMUL((phase & 0xffff) << 15, - src[j][pos] - last_sample); + + /* Be sure starting position isn't passed the available data */ + if (pos < count) + *d[j]++ = last_sample + FRACMUL((phase & 0xffff) << 15, + src[j][pos] - last_sample); + else /* This is kinda nasty but works somewhat well for now */ + *d[j]++ = src[j][count - 1]; } phase += delta; @@ -316,7 +319,7 @@ static inline int resample(int32_t* src[], int count) if (dsp->frequency != NATIVE_FREQUENCY) { - int32_t* dst[2] = {&resample_buf[0], &resample_buf[RESAMPLE_BUF_SIZE / 2]}; + int32_t* dst[2] = {&resample_buf[0], &resample_buf[RESAMPLE_BUF_COUNT / 2]}; if (dsp->frequency < NATIVE_FREQUENCY) { @@ -619,7 +622,7 @@ static void apply_gain(int32_t* _src[], int _count) if (s0 != s1) { - d = &sample_buf[SAMPLE_BUF_SIZE / 2]; + d = &sample_buf[SAMPLE_BUF_COUNT / 2]; src[1] = d; s = *s1++; @@ -736,18 +739,17 @@ static void write_samples(short* dst, int32_t* src[], int count) } /* Process and convert src audio to dst based on the DSP configuration, - * reading size bytes of audio data. dst is assumed to be large enough; use - * dst_get_dest_size() to get the required size. src is an array of - * pointers; for mono and interleaved stereo, it contains one pointer to the - * start of the audio data; for non-interleaved stereo, it contains two - * pointers, one for each audio channel. Returns number of bytes written to - * dest. + * reading count number of audio samples. dst is assumed to be large + * enough; use dsp_output_count() to get the required number. src is an + * array of pointers; for mono and interleaved stereo, it contains one + * pointer to the start of the audio data and the other is ignored; for + * non-interleaved stereo, it contains two pointers, one for each audio + * channel. Returns number of bytes written to dst. */ -long dsp_process(char* dst, const char* src[], long size) +int dsp_process(char *dst, const char *src[], int count) { int32_t* tmp[2]; - long written = 0; - long factor; + int written = 0; int samples; #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) @@ -759,14 +761,12 @@ long dsp_process(char* dst, const char* src[], long size) dsp = &dsp_conf[current_codec]; - factor = (dsp->stereo_mode != STEREO_MONO) ? 2 : 1; - size /= dsp->sample_bytes * factor; dsp_set_replaygain(false); - while (size > 0) + while (count > 0) { - samples = convert_to_internal(src, size, tmp); - size -= samples; + samples = convert_to_internal(src, count, tmp); + count -= samples; apply_gain(tmp, samples); samples = resample(tmp, samples); if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO) @@ -780,85 +780,61 @@ long dsp_process(char* dst, const char* src[], long size) dst += samples * sizeof(short) * 2; yield(); } + #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) /* set old macsr again */ coldfire_set_macsr(old_macsr); #endif - return written * sizeof(short) * 2; + return written; } -/* Given size bytes of input data, calculate the maximum number of bytes of - * output data that would be generated (the calculation is not entirely - * exact and rounds upwards to be on the safe side; during resampling, - * the number of samples generated depends on the current state of the - * resampler). +/* Given count number of input samples, calculate the maximum number of + * samples of output data that would be generated (the calculation is not + * entirely exact and rounds upwards to be on the safe side; during + * resampling, the number of samples generated depends on the current state + * of the resampler). */ /* dsp_input_size MUST be called afterwards */ -long dsp_output_size(long size) +int dsp_output_count(int count) { dsp = &dsp_conf[current_codec]; - if (dsp->sample_depth > NATIVE_DEPTH) - { - size /= 2; - } - if (dsp->frequency != NATIVE_FREQUENCY) { - size = (long) ((((unsigned long) size * NATIVE_FREQUENCY) - + (dsp->frequency - 1)) / dsp->frequency); + count = (int)(((unsigned long)count * NATIVE_FREQUENCY + + (dsp->frequency - 1)) / dsp->frequency); } - /* round to the next multiple of 2 (these are shorts) */ - size = (size + 1) & ~1; + /* Now we have the resampled sample count which must not exceed + * RESAMPLE_BUF_COUNT/2 to avoid resample buffer overflow. One + * must call dsp_input_count() to get the correct input sample + * count. + */ + if (count > RESAMPLE_BUF_COUNT/2) + count = RESAMPLE_BUF_COUNT/2; - if (dsp->stereo_mode == STEREO_MONO) - { - size *= 2; - } - - /* now we have the size in bytes for two resampled channels, - * and the size in (short) must not exceed RESAMPLE_BUF_SIZE to - * avoid resample buffer overflow. One must call dsp_input_size() - * to get the correct input buffer size. */ - if (size > RESAMPLE_BUF_SIZE*2) - size = RESAMPLE_BUF_SIZE*2; - - return size; + return count; } -/* Given size bytes of output buffer, calculate number of bytes of input - * data that would be consumed in order to fill the output buffer. +/* Given count output samples, calculate number of input samples + * that would be consumed in order to fill the output buffer. */ -long dsp_input_size(long size) +int dsp_input_count(int count) { dsp = &dsp_conf[current_codec]; - - /* convert to number of output stereo samples. */ - size /= 2; - /* Mono means we need half input samples to fill the output buffer */ - if (dsp->stereo_mode == STEREO_MONO) - size /= 2; - - /* size is now the number of resampled input samples. Convert to + /* count is now the number of resampled input samples. Convert to original input samples. */ if (dsp->frequency != NATIVE_FREQUENCY) { /* Use the real resampling delta = - * (unsigned long) dsp->frequency * 65536 / NATIVE_FREQUENCY, and + * dsp->frequency * 65536 / NATIVE_FREQUENCY, and * round towards zero to avoid buffer overflows. */ - size = ((unsigned long)size * - resample_data[current_codec].delta) >> 16; + count = (int)(((unsigned long)count * + resample_data[current_codec].delta) >> 16); } - /* Convert back to bytes. */ - if (dsp->sample_depth > NATIVE_DEPTH) - size *= 4; - else - size *= 2; - - return size; + return count; } int 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 { #define DIV64(x, y, z) (long)(((long long)(x) << (z))/(y)) -long dsp_process(char *dest, const char *src[], long size); -long dsp_input_size(long size); -long dsp_output_size(long size); +int dsp_process(char *dest, const char *src[], int count); +int dsp_input_count(int count); +int dsp_output_count(int count); int dsp_stereo_mode(void); bool dsp_configure(int setting, void *value); void 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) return true; } -void* pcmbuf_request_buffer(size_t length, size_t *realsize) +void* pcmbuf_request_buffer(int *count) { if (crossfade_init) crossfade_start(); if (crossfade_active) { - *realsize = MIN(length, PCMBUF_MIX_CHUNK); + *count = MIN(*count, PCMBUF_MIX_CHUNK/4); return fadebuf; } else { - if(prepare_insert(length)) + if(prepare_insert(*count << 2)) { size_t audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; - *realsize = length; if (pcmbuf_size - audiobuffer_index >= PCMBUF_MIN_CHUNK) { /* Usual case, there's space here */ @@ -821,34 +820,31 @@ void* pcmbuf_request_buffer(size_t length, size_t *realsize) } else { - *realsize = 0; return NULL; } } } -void* pcmbuf_request_voice_buffer(size_t length, size_t *realsize, bool mix) +void* pcmbuf_request_voice_buffer(int *count, bool mix) { if (mix) { if (pcmbuf_read == NULL) { - *realsize = 0; return NULL; } else if (pcmbuf_mix_chunk || pcmbuf_read->link) { - *realsize = MIN(length, PCMBUF_MIX_CHUNK); + *count = MIN(*count, PCMBUF_MIX_CHUNK/4); return voicebuf; } else { - *realsize = 0; return NULL; } } else - return pcmbuf_request_buffer(length, realsize); + return pcmbuf_request_buffer(count); } bool pcmbuf_is_crossfade_active(void) @@ -856,8 +852,10 @@ bool pcmbuf_is_crossfade_active(void) return crossfade_active || crossfade_init; } -void pcmbuf_write_complete(size_t length) +void pcmbuf_write_complete(int count) { + size_t length = (size_t)(unsigned int)count << 2; + if (crossfade_active) { flush_crossfade(fadebuf, length); @@ -874,8 +872,10 @@ void pcmbuf_write_complete(size_t length) } #if 0 -bool pcmbuf_insert_buffer(char *buf, size_t length) +bool pcmbuf_insert_buffer(char *buf, int count) { + size_t length = (size_t)(unsigned int)count << 2; + if (crossfade_active) { flush_crossfade(buf, length); @@ -980,7 +980,7 @@ int pcmbuf_mix_free(void) return 100; } -void pcmbuf_mix_voice(size_t length) +void pcmbuf_mix_voice(int count) { short *ibuf = (short *)voicebuf; short *obuf; @@ -998,9 +998,9 @@ void pcmbuf_mix_voice(size_t length) obuf = (short *)pcmbuf_mix_chunk->addr; chunk_samples = pcmbuf_mix_chunk->size / 2; - length /= 2; + count <<= 1; - while (length-- > 0) { + while (count-- > 0) { int sample = *ibuf++; if (pcmbuf_mix_sample >= chunk_samples) { 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)); size_t pcmbuf_free(void); unsigned int pcmbuf_get_latency(void); void pcmbuf_set_low_latency(bool state); -void pcmbuf_write_complete(size_t length); -void* pcmbuf_request_buffer(size_t length, size_t *realsize); -void* pcmbuf_request_voice_buffer(size_t length, size_t *realsize, bool mix); +void pcmbuf_write_complete(int count); +void* pcmbuf_request_buffer(int *count); +void* pcmbuf_request_voice_buffer(int *count, bool mix); bool pcmbuf_is_crossfade_enabled(void); void pcmbuf_crossfade_enable(bool on_off); int pcmbuf_usage(void); int pcmbuf_mix_free(void); void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude); -void pcmbuf_mix_voice(size_t length); +void pcmbuf_mix_voice(int count); int pcmbuf_used_descs(void); int 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) #ifdef PLAYBACK_VOICE -static bool voice_pcmbuf_insert_split_callback( - const void *ch1, const void *ch2, size_t length) +static bool voice_pcmbuf_insert_callback( + const void *ch1, const void *ch2, int count) { - const char* src[2]; - char *dest; - long input_size; - size_t output_size; + const char *src[2] = { ch1, ch2 }; - src[0] = ch1; - src[1] = ch2; - - if (dsp_stereo_mode() == STEREO_NONINTERLEAVED) - length *= 2; /* Length is per channel */ - - while (length) + while (count > 0) { - long est_output_size = dsp_output_size(length); - - while ((dest = pcmbuf_request_voice_buffer(est_output_size, - &output_size, playing)) == NULL) + int out_count = dsp_output_count(count); + int inp_count; + char *dest; + + while ((dest = pcmbuf_request_voice_buffer( + &out_count, playing)) == NULL) { if (playing && audio_codec_loaded) swap_codec(); else yield(); } - + /* Get the real input_size for output_size bytes, guarding * against resampling buffer overflows. */ - input_size = dsp_input_size(output_size); + inp_count = dsp_input_count(out_count); - if (input_size <= 0) + if (inp_count <= 0) { - DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n", - output_size, length, input_size); + DEBUGF("Error: dsp_input_count(%ld=dsp_output_count(%ld))=%ld<=0\n", + out_count, count, inp_count); /* If this happens, there are samples of codec data that don't * become a number of pcm samples, and something is broken */ return false; } /* Input size has grown, no error, just don't write more than length */ - if ((size_t)input_size > length) - input_size = length; + if (inp_count > count) + inp_count = count; - output_size = dsp_process(dest, src, input_size); + out_count = dsp_process(dest, src, inp_count); if (playing) { - pcmbuf_mix_voice(output_size); + pcmbuf_mix_voice(out_count); if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) && audio_codec_loaded) swap_codec(); } else - pcmbuf_write_complete(output_size); + pcmbuf_write_complete(out_count); - length -= input_size; + count -= inp_count; } return true; -} /* voice_pcmbuf_insert_split_callback */ - -static bool voice_pcmbuf_insert_callback(const char *buf, size_t length) -{ - /* TODO: The audiobuffer API should probably be updated, and be based on - * pcmbuf_insert_split(). */ - long real_length = length; - - if (dsp_stereo_mode() == STEREO_NONINTERLEAVED) - length /= 2; /* Length is per channel */ - - /* Second channel is only used for non-interleaved stereo. */ - return voice_pcmbuf_insert_split_callback(buf, buf + (real_length / 2), - length); -} +} /* voice_pcmbuf_insert_callback */ static void* voice_get_memory_callback(size_t *size) { @@ -1321,30 +1300,22 @@ static void voice_thread(void) #endif /* PLAYBACK_VOICE */ /* --- Codec thread --- */ - -static bool codec_pcmbuf_insert_split_callback( - const void *ch1, const void *ch2, size_t length) +static bool codec_pcmbuf_insert_callback( + const void *ch1, const void *ch2, int count) { - const char* src[2]; - char *dest; - long input_size; - size_t output_size; + const char *src[2] = { ch1, ch2 }; - src[0] = ch1; - src[1] = ch2; - - if (dsp_stereo_mode() == STEREO_NONINTERLEAVED) - length *= 2; /* Length is per channel */ - - while (length) + while (count > 0) { - long est_output_size = dsp_output_size(length); + int out_count = dsp_output_count(count); + int inp_count; + char *dest; + /* Prevent audio from a previous track from playing */ if (ci.new_track || ci.stop_codec) return true; - while ((dest = pcmbuf_request_buffer(est_output_size, - &output_size)) == NULL) + while ((dest = pcmbuf_request_buffer(&out_count)) == NULL) { sleep(1); if (ci.seek_time || ci.new_track || ci.stop_codec) @@ -1353,24 +1324,24 @@ static bool codec_pcmbuf_insert_split_callback( /* Get the real input_size for output_size bytes, guarding * against resampling buffer overflows. */ - input_size = dsp_input_size(output_size); + inp_count = dsp_input_count(out_count); - if (input_size <= 0) + if (inp_count <= 0) { - DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n", - output_size, length, input_size); + DEBUGF("Error: dsp_input_count(%ld=dsp_output_count(%ld))=%ld<=0\n", + out_count, count, inp_count); /* If this happens, there are samples of codec data that don't * become a number of pcm samples, and something is broken */ return false; } /* Input size has grown, no error, just don't write more than length */ - if ((size_t)input_size > length) - input_size = length; + if (inp_count > count) + inp_count = count; - output_size = dsp_process(dest, src, input_size); + out_count = dsp_process(dest, src, inp_count); - pcmbuf_write_complete(output_size); + pcmbuf_write_complete(out_count); #ifdef PLAYBACK_VOICE if ((voice_is_playing || voice_thread_start) @@ -1381,26 +1352,12 @@ static bool codec_pcmbuf_insert_split_callback( swap_codec(); } #endif - - length -= input_size; + + count -= inp_count; } return true; -} /* codec_pcmbuf_insert_split_callback */ - -static bool codec_pcmbuf_insert_callback(const char *buf, size_t length) -{ - /* TODO: The audiobuffer API should probably be updated, and be based on - * pcmbuf_insert_split(). */ - long real_length = length; - - if (dsp_stereo_mode() == STEREO_NONINTERLEAVED) - length /= 2; /* Length is per channel */ - - /* Second channel is only used for non-interleaved stereo. */ - return codec_pcmbuf_insert_split_callback(buf, buf + (real_length / 2), - length); -} +} /* codec_pcmbuf_insert_callback */ static void* codec_get_memory_callback(size_t *size) { @@ -3523,7 +3480,6 @@ static void audio_playback_init(void) /* Initialize codec api. */ ci.read_filebuf = codec_filebuf_callback; ci.pcmbuf_insert = codec_pcmbuf_insert_callback; - ci.pcmbuf_insert_split = codec_pcmbuf_insert_split_callback; ci.get_codec_memory = codec_get_memory_callback; ci.request_buffer = codec_request_buffer_callback; ci.advance_buffer = codec_advance_buffer_callback; @@ -3543,7 +3499,6 @@ static void audio_playback_init(void) memset(&id3_voice, 0, sizeof(struct mp3entry)); ci_voice.read_filebuf = voice_filebuf_callback; ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback; - ci_voice.pcmbuf_insert_split = voice_pcmbuf_insert_split_callback; ci_voice.get_codec_memory = voice_get_memory_callback; ci_voice.request_buffer = voice_request_buffer_callback; ci_voice.advance_buffer = voice_advance_buffer_callback;