From 6c0908b4160838142225c5b570036c4d98de4ece Mon Sep 17 00:00:00 2001 From: Brandon Low Date: Sun, 23 Apr 2006 22:54:34 +0000 Subject: [PATCH] Rework crossfade to properly follow pcmbuf chunks instaed of blindly inserting into the ring buffer git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9780 a1c6a512-1295-4272-9138-f99709370657 --- apps/debug_menu.c | 5 +- apps/pcmbuf.c | 453 ++++++++++++++++++++++------------------------ apps/pcmbuf.h | 6 +- 3 files changed, 223 insertions(+), 241 deletions(-) diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 9c8fdcd404..1bbf99d6e1 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -208,7 +208,6 @@ bool dbg_audio_thread(void) return false; } #else /* CONFIG_CODEC == SWCODEC */ -extern size_t audiobuffer_free; extern size_t filebuflen; /* This is a size_t, but call it a long so it puts a - when it's bad. */ extern long filebufused; @@ -260,12 +259,12 @@ bool dbg_audio_thread(void) lcd_clear_display(); snprintf(buf, sizeof(buf), "pcm: %7ld/%7ld", - bufsize-audiobuffer_free, bufsize); + bufsize-pcmbuf_free(), bufsize); lcd_puts(0, line++, buf); /* Playable space left */ scrollbar(0, line*8, LCD_WIDTH, 6, bufsize, 0, - bufsize-audiobuffer_free, HORIZONTAL); + bufsize-pcmbuf_free(), HORIZONTAL); line++; snprintf(buf, sizeof(buf), "codec: %8ld/%8ld", filebufused, filebuflen); diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 0c12790389..ff7d4cfa82 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -38,44 +38,6 @@ #define PCMBUF_WATERMARK (NATIVE_FREQUENCY * 4 * 1) -/* Size of the PCM buffer. */ -static size_t pcmbuf_size IDATA_ATTR = 0; - -static char *audiobuffer IDATA_ATTR; -/* Current audio buffer write index. */ -static size_t audiobuffer_pos IDATA_ATTR; -/* Amount of bytes left in the buffer. */ -size_t audiobuffer_free IDATA_ATTR; -/* Amount audiobuffer_pos will be increased.*/ -static size_t audiobuffer_fillpos 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; - -/* Crossfade related. */ -static int crossfade_mode IDATA_ATTR; -static bool crossfade_enabled IDATA_ATTR; -static bool crossfade_active IDATA_ATTR; -static bool crossfade_init IDATA_ATTR; -static size_t crossfade_pos IDATA_ATTR; -static size_t crossfade_rem IDATA_ATTR; - -/* Crossfade modes. If CFM_CROSSFADE is selected, normal - * crossfader will activate. Selecting CFM_FLUSH is a special - * operation that only overwrites the pcm buffer without crossfading. - */ -enum { - CFM_CROSSFADE, - CFM_MIX, - CFM_FLUSH -}; - -static size_t crossfade_fade_in_amount IDATA_ATTR; -static size_t crossfade_fade_in_rem IDATA_ATTR; - - /* Structure we can use to queue pcm chunks in memory to be played * by the driver code. */ struct pcmbufdesc @@ -87,17 +49,61 @@ struct pcmbufdesc void (*callback)(void); }; +/* Size of the PCM buffer. */ +static size_t pcmbuf_size IDATA_ATTR = 0; + +static char *audiobuffer IDATA_ATTR; +/* Current audio buffer write index. */ +static size_t audiobuffer_pos IDATA_ATTR; +/* Amount audiobuffer_pos will be increased.*/ +static size_t audiobuffer_fillpos 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; + +/* Crossfade related state */ +static bool crossfade_enabled; +static bool crossfade_mix; +static bool crossfade_active IDATA_ATTR; +static bool crossfade_init IDATA_ATTR; + +/* Track the current location for processing crossfade */ +static struct pcmbufdesc *crossfade_chunk IDATA_ATTR; +static size_t crossfade_sample IDATA_ATTR; + +/* Counters for fading in new data */ +static size_t crossfade_fade_in_total IDATA_ATTR; +static size_t crossfade_fade_in_rem IDATA_ATTR; + static size_t pcmbuf_descsize; static struct pcmbufdesc *pcmbuf_read IDATA_ATTR; static struct pcmbufdesc *pcmbuf_read_end IDATA_ATTR; static struct pcmbufdesc *pcmbuf_write IDATA_ATTR; static struct pcmbufdesc *pcmbuf_write_end IDATA_ATTR; static size_t last_chunksize IDATA_ATTR; +/* +static inline size_t pcmbuf_unplayed_bytes(void) +{ + size_t bytes = 0; + if (pcmbuf_read) + { + struct pcmbufdesc *pcmbuf_chunk = pcmbuf_read; + do + { + bytes += pcmbuf_chunk->size; + pcmbuf_chunk = pcmbuf_chunk->link; + } while (pcmbuf_chunk); + } + return bytes; +} */ static size_t pcmbuf_unplayed_bytes IDATA_ATTR; static size_t pcmbuf_watermark IDATA_ATTR; static struct pcmbufdesc *pcmbuf_mix_chunk IDATA_ATTR; static size_t pcmbuf_mix_sample IDATA_ATTR; static bool low_latency_mode = false; +static bool pcmbuf_flush; /* Helpful macros for use in conditionals this assumes some of the above * static variable names */ @@ -106,7 +112,6 @@ static bool low_latency_mode = false; #define LOW_DATA(quarter_secs) \ (pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs) -static void pcmbuf_flush_audio(void); static void pcmbuf_under_watermark(void); static bool pcmbuf_flush_fillpos(void); @@ -140,13 +145,8 @@ static void pcmbuf_callback(unsigned char** start, size_t* size) /* Take the finished buffer out of circulation */ pcmbuf_read = pcmbuf_current->link; - { - size_t finished_size = last_chunksize; - audiobuffer_free += finished_size; - - /* The buffer is finished, call the callback functions */ - CALL_IF_EXISTS(position_callback, finished_size); - } + /* The buffer is finished, call the callback functions */ + CALL_IF_EXISTS(position_callback, last_chunksize); CALL_IF_EXISTS(pcmbuf_current->callback); /* Put the finished buffer back into circulation */ @@ -214,8 +214,20 @@ static inline void pcmbuf_add_chunk(void) /* This is single use only */ pcmbuf_event_handler = NULL; if (pcmbuf_read) { + if (pcmbuf_flush) + { + pcmbuf_write_end->link = pcmbuf_read->link; + pcmbuf_read->link = pcmbuf_current; + while (pcmbuf_write_end->link) + { + pcmbuf_write_end = pcmbuf_write_end->link; + pcmbuf_unplayed_bytes -= pcmbuf_write_end->size; + } + pcmbuf_flush = false; + } /* If there is already a read buffer setup, add to it */ - pcmbuf_read_end->link = pcmbuf_current; + else + pcmbuf_read_end->link = pcmbuf_current; } else { /* Otherwise create the buffer */ pcmbuf_read = pcmbuf_current; @@ -238,7 +250,7 @@ static void pcmbuf_under_watermark(void) /* Fill audio buffer by boosting cpu */ pcmbuf_boost(true); /* Disable crossfade if < .5s of audio */ - if (LOW_DATA(2) && crossfade_mode != CFM_FLUSH) + if (LOW_DATA(2)) crossfade_active = false; } @@ -269,23 +281,43 @@ bool pcmbuf_is_lowdata(void) return LOW_DATA(2); } +/* Amount of bytes left in the buffer. */ +inline size_t pcmbuf_free(void) +{ + if (pcmbuf_read) + { + size_t read = (size_t)pcmbuf_read->addr; + size_t write = + (size_t)&audiobuffer[audiobuffer_pos + audiobuffer_fillpos]; + if (read < write) + read += pcmbuf_size; + return read - write; + } + return pcmbuf_size; +} + bool pcmbuf_crossfade_init(bool manual_skip) { - if (pcmbuf_unplayed_bytes < PCMBUF_TARGET_CHUNK * 8 - || !pcmbuf_is_crossfade_enabled() - || crossfade_active || crossfade_init || low_latency_mode) { - pcmbuf_flush_audio(); + /* Can't do two crossfades at once and, no fade if pcm is off now */ + if (crossfade_init || crossfade_active || !pcm_is_playing()) + { + pcmbuf_play_stop(); return false; } + + /* Not enough data, or crossfade disabled, flush the old data instead */ + if (LOW_DATA(6) || !pcmbuf_is_crossfade_enabled() || low_latency_mode) + { + pcmbuf_boost(true); + pcmbuf_flush = true; + return false; + } + logf("pcmbuf_crossfade_init"); pcmbuf_boost(true); /* Don't enable mix mode when skipping tracks manually. */ - if (manual_skip) - crossfade_mode = CFM_CROSSFADE; - else - crossfade_mode = global_settings.crossfade_fade_out_mixmode - ? CFM_MIX : CFM_CROSSFADE; + crossfade_mix = manual_skip && global_settings.crossfade_fade_out_mixmode; crossfade_init = true; return true; @@ -309,9 +341,9 @@ void pcmbuf_play_stop(void) } audiobuffer_pos = 0; audiobuffer_fillpos = 0; - audiobuffer_free = pcmbuf_size; crossfade_init = false; crossfade_active = false; + pcmbuf_flush = false; pcmbuf_boost(false); @@ -328,7 +360,7 @@ int pcmbuf_used_descs(void) { } int pcmbuf_descs(void) { - return pcmbuf_size / PCMBUF_MINAVG_CHUNK; + return pcmbuf_size / PCMBUF_TARGET_CHUNK; } size_t get_pcmbuf_descsize(void) { @@ -368,21 +400,6 @@ size_t pcmbuf_get_bufsize(void) return pcmbuf_size; } -/** Initialize a track switch so that audio playback will not stop but - * the switch to next track would happen as soon as possible. - */ -static void pcmbuf_flush_audio(void) -{ - if (crossfade_init || crossfade_active || !pcm_is_playing()) { - pcmbuf_play_stop(); - return ; - } - - pcmbuf_boost(true); - crossfade_mode = CFM_FLUSH; - crossfade_init = true; -} - void pcmbuf_pause(bool pause) { if (pause) pcm_mute(true); @@ -442,60 +459,67 @@ static bool pcmbuf_flush_fillpos(void) static void crossfade_process_buffer(size_t fade_in_delay, size_t fade_out_delay, size_t fade_out_rem) { - if (crossfade_mode == CFM_CROSSFADE) + if (!crossfade_mix) { /* 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 *)fadebuf; - - /* Wrap the starting position if needed */ - if (buf >= buf_end) buf -= pcmbuf_size / 2; + size_t fade_out_sample; + struct pcmbufdesc *fade_out_chunk = crossfade_chunk; + /* Find the right chunk to start fading out */ + while (fade_out_delay >= fade_out_chunk->size) + { + fade_out_delay -= fade_out_chunk->size; + fade_out_chunk = fade_out_chunk->link; + } + /* The start sample within the chunk */ + fade_out_sample = fade_out_delay / 2; + while (fade_out_rem > 0) { /* Each 1/10 second of audio will have the same fade applied */ size_t block_rem = MIN(NATIVE_FREQUENCY * 2 / 10, fade_out_rem); - unsigned int factor = (fade_out_rem << 8) / total_fade_out; - short *block_end = buf + block_rem; + int factor = (fade_out_rem << 8) / total_fade_out; fade_out_rem -= block_rem; /* Fade this block */ - while (buf < block_end) + while (block_rem > 0) { /* Fade one sample */ - *buf = (*buf * factor) >> 8; - buf++; + short *buf = (short *)(fade_out_chunk->addr); + int sample = buf[fade_out_sample]; + buf[fade_out_sample++] = (sample * factor) >> 8; - if (buf >= buf_end) + block_rem--; + /* Move to the next chunk as needed */ + if (fade_out_sample * 2 >= fade_out_chunk->size) { - /* Wrap the pcmbuffer */ - buf -= pcmbuf_size / 2; - /* Wrap the end pointer to ensure proper termination */ - block_end -= pcmbuf_size / 2; + fade_out_chunk = fade_out_chunk->link; + fade_out_sample = 0; } } } } - /* And finally set the mixing position where we should start fading in. */ - crossfade_rem -= fade_in_delay; - crossfade_pos += fade_in_delay*2; - if (crossfade_pos >= pcmbuf_size) - crossfade_pos -= pcmbuf_size; + /* Find the right chunk and sample to start fading in */ + while (fade_in_delay >= crossfade_chunk->size) + { + fade_in_delay -= crossfade_chunk->size; + crossfade_chunk = crossfade_chunk->link; + } + crossfade_sample = fade_in_delay / 2; logf("process done!"); } -/** - * Initializes crossfader, calculates all necessary parameters and - * performs fade-out with the pcm buffer. - */ +/* Initializes crossfader, calculates all necessary parameters and + * performs fade-out with the pcm buffer. */ static void crossfade_start(void) { - size_t fade_out_rem = 0; - unsigned int fade_out_delay = 0; - unsigned fade_in_delay = 0; + size_t crossfade_rem; + size_t fade_out_rem; + size_t fade_out_delay; + size_t fade_in_delay; crossfade_init = false; /* Reject crossfade if less than .5s of data */ @@ -506,88 +530,81 @@ static void crossfade_start(void) } logf("crossfade_start"); - pcmbuf_boost(true); pcmbuf_flush_fillpos(); crossfade_active = true; - crossfade_pos = audiobuffer_pos; + /* Initialize the crossfade buffer size to all of the buffered data that * has not yet been sent to the DMA */ - crossfade_rem = pcmbuf_unplayed_bytes / 2; + crossfade_rem = pcmbuf_unplayed_bytes; + crossfade_chunk = pcmbuf_read->link; - switch (crossfade_mode) { - case CFM_MIX: - case CFM_CROSSFADE: - /* Get fade out delay from settings. */ - fade_out_delay = NATIVE_FREQUENCY - * global_settings.crossfade_fade_out_delay * 2; + /* Get fade out delay from settings. */ + fade_out_delay = + NATIVE_FREQUENCY * global_settings.crossfade_fade_out_delay * 4; - /* Get fade out duration from settings. */ - fade_out_rem = NATIVE_FREQUENCY - * global_settings.crossfade_fade_out_duration * 2; + /* Get fade out duration from settings. */ + fade_out_rem = + NATIVE_FREQUENCY * global_settings.crossfade_fade_out_duration * 4; - /* We want only to modify the last part of the buffer. */ - if (crossfade_rem > fade_out_rem + fade_out_delay) - crossfade_rem = fade_out_rem + fade_out_delay; - - /* Truncate fade out duration if necessary. */ - if (crossfade_rem < fade_out_rem + fade_out_delay) - fade_out_rem -= (fade_out_rem + fade_out_delay) - crossfade_rem; - - /* Get also fade in duration and delays from settings. */ - crossfade_fade_in_rem = NATIVE_FREQUENCY - * global_settings.crossfade_fade_in_duration * 2; - crossfade_fade_in_amount = crossfade_fade_in_rem; - - /* We should avoid to divide by zero. */ - if (crossfade_fade_in_amount == 0) - crossfade_fade_in_amount = 1; - - fade_in_delay = NATIVE_FREQUENCY - * global_settings.crossfade_fade_in_delay * 2; - - /* Decrease the fade out delay if necessary. */ - if (crossfade_rem < fade_out_rem + fade_out_delay) - fade_out_delay -= - (fade_out_rem + fade_out_delay) - crossfade_rem; - break ; - - case CFM_FLUSH: - crossfade_fade_in_rem = 0; - crossfade_fade_in_amount = 0; - break ; + /* We want only to modify the last part of the buffer. */ + if (crossfade_rem > fade_out_rem + fade_out_delay) + { + size_t crossfade_extra = crossfade_rem - fade_out_rem + fade_out_delay; + while (crossfade_extra > crossfade_chunk->size) + { + crossfade_extra -= crossfade_chunk->size; + crossfade_chunk = crossfade_chunk->link; + } + crossfade_sample = crossfade_extra / 2; + } + /* Truncate fade out duration if necessary. */ + else if (crossfade_rem < fade_out_rem + fade_out_delay) + { + size_t crossfade_short = fade_out_rem + fade_out_delay - crossfade_rem; + if (fade_out_rem > crossfade_short) + fade_out_rem -= crossfade_short; + else + { + fade_out_delay -= crossfade_short - fade_out_rem; + fade_out_rem = 0; + } } - if (crossfade_pos < crossfade_rem * 2) - crossfade_pos += pcmbuf_size; - crossfade_pos -= crossfade_rem*2; + /* Get also fade in duration and delays from settings. */ + crossfade_fade_in_total = + NATIVE_FREQUENCY * global_settings.crossfade_fade_in_duration * 4; + crossfade_fade_in_rem = crossfade_fade_in_total; - if (crossfade_mode != CFM_FLUSH) { - /* Process the fade out part of the crossfade. */ - crossfade_process_buffer(fade_in_delay, fade_out_delay, fade_out_rem); - } + /* We should avoid to divide by zero. */ + if (crossfade_fade_in_total == 0) + crossfade_fade_in_total = 1; + fade_in_delay = + NATIVE_FREQUENCY * global_settings.crossfade_fade_in_delay * 4; + + crossfade_process_buffer(fade_in_delay, fade_out_delay, fade_out_rem); } /** * Fades in samples passed to the function and inserts them * to the pcm buffer. */ -static void fade_insert(const short *inbuf, size_t length) +static void fade_insert(const char *buf, size_t length) { size_t copy_n; int factor; - unsigned int i, samples; - short *buf; + unsigned int i; + short *output_buf; + const short *input_buf = (const short *)buf; - factor = ((crossfade_fade_in_amount-crossfade_fade_in_rem)<<8) - /crossfade_fade_in_amount; + factor = ((crossfade_fade_in_total-crossfade_fade_in_rem)<<8) + /crossfade_fade_in_total; - while (audiobuffer_free < length) + while (pcmbuf_free() < length) { pcmbuf_boost(false); sleep(1); } - audiobuffer_free -= length; while (length > 0) { unsigned int audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; @@ -597,79 +614,24 @@ static void fade_insert(const short *inbuf, size_t length) pcmbuf_flush_fillpos(); audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; } - copy_n = MIN(length, pcmbuf_size - audiobuffer_index); - - buf = (short *)&audiobuffer[audiobuffer_index]; - samples = copy_n / 2; - for (i = 0; i < samples; i++) - buf[i] = (inbuf[i] * factor) >> 8; - - inbuf += samples; audiobuffer_fillpos += copy_n; length -= copy_n; - } -} + output_buf = (short *)&audiobuffer[audiobuffer_index]; -/** - * Fades in buf2 and mixes it with buf. - */ -static int crossfade(short *buf, const short *buf2, unsigned int length) -{ - size_t size; - unsigned int i; - size_t size_insert = 0; - int factor; - - size = MIN(length, crossfade_rem); - switch (crossfade_mode) { - /* Fade in the current stream and mix it. */ - case CFM_MIX: - case CFM_CROSSFADE: - factor = ((crossfade_fade_in_amount-crossfade_fade_in_rem)<<8) / - crossfade_fade_in_amount; - - for (i = 0; i < size; i++) { - buf[i] = MIN(32767, MAX(-32768, - buf[i] + ((buf2[i] * factor) >> 8))); - } - break ; - - /* Join two streams. */ - case CFM_FLUSH: - for (i = 0; i < size; i++) { - buf[i] = buf2[i]; - } - //memcpy((char *)buf, (char *)buf2, size*2); - break ; - } - - if (crossfade_fade_in_rem > size) - crossfade_fade_in_rem = crossfade_fade_in_rem - size; - else - crossfade_fade_in_rem = 0; - - crossfade_rem -= size; - if (crossfade_rem == 0) - { - if (crossfade_fade_in_rem > 0 && crossfade_fade_in_amount > 0) + for (copy_n /=2, i = 0; i < copy_n; i++) { - size_insert = MIN(crossfade_fade_in_rem, length - size); - fade_insert(&buf2[size], size_insert*2); - crossfade_fade_in_rem -= size_insert; + int sample = input_buf[i]; + output_buf[i] = (sample * factor) >> 8; } - if (crossfade_fade_in_rem == 0) - crossfade_active = false; + input_buf += copy_n; } - - return size + size_insert; } static void pcmbuf_flush_buffer(const char *buf, size_t length) { size_t copy_n; - audiobuffer_free -= length; while (length > 0) { size_t audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; if (NEED_FLUSH(audiobuffer_index)) @@ -685,21 +647,47 @@ static void pcmbuf_flush_buffer(const char *buf, size_t length) } } -static void flush_crossfade(const char *buf, size_t length) { - size_t copy_n; +static void flush_crossfade(const char *buf, size_t length) +{ + const short *input_buf = (const short *)buf; + int factor = ((crossfade_fade_in_total-crossfade_fade_in_rem)<<8) / + crossfade_fade_in_total; - while (length > 0 && crossfade_active) { - copy_n = MIN(length, pcmbuf_size - crossfade_pos); - copy_n = 2 * crossfade((short *)&audiobuffer[crossfade_pos], - (const short *)buf, copy_n/2); - buf += copy_n; - length -= copy_n; - crossfade_pos += copy_n; - if (crossfade_pos >= pcmbuf_size) - crossfade_pos = 0; + while (length && crossfade_fade_in_rem && crossfade_chunk) + { + short *output_buf = (short *)(crossfade_chunk->addr); + int sample = *input_buf++; + sample = ((sample * factor) >> 8) + output_buf[crossfade_sample]; + output_buf[crossfade_sample++] = MIN(32767, MAX(-32768, sample)); + + length -= 2; + crossfade_fade_in_rem -= 2; + if (crossfade_sample * 2 >= crossfade_chunk->size) + { + crossfade_chunk = crossfade_chunk->link; + crossfade_sample = 0; + } } - pcmbuf_flush_buffer(buf, length); + buf = (const char *)input_buf; + + if (!crossfade_chunk) + { + if (crossfade_fade_in_rem > 0 && crossfade_fade_in_total > 0) + { + size_t size_insert = MIN(crossfade_fade_in_rem, length); + fade_insert(buf, size_insert); + crossfade_fade_in_rem -= size_insert; + length -= size_insert; + buf += size_insert; + } + } + + if (crossfade_fade_in_rem == 0) + crossfade_active = false; + + if (length > 0) + pcmbuf_flush_buffer(buf, length); } static bool prepare_insert(size_t length) @@ -713,7 +701,7 @@ static bool prepare_insert(size_t length) } /* Need to save PCMBUF_MIN_CHUNK to prevent wrapping overwriting */ - if (audiobuffer_free < length + PCMBUF_MIN_CHUNK && !crossfade_active) + if (pcmbuf_free() < length + PCMBUF_MIN_CHUNK && !crossfade_active) { pcmbuf_boost(false); return false; @@ -801,7 +789,6 @@ void pcmbuf_write_complete(size_t length) flush_crossfade(fadebuf, length); else { - audiobuffer_free -= length; audiobuffer_fillpos += length; if (NEED_FLUSH(audiobuffer_pos + audiobuffer_fillpos)) @@ -937,7 +924,7 @@ void pcmbuf_mix_voice(size_t length) length /= 2; while (length-- > 0) { - long sample = *ibuf++; + int sample = *ibuf++; if (pcmbuf_mix_sample >= chunk_samples) { pcmbuf_mix_chunk = pcmbuf_mix_chunk->link; diff --git a/apps/pcmbuf.h b/apps/pcmbuf.h index 819d5011cf..ffd62ed1b6 100644 --- a/apps/pcmbuf.h +++ b/apps/pcmbuf.h @@ -21,10 +21,6 @@ #define PCMBUF_TARGET_CHUNK 32768 /* This is the target fill size of chunks on the pcm buffer */ -#define PCMBUF_MINAVG_CHUNK 24576 /* This is the minimum average size of - chunks on the pcm buffer (or we run out - of buffer descriptors, which is - non-fatal) */ #define PCMBUF_MIN_CHUNK 4096 /* We try to never feed a chunk smaller than this to the DMA */ #define PCMBUF_MIX_CHUNK 8192 /* This is the maximum size of one packet @@ -54,9 +50,9 @@ void pcmbuf_play_start(void); bool pcmbuf_crossfade_init(bool manual_skip); void pcmbuf_set_event_handler(void (*callback)(void)); 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); -bool pcmbuf_insert_buffer(const char *buf, size_t length); 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);