First commit of reworking voice to be mroe stable on swcodec

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9758 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Brandon Low 2006-04-22 14:40:13 +00:00
parent b5991b27ca
commit f3bc1efc49
16 changed files with 531 additions and 405 deletions

View File

@ -141,7 +141,6 @@ enum codec_status codec_start(struct codec_api *api)
ci->memset(iedata, 0, iend - iedata);
#endif
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_DITHER, (bool *)false);
ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_NONINTERLEAVED);
ci->configure(DSP_SET_SAMPLE_DEPTH, (long *)28);
@ -185,9 +184,11 @@ next_track:
a52_decode_data(filebuf, filebuf + n);
ci->advance_buffer(n);
}
retval = CODEC_OK;
if (ci->request_next_track())
goto next_track;
retval = CODEC_OK;
exit:
a52_free(state);
return retval;

View File

@ -63,7 +63,6 @@ enum codec_status codec_start(struct codec_api* api)
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16));
ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_DITHER, (bool *)false);
ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED);
ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(29));
@ -88,7 +87,7 @@ next_track:
if (!qtmovie_read(&input_stream, &demux_res)) {
LOGF("FAAD: Error initialising file\n");
err = CODEC_ERROR;
goto exit;
goto done;
}
/* initialise the sound converter */
@ -98,7 +97,7 @@ next_track:
if (!hDecoder) {
LOGF("FAAD: Error opening decoder\n");
err = CODEC_ERROR;
goto exit;
goto done;
}
NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(hDecoder);
@ -112,7 +111,7 @@ next_track:
if (err) {
LOGF("FAAD: Error initialising decoder: %d, type=%d\n", err,hDecoder->object_type);
err = CODEC_ERROR;
goto exit;
goto done;
}
ci->id3->frequency=s;
@ -142,7 +141,7 @@ next_track:
&sample_byte_size)) {
LOGF("AAC: Error in get_sample_info\n");
err = CODEC_ERROR;
goto exit;
goto done;
}
/* Request the required number of bytes from the input buffer */
@ -156,7 +155,7 @@ next_track:
if (frameInfo.error > 0) {
LOGF("FAAD: decoding error \"%s\"\n", NeAACDecGetErrorMessage(frameInfo.error));
err = CODEC_ERROR;
goto exit;
goto done;
}
/* Get the number of decoded samples */
@ -182,13 +181,14 @@ next_track:
i++;
}
err = CODEC_OK;
done:
LOGF("AAC: Decoded %d samples\n",samplesdone);
if (ci->request_next_track())
goto next_track;
err = CODEC_OK;
exit:
return err;
}

View File

