From 874c91146402df8a47718e327558e8ceab0b482c Mon Sep 17 00:00:00 2001 From: Jeffrey Goode Date: Mon, 9 Nov 2009 18:12:20 +0000 Subject: pcmbuf: refactoring git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23592 a1c6a512-1295-4272-9138-f99709370657 --- apps/pcmbuf.c | 207 +++++++++++++++++++++++++++------------------------------- 1 file changed, 98 insertions(+), 109 deletions(-) (limited to 'apps') diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index cda20d9f48..02c307df72 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -68,10 +68,8 @@ struct chunkdesc bool end_of_track; }; -#define CHUNK_DESCS(bufsize) \ +#define NUM_CHUNK_DESCS(bufsize) \ ((bufsize) / PCMBUF_MINAVG_CHUNK) -#define CHUNK_DESCS_SIZE(bufsize) \ - (CHUNK_DESCS(bufsize)*sizeof(struct chunkdesc)) /* Size of the PCM buffer. */ static size_t pcmbuf_size IDATA_ATTR = 0; @@ -132,7 +130,6 @@ extern unsigned int codec_thread_id; #define LOW_DATA(quarter_secs) \ (pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs) -static void finish_gapless_track_change(void); #ifdef HAVE_CROSSFADE static void crossfade_start(void); static void flush_crossfade(char *buf, size_t length); @@ -432,22 +429,17 @@ static size_t get_next_required_pcmbuf_size(void) return seconds * (NATIVE_FREQUENCY*4); /* 2 channels + 2 bytes/sample */ } -static char *pcmbuf_calc_pcmbuffer_ptr(size_t bufsize) -{ - return pcmbuf_bufend - (bufsize + PCMBUF_MIX_CHUNK * 2 + - CHUNK_DESCS_SIZE(bufsize)); -} - /* Initialize the pcmbuffer the structure looks like this: * ...|---------PCMBUF---------|FADEBUF|VOICEBUF|DESCS|... */ size_t pcmbuf_init(unsigned char *bufend) { pcmbuf_bufend = bufend; pcmbuf_size = get_next_required_pcmbuf_size(); - pcmbuffer = pcmbuf_calc_pcmbuffer_ptr(pcmbuf_size); - fadebuf = &pcmbuffer[pcmbuf_size]; - voicebuf = &fadebuf[PCMBUF_MIX_CHUNK]; - write_chunk = (struct chunkdesc *)&voicebuf[PCMBUF_MIX_CHUNK]; + write_chunk = (struct chunkdesc *)pcmbuf_bufend - + NUM_CHUNK_DESCS(pcmbuf_size); + voicebuf = (char *)write_chunk - PCMBUF_MIX_CHUNK; + fadebuf = voicebuf - PCMBUF_MIX_CHUNK; + pcmbuffer = fadebuf - pcmbuf_size; init_pcmbuffers(); @@ -463,6 +455,91 @@ size_t pcmbuf_init(unsigned char *bufend) } +/* Track change */ + +/* The codec is moving on to the next track, but the current track is + * still playing. Set flags to make sure the elapsed time of the current + * track is updated properly, and mark the currently written chunk as the + * last one in the track. */ +static void start_gapless_track_change(void) +{ + /* we're starting a track transition */ + track_transition = true; + + /* mark the last chunk in the track */ + end_of_track = true; +} + +static void start_crossfade_track_change(bool auto_skip) +{ + /* Notify the wps that the track change starts now */ + audio_post_track_change(false); + + /* Can't do two crossfades at once and, no fade if pcm is off now */ + if (pcmbuf_is_crossfade_active() || !pcm_is_playing()) + { + pcmbuf_play_stop(); + return; + } + + trigger_cpu_boost(); + + /* Not enough data, or crossfade disabled, flush the old data instead */ + if (LOW_DATA(2) || !pcmbuf_is_crossfade_enabled() || low_latency_mode) + { + /* commit everything to this point and keep going, but... */ + commit_chunk(); + /* ... when the next chunk commits, throw away everything but itself */ + flush_pcmbuf = true; + return; + } + + /* Don't enable mix mode when skipping tracks manually. */ + crossfade_mixmode = auto_skip && global_settings.crossfade_fade_out_mixmode; + + crossfade_track_change_started = true; +} + +void pcmbuf_start_track_change(bool auto_skip) +{ + /* Manual track change (always crossfade or flush audio). */ + if (!auto_skip) + start_crossfade_track_change(false); + + /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */ + else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active() + && global_settings.crossfade != CROSSFADE_ENABLE_TRACKSKIP) + { + if (global_settings.crossfade == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP) + { + if (global_settings.playlist_shuffle) + /* shuffle mode is on, so crossfade: */ + start_crossfade_track_change(true); + else + /* shuffle mode is off, so normal gapless playback */ + start_gapless_track_change(); + } + else + /* normal crossfade: */ + start_crossfade_track_change(true); + } + else + /* normal gapless playback. */ + start_gapless_track_change(); +} + +/* Called when the last chunk in the track has been played */ +static void finish_gapless_track_change(void) +{ + /* not in a track transition anymore */ + if(track_transition){logf("pcmbuf: (finish change) track transition false");} + track_transition = false; + + /* notify playback that the track has just finished */ + audio_post_track_change(true); +} + + /* Playback */ /** PCM driver callback @@ -512,24 +589,21 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size) { /* Send the new buffer to the pcm */ - struct chunkdesc *pcmbuf_new = read_chunk; - size_t *realsize = size; - unsigned char** realstart = start; - if(pcmbuf_new) + if(read_chunk) { - size_t current_size = pcmbuf_new->size; + size_t current_size = read_chunk->size; pcmbuf_unplayed_bytes -= current_size; last_chunksize = current_size; - *realsize = current_size; - *realstart = pcmbuf_new->addr; + *size = current_size; + *start = read_chunk->addr; } else { /* No more buffers */ last_chunksize = 0; - *realsize = 0; - *realstart = NULL; + *size = 0; + *start = NULL; if (end_of_track) finish_gapless_track_change(); } @@ -580,91 +654,6 @@ void pcmbuf_pause(bool pause) } -/* Track change */ - -/* The codec is moving on to the next track, but the current track is - * still playing. Set flags to make sure the elapsed time of the current - * track is updated properly, and mark the currently written chunk as the - * last one in the track. */ -static void start_gapless_track_change(void) -{ - /* we're starting a track transition */ - track_transition = true; - - /* mark the last chunk in the track */ - end_of_track = true; -} - -static void start_crossfade_track_change(bool auto_skip) -{ - /* Notify the wps that the track change starts now */ - audio_post_track_change(false); - - /* Can't do two crossfades at once and, no fade if pcm is off now */ - if (pcmbuf_is_crossfade_active() || !pcm_is_playing()) - { - pcmbuf_play_stop(); - return; - } - - trigger_cpu_boost(); - - /* Not enough data, or crossfade disabled, flush the old data instead */ - if (LOW_DATA(2) || !pcmbuf_is_crossfade_enabled() || low_latency_mode) - { - /* commit everything to this point and keep going, but... */ - commit_chunk(); - /* ... when the next chunk commits, throw away everything but itself */ - flush_pcmbuf = true; - return; - } - - /* Don't enable mix mode when skipping tracks manually. */ - crossfade_mixmode = auto_skip && global_settings.crossfade_fade_out_mixmode; - - crossfade_track_change_started = true; -} - -void pcmbuf_start_track_change(bool auto_skip) -{ - /* Manual track change (always crossfade or flush audio). */ - if (!auto_skip) - start_crossfade_track_change(false); - - /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */ - else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active() - && global_settings.crossfade != CROSSFADE_ENABLE_TRACKSKIP) - { - if (global_settings.crossfade == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP) - { - if (global_settings.playlist_shuffle) - /* shuffle mode is on, so crossfade: */ - start_crossfade_track_change(true); - else - /* shuffle mode is off, so normal gapless playback */ - start_gapless_track_change(); - } - else - /* normal crossfade: */ - start_crossfade_track_change(true); - } - else - /* normal gapless playback. */ - start_gapless_track_change(); -} - -/* Called when the last chunk in the track has been played */ -static void finish_gapless_track_change(void) -{ - /* not in a track transition anymore */ - if(track_transition){logf("pcmbuf: (finish change) track transition false");} - track_transition = false; - - /* notify playback that the track has just finished */ - audio_post_track_change(true); -} - - /* Crossfade */ /* Clip sample to signed 16 bit range */ @@ -1095,7 +1084,7 @@ int pcmbuf_used_descs(void) int pcmbuf_descs(void) { - return CHUNK_DESCS(pcmbuf_size); + return NUM_CHUNK_DESCS(pcmbuf_size); } #ifdef ROCKBOX_HAS_LOGF -- cgit v1.2.3