@ -98,11 +98,11 @@ next_track:
buf = ci->request_buffer(&n, 1024);
if (n < 44) {
i = CODEC_ERROR;
goto exit;
goto done;
}
if ((memcmp(buf, "FORM", 4) != 0) || (memcmp(&buf[8], "AIFF", 4) != 0)) {
i = CODEC_ERROR;
goto exit;
goto done;
}
buf += 12;
@ -117,7 +117,7 @@ next_track:
if (i != 18) {
DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu != 18\n", i);
i = CODEC_ERROR;
goto exit;
goto done;
}
/* num_channels */
num_channels = ((buf[8]<<8)|buf[9]);
@ -130,7 +130,7 @@ next_track:
if (buf[16] != 0x40) {
DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n", i);
i = CODEC_ERROR;
goto exit;
goto done;
}
sample_rate = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1;
sample_rate = sample_rate >> (16 + 14 - buf[17]);
@ -140,7 +140,7 @@ next_track:
if (sample_size == 0) {
DEBUGF("CODEC_ERROR: unsupported chunk order\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
/* offset2snd */
offset2snd = ((buf[8]<<8)|buf[9]);
@ -161,7 +161,7 @@ next_track:
if (n < (i + 8)) {
DEBUGF("CODEC_ERROR: AIFF header size > 1024\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
n -= i + 8;
} /* while 'SSND' */
@ -169,21 +169,20 @@ next_track:
if (num_channels == 0) {
DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
if (numbytes == 0) {
DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
if (sample_size > 24) {
DEBUGF("CODEC_ERROR: PCM with more than 24 bits per sample "
"is unsupported\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency));
ci->configure(DSP_SET_SAMPLE_DEPTH, (long *)28);
@ -194,7 +193,7 @@ next_track:
} else {
DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
firstblockposn = 1024 - n;
@ -277,11 +276,12 @@ next_track:
ci->set_elapsed(bytesdone*1000LL/avgbytespersec);
}
i = CODEC_OK;
done:
if (ci->request_next_track())
goto next_track;
i = CODEC_OK;
exit:
return i;
}

View File

@ -64,7 +64,6 @@ enum codec_status codec_start(struct codec_api* api)
ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128));
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_DITHER, (bool *)false);
ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED);
ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(ALAC_OUTPUT_DEPTH-1));
@ -89,7 +88,7 @@ enum codec_status codec_start(struct codec_api* api)
if (!qtmovie_read(&input_stream, &demux_res)) {
LOGF("ALAC: Error initialising file\n");
retval = CODEC_ERROR;
goto exit;
goto done;
}
/* initialise the sound converter */
@ -121,7 +120,7 @@ enum codec_status codec_start(struct codec_api* api)
&sample_byte_size)) {
LOGF("ALAC: Error in get_sample_info\n");
retval = CODEC_ERROR;
goto exit;
goto done;
}
/* Request the required number of bytes from the input buffer */
@ -129,7 +128,7 @@ enum codec_status codec_start(struct codec_api* api)
buffer=ci->request_buffer(&n,sample_byte_size);
if (n!=sample_byte_size) {
retval = CODEC_ERROR;
goto exit;
goto done;
}
/* Decode one block - returned samples will be host-endian */
@ -156,13 +155,14 @@ enum codec_status codec_start(struct codec_api* api)
i++;
}
retval = CODEC_OK;
done:
LOGF("ALAC: Decoded %d samples\n",samplesdone);
if (ci->request_next_track())
goto next_track;
retval = CODEC_OK;
exit:
return retval;
}

View File

@ -224,7 +224,7 @@ enum codec_status codec_start(struct codec_api* api)
{
int8_t *buf;
FLACContext fc;
uint32_t samplesdone;
uint32_t samplesdone = 0;
uint32_t elapsedtime;
size_t bytesleft;
int consumed;
@ -244,7 +244,6 @@ enum codec_status codec_start(struct codec_api* api)
ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128));
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_DITHER, (bool *)false);
ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_NONINTERLEAVED);
ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(FLAC_OUTPUT_DEPTH-1));
@ -260,7 +259,7 @@ enum codec_status codec_start(struct codec_api* api)
if (!flac_init(&fc,ci->id3->first_frame_offset)) {
LOGF("FLAC: Error initialising codec\n");
retval = CODEC_ERROR;
goto exit;
goto done;
}
while (!*ci->taginfo_ready)
@ -292,7 +291,7 @@ enum codec_status codec_start(struct codec_api* api)
bytesleft,ci->yield)) < 0) {
LOGF("FLAC: Frame %d, error %d\n",frame,res);
retval = CODEC_ERROR;
goto exit;
goto done;
}
consumed=fc.gb.index/8;
frame++;
@ -312,12 +311,14 @@ enum codec_status codec_start(struct codec_api* api)
buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE);
}
retval = CODEC_OK;
done:
LOGF("FLAC: Decoded %d samples\n",samplesdone);
if (ci->request_next_track())
goto next_track;
retval = CODEC_OK;
exit:
return retval;
}

View File

@ -91,7 +91,7 @@ void init_mad(void)
/* this is the codec entry point */
enum codec_status codec_start(struct codec_api *api)
{
int status = CODEC_OK;
int status;
size_t size;
int file_end;
int frame_skip; /* samples to skip current frame */
@ -110,7 +110,6 @@ enum codec_status codec_start(struct codec_api *api)
/* Create a decoder instance */
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_DITHER, (bool *)false);
ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(MAD_F_FRACBITS));
ci->configure(DSP_SET_CLIP_MIN, (int *)-MAD_F_ONE);
@ -122,6 +121,7 @@ enum codec_status codec_start(struct codec_api *api)
* for gapless playback.
* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
next_track:
status = CODEC_OK;
init_mad();
@ -171,7 +171,7 @@ enum codec_status codec_start(struct codec_api *api)
ci->id3->first_frame_offset;
if (!ci->seek_buffer(newpos))
goto next_track;
break;
ci->seek_complete();
init_mad();
}
@ -192,7 +192,7 @@ enum codec_status codec_start(struct codec_api *api)
break;
/* Fill the buffer */
if (stream.next_frame)
if (stream.next_frame && stream.next_frame != stream.this_frame)
ci->advance_buffer_loc((void *)stream.next_frame);
else
ci->advance_buffer(size);

View File

@ -90,7 +90,6 @@ enum codec_status codec_start(struct codec_api *api)
ci->memset(iedata, 0, iend - iedata);
#endif
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_DITHER, (bool *)false);
ci->configure(DSP_SET_SAMPLE_DEPTH, (long *)(28));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (long *)(1024*16));
@ -113,7 +112,7 @@ next_track:
mpc_streaminfo_init(&info);
if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
retval = CODEC_ERROR;
goto exit;
goto done;
}
frequency = info.sample_freq;
ci->configure(DSP_SET_FREQUENCY, (long *)(long)info.sample_freq);
@ -127,7 +126,7 @@ next_track:
ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_MONO);
else {
retval = CODEC_ERROR;
goto exit;
goto done;
}
codec_set_replaygain(ci->id3);
@ -135,7 +134,7 @@ next_track:
mpc_decoder_setup(&decoder, &reader);
if (!mpc_decoder_initialize(&decoder, &info)) {
retval = CODEC_ERROR;
goto exit;
goto done;
}
/* This is the decoding loop. */
@ -171,7 +170,7 @@ next_track:
ci->yield();
if (status == (unsigned)(-1)) { /* decode error */
retval = CODEC_ERROR;
goto exit;
goto done;
} else {
while (!ci->pcmbuf_insert_split(sample_buffer,
sample_buffer + MPC_FRAME_LENGTH,
@ -181,11 +180,12 @@ next_track:
ci->set_elapsed(samplesdone/(frequency/1000));
}
} while (status != 0);
retval = CODEC_OK;
done:
if (ci->request_next_track())
goto next_track;
retval = CODEC_OK;
exit:
return retval;
}

View File

@ -63,7 +63,6 @@ enum codec_status codec_start(struct codec_api* api)
ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128));
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_DITHER, (bool *)false);
ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_NONINTERLEAVED);
ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(SHN_OUTPUT_DEPTH-1));
@ -146,7 +145,7 @@ seek_start:
if (res == FN_ERROR) {
LOGF("Shorten: shorten_decode_frames error (%d)\n", samplesdone);
return CODEC_ERROR;
break;
} else {
/* Insert decoded samples in pcmbuf */
if (nsamples) {

View File

@ -129,7 +129,6 @@ enum codec_status codec_start(struct codec_api *api)
rb->memset(iedata, 0, iend - iedata);
#endif
rb->configure(CODEC_DSP_ENABLE, (bool *)true);
rb->configure(DSP_DITHER, (bool *)false);
rb->configure(DSP_SET_SAMPLE_DEPTH, (long *)24);
rb->configure(DSP_SET_CLIP_MAX, (long *)((1 << 24) - 1));
@ -194,7 +193,7 @@ next_track:
} else {
//rb->logf("ov_open: %d", error);
error = CODEC_ERROR;
goto exit;
goto done;
}
if (rb->id3->offset) {
@ -224,7 +223,7 @@ next_track:
if (current_section != previous_section) {
if (!vorbis_set_codec_parameters(&vf)) {
error = CODEC_ERROR;
goto exit;
goto done;
} else {
previous_section = current_section;
}
@ -243,7 +242,9 @@ next_track:
rb->set_elapsed(ov_time_tell(&vf));
}
}
error = CODEC_OK;
done:
if (rb->request_next_track()) {
/* Clean things up for the next track */
vf.dataoffsets = NULL;
@ -255,7 +256,6 @@ next_track:
goto next_track;
}
error = CODEC_OK;
exit:
return error;
}

View File

@ -242,7 +242,6 @@ enum codec_status codec_start(struct codec_api *api)
ci->memset(iedata, 0, iend - iedata);
#endif
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_SET_SAMPLE_DEPTH, (long *)28);
ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*256));
@ -261,11 +260,11 @@ next_track:
buf = ci->request_buffer(&n, 1024);
if (n < 44) {
i = CODEC_ERROR;
goto exit;
goto done;
}
if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) {
i = CODEC_ERROR;
goto exit;
goto done;
}
buf += 12;
@ -281,7 +280,7 @@ next_track:
if (i < 16) {
DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", i);
i = CODEC_ERROR;
goto exit;
goto done;
}
/* wFormatTag */
formattag=buf[8]|(buf[9]<<8);
@ -309,7 +308,7 @@ next_track:
DEBUGF("CODEC_ERROR: dvi_adpcm is missing "
"SamplesPerBlock value\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
samplesperblock = buf[26]|(buf[27]<<8);
} else if (formattag == WAVE_FORMAT_EXTENSIBLE) {
@ -317,7 +316,7 @@ next_track:
DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is "
"missing extension\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
/* wValidBitsPerSample */
bitspersample = buf[26]|(buf[27]<<8);
@ -344,7 +343,7 @@ next_track:
if (n < (i + 8)) {
DEBUGF("CODEC_ERROR: WAVE header size > 1024\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
n -= i + 8;
}
@ -352,12 +351,12 @@ next_track:
if (channels == 0) {
DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
if (numbytes == 0) {
DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
if (formattag != WAVE_FORMAT_PCM && totalsamples == 0) {
/* This is non-fatal for some formats */
@ -368,7 +367,7 @@ next_track:
if (bitspersample != 8) {
DEBUGF("CODEC_ERROR: alaw and mulaw must have 8 bitspersample\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
bytespersample = channels;
}
@ -376,13 +375,13 @@ next_track:
&& bitspersample != 4 && bitspersample != 3) {
DEBUGF("CODEC_ERROR: dvi_adpcm must have 3 or 4 bitspersample\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
if (formattag == WAVE_FORMAT_PCM && bitspersample > 32) {
DEBUGF("CODEC_ERROR: pcm with more than 32 bitspersample "
"is unsupported\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency));
@ -393,7 +392,7 @@ next_track:
} else {
DEBUGF("CODEC_ERROR: more than 2 channels\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
if (totalsamples == 0) {
@ -406,7 +405,7 @@ next_track:
} else {
DEBUGF("CODEC_ERROR: cannot compute totalsamples\n");
i = CODEC_ERROR;
goto exit;
goto done;
}
}
@ -505,14 +504,14 @@ next_track:
samples + i*samplesperblock*channels,
&decodedsize) != CODEC_OK) {
i = CODEC_ERROR;
goto exit;
goto done;
}
}
bufsize = nblocks*samplesperblock*channels*4;
} else {
DEBUGF("CODEC_ERROR: unsupported format %x\n", formattag);
i = CODEC_ERROR;
goto exit;
goto done;
}
while (!ci->pcmbuf_insert((char *)samples, bufsize))
@ -524,11 +523,12 @@ next_track:
endofstream = 1;
ci->set_elapsed(bytesdone*1000LL/avgbytespersec);
}
i = CODEC_OK;
done:
if (ci->request_next_track())
goto next_track;
i = CODEC_OK;
exit:
return i;
}

View File

@ -75,7 +75,6 @@ enum codec_status codec_start(struct codec_api* api)
while (!*ci->taginfo_ready && !ci->stop_codec)
ci->sleep(1);
ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency));
codec_set_replaygain(ci->id3);
@ -84,7 +83,7 @@ enum codec_status codec_start(struct codec_api* api)
if (!wpc) {
retval = CODEC_ERROR;
goto exit;
goto done;
}
bps = WavpackGetBytesPerSample (wpc);
@ -143,11 +142,12 @@ enum codec_status codec_start(struct codec_api* api)
ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
ci->yield ();
}
retval = CODEC_OK;
done:
if (ci->request_next_track())
goto next_track;
retval = CODEC_OK;
exit:
return retval;
}

View File

@ -31,7 +31,6 @@
enum {
CODEC_SET_FILEBUF_WATERMARK = 1,
CODEC_SET_FILEBUF_CHUNKSIZE,
CODEC_DSP_ENABLE,
DSP_SET_FREQUENCY,
DSP_SWITCH_FREQUENCY,
DSP_SET_CLIP_MIN,

View File

@ -48,7 +48,8 @@ static size_t audiobuffer_pos IDATA_ATTR;
size_t audiobuffer_free IDATA_ATTR;
/* Amount audiobuffer_pos will be increased.*/
static size_t audiobuffer_fillpos IDATA_ATTR;
static char *guardbuf IDATA_ATTR;
static char *fadebuf IDATA_ATTR;
static char *voicebuf IDATA_ATTR;
static void (*pcmbuf_event_handler)(void) IDATA_ATTR;
static void (*position_callback)(size_t size) IDATA_ATTR;
@ -93,9 +94,9 @@ static struct pcmbufdesc *pcmbuf_write IDATA_ATTR;
static struct pcmbufdesc *pcmbuf_write_end IDATA_ATTR;
static size_t last_chunksize IDATA_ATTR;
static size_t pcmbuf_unplayed_bytes IDATA_ATTR;
static size_t pcmbuf_mix_used_bytes IDATA_ATTR;
static size_t pcmbuf_watermark IDATA_ATTR;
static short *mixpos IDATA_ATTR;
static struct pcmbufdesc *pcmbuf_mix_chunk IDATA_ATTR;
static size_t pcmbuf_mix_sample IDATA_ATTR;
static bool low_latency_mode = false;
/* Helpful macros for use in conditionals this assumes some of the above
@ -151,6 +152,10 @@ static void pcmbuf_callback(unsigned char** start, size_t* size)
/* Put the finished buffer back into circulation */
pcmbuf_write_end->link = pcmbuf_current;
pcmbuf_write_end = pcmbuf_current;
/* If we've read through the mix chunk while it's still mixing there */
if (pcmbuf_current == pcmbuf_mix_chunk)
pcmbuf_mix_chunk = NULL;
}
process_new_buffer:
@ -162,9 +167,10 @@ process_new_buffer:
if(pcmbuf_new)
{
size_t current_size = pcmbuf_new->size;
pcmbuf_unplayed_bytes -= current_size;
*realsize = current_size;
last_chunksize = current_size;
*realsize = current_size;
*realstart = pcmbuf_new->addr;
}
else
@ -219,14 +225,10 @@ static inline void pcmbuf_add_chunk(void)
/* Update bytes counters */
pcmbuf_unplayed_bytes += size;
if (pcmbuf_mix_used_bytes > size)
pcmbuf_mix_used_bytes -= size;
else
pcmbuf_mix_used_bytes = 0;
audiobuffer_pos += size;
if (audiobuffer_pos >= pcmbuf_size)
audiobuffer_pos = 0;
audiobuffer_pos -= pcmbuf_size;
audiobuffer_fillpos = 0;
}
@ -299,7 +301,7 @@ void pcmbuf_play_stop(void)
pcm_mute(false);
pcmbuf_unplayed_bytes = 0;
pcmbuf_mix_used_bytes = 0;
pcmbuf_mix_chunk = NULL;
if (pcmbuf_read) {
pcmbuf_write_end->link = pcmbuf_read;
pcmbuf_write_end = pcmbuf_read_end;
@ -351,9 +353,10 @@ void pcmbuf_init(size_t bufsize)
pcmbuf_size = bufsize;
pcmbuf_descsize = pcmbuf_descs()*sizeof(struct pcmbufdesc);
audiobuffer = (char *)&audiobuf[(audiobufend - audiobuf) -
(pcmbuf_size + PCMBUF_FADE_CHUNK + pcmbuf_descsize)];
guardbuf = &audiobuffer[pcmbuf_size];
pcmbuf_write = (struct pcmbufdesc *)(&guardbuf[PCMBUF_FADE_CHUNK]);
(pcmbuf_size + PCMBUF_MIX_CHUNK * 2 + pcmbuf_descsize)];
fadebuf = &audiobuffer[pcmbuf_size];
voicebuf = &fadebuf[PCMBUF_MIX_CHUNK];
pcmbuf_write = (struct pcmbufdesc *)(&voicebuf[PCMBUF_MIX_CHUNK]);
pcmbuf_init_pcmbuffers();
position_callback = NULL;
pcmbuf_event_handler = NULL;
@ -444,7 +447,7 @@ static void crossfade_process_buffer(size_t fade_in_delay,
/* Fade out the specified amount of the already processed audio */
size_t total_fade_out = fade_out_rem;
short *buf = (short *)&audiobuffer[crossfade_pos + fade_out_delay * 2];
short *buf_end = (short *)guardbuf;
short *buf_end = (short *)fadebuf;
/* Wrap the starting position if needed */
if (buf >= buf_end) buf -= pcmbuf_size / 2;
@ -738,8 +741,8 @@ void* pcmbuf_request_buffer(size_t length, size_t *realsize)
crossfade_start();
if (crossfade_active) {
*realsize = MIN(length, PCMBUF_FADE_CHUNK);
return &guardbuf[0];
*realsize = MIN(length, PCMBUF_MIX_CHUNK);
return fadebuf;
}
else
{
@ -772,8 +775,16 @@ void* pcmbuf_request_voice_buffer(size_t length, size_t *realsize, bool mix)
{
if (mix)
{
*realsize = MIN(length, PCMBUF_FADE_CHUNK);
return &guardbuf[0];
if (pcmbuf_mix_chunk || pcmbuf_read->link)
{
*realsize = MIN(length, PCMBUF_MIX_CHUNK);
return voicebuf;
}
else
{
*realsize = 0;
return NULL;
}
}
else
return pcmbuf_request_buffer(length, realsize);
@ -787,7 +798,7 @@ bool pcmbuf_is_crossfade_active(void)
void pcmbuf_write_complete(size_t length)
{
if (crossfade_active)
flush_crossfade(guardbuf, length);
flush_crossfade(fadebuf, length);
else
{
audiobuffer_free -= length;
@ -814,16 +825,16 @@ bool pcmbuf_insert_buffer(const char *buf, size_t length)
}
/* Get a pointer to where to mix immediate audio */
static inline short* get_mix_insert_pos(void) {
/* Give at least 1/8s clearance here */
size_t pcmbuf_mix_back_pos =
pcmbuf_unplayed_bytes - NATIVE_FREQUENCY * 4 / 8;
static inline short* get_mix_insert_buf(void) {
if (pcmbuf_read->link)
{
/* Get the next chunk */
char *pcmbuf_mix_buf = pcmbuf_read->link->addr;
if (audiobuffer_pos < pcmbuf_mix_back_pos)
return (short *)&audiobuffer[pcmbuf_size +
audiobuffer_pos - pcmbuf_mix_back_pos];
else
return (short *)&audiobuffer[audiobuffer_pos - pcmbuf_mix_back_pos];
/* Give at least 1/8s clearance. TODO: Check size here? */
return (short *)&pcmbuf_mix_buf[NATIVE_FREQUENCY * 4 / 8];
}
return NULL;
}
/* Generates a constant square wave sound with a given frequency
@ -834,12 +845,12 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude)
unsigned int interval = NATIVE_FREQUENCY / frequency;
long sample;
short *buf;
short *pcmbuf_end = (short *)guardbuf;
short *pcmbuf_end = (short *)fadebuf;
size_t samples = NATIVE_FREQUENCY / 1000 * duration;
if (pcm_is_playing())
{
buf = get_mix_insert_pos();
buf = get_mix_insert_buf();
while (i++ < samples)
{
sample = *buf;
@ -888,35 +899,56 @@ int pcmbuf_usage(void)
return pcmbuf_unplayed_bytes * 100 / pcmbuf_size;
}
int pcmbuf_mix_usage(void)
int pcmbuf_mix_free(void)
{
return pcmbuf_mix_used_bytes * 100 / pcmbuf_unplayed_bytes;
if (pcmbuf_mix_chunk)
{
size_t my_mix_end =
(size_t)&((short *)pcmbuf_mix_chunk->addr)[pcmbuf_mix_sample];
size_t my_write_pos = (size_t)&audiobuffer[audiobuffer_pos];
if (my_write_pos < my_mix_end)
my_write_pos += pcmbuf_size;
return (my_write_pos - my_mix_end) * 100 / pcmbuf_unplayed_bytes;
}
return 100;
}
void pcmbuf_reset_mixpos(void)
/* This function does not check for writing over the current main insertion
* point of the pcm buffer (audiobuffer_fillpos) so that must be checked by
* the caller */
void pcmbuf_mix_voice(size_t length)
{
mixpos = get_mix_insert_pos();
pcmbuf_mix_used_bytes = 0;
}
short *ibuf = (short *)voicebuf;
short *obuf;
size_t chunk_samples;
void pcmbuf_mix(char *buf, size_t length)
{
short *ibuf = (short *)buf;
short *pcmbuf_end = (short *)guardbuf;
if (!pcmbuf_mix_chunk && pcmbuf_read)
{
pcmbuf_mix_chunk = pcmbuf_read->link;
/* Start 1/8s into the next chunk */
pcmbuf_mix_sample = NATIVE_FREQUENCY * 4 / 16;
}
if (!pcmbuf_mix_chunk)
return;
if (pcmbuf_mix_used_bytes == 0)
pcmbuf_reset_mixpos();
obuf = (short *)pcmbuf_mix_chunk->addr;
chunk_samples = pcmbuf_mix_chunk->size / 2;
pcmbuf_mix_used_bytes += length;
length /= 2;
while (length-- > 0) {
long sample = *ibuf++;
sample += *mixpos >> 2;
*mixpos++ = MIN(MAX(sample, -32768), 32767);
if (mixpos >= pcmbuf_end)
mixpos = (short *)audiobuffer;
if (pcmbuf_mix_sample >= chunk_samples)
{
pcmbuf_mix_chunk = pcmbuf_mix_chunk->link;
if (!pcmbuf_mix_chunk)
return;
pcmbuf_mix_sample = 0;
obuf = pcmbuf_mix_chunk->addr;
chunk_samples = pcmbuf_mix_chunk->size / 2;
}
sample += obuf[pcmbuf_mix_sample];
obuf[pcmbuf_mix_sample++] = MIN(MAX(sample, -32768), 32767);
}
}

View File

@ -27,7 +27,7 @@
non-fatal) */
#define PCMBUF_MIN_CHUNK 4096 /* We try to never feed a chunk smaller than
this to the DMA */
#define PCMBUF_FADE_CHUNK 8192 /* This is the maximum size of one packet
#define PCMBUF_MIX_CHUNK 8192 /* This is the maximum size of one packet
for mixing (crossfade or voice) */
/* Returns true if the buffer needs to change size */
@ -64,10 +64,9 @@ bool pcmbuf_is_crossfade_enabled(void);
void pcmbuf_crossfade_enable(bool on_off);
int pcmbuf_usage(void);
int pcmbuf_mix_usage(void);
int pcmbuf_mix_free(void);
void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude);
void pcmbuf_reset_mixpos(void);
void pcmbuf_mix(char *buf, size_t length);
void pcmbuf_mix_voice(size_t length);
int pcmbuf_used_descs(void);
int pcmbuf_descs(void);

File diff suppressed because it is too large Load Diff

View File

@ -629,11 +629,6 @@ void mp3_shutdown(void)
/* a dummy */
}
void mp3_play_stop(void)
{
/* a dummy */
}
void mp3_play_pause(bool play)
{
/* a dummy */