summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/pcmbuf.c34
-rw-r--r--apps/pcmbuf.h1
-rw-r--r--apps/sound_menu.c9
3 files changed, 35 insertions, 9 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index f184672bd1..22e725507b 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -36,11 +36,12 @@
36#include "audio.h" 36#include "audio.h"
37#include "dsp.h" 37#include "dsp.h"
38 38
39#define CHUNK_SIZE PCMBUF_GUARD 39#define CHUNK_SIZE 32768
40/* Must be a power of 2 */ 40/* Must be a power of 2 */
41#define NUM_PCM_BUFFERS 128 41#define NUM_PCM_BUFFERS 128
42#define NUM_PCM_BUFFERS_MASK (NUM_PCM_BUFFERS - 1) 42#define NUM_PCM_BUFFERS_MASK (NUM_PCM_BUFFERS - 1)
43#define PCMBUF_WATERMARK (CHUNK_SIZE * 6) 43/* Watermark level at 1s. */
44#define PCMBUF_WATERMARK (NATIVE_FREQUENCY * 4 * 1)
44 45
45/* Audio buffer related settings. */ 46/* Audio buffer related settings. */
46static long pcmbuf_size = 0; /* Size of the PCM buffer. */ 47static long pcmbuf_size = 0; /* Size of the PCM buffer. */
@@ -83,7 +84,7 @@ struct pcmbufdesc
83 int size; 84 int size;
84 /* Call this when the buffer has been played */ 85 /* Call this when the buffer has been played */
85 void (*callback)(void); 86 void (*callback)(void);
86} pcmbuffers[NUM_PCM_BUFFERS] IDATA_ATTR; 87} pcmbuffers[NUM_PCM_BUFFERS] IDATA_ATTR; /* Do we really need IRAM for this? */
87 88
88static int pcmbuf_read_index; 89static int pcmbuf_read_index;
89static int pcmbuf_write_index; 90static int pcmbuf_write_index;
@@ -95,6 +96,7 @@ static int pcmbuf_num_used_buffers(void);
95static void (*position_callback)(int size); 96static void (*position_callback)(int size);
96static int last_chunksize; 97static int last_chunksize;
97static long mixpos = 0; 98static long mixpos = 0;
99static bool low_latency_mode = false;
98 100
99#ifdef HAVE_ADJUSTABLE_CPU_FREQ 101#ifdef HAVE_ADJUSTABLE_CPU_FREQ
100static bool boost_mode; 102static bool boost_mode;
@@ -222,12 +224,17 @@ unsigned int pcmbuf_get_latency(void)
222 return latency<0?0:latency; 224 return latency<0?0:latency;
223} 225}
224 226
227void pcmbuf_set_low_latency(bool state)
228{
229 low_latency_mode = state;
230}
231
225bool pcmbuf_is_lowdata(void) 232bool pcmbuf_is_lowdata(void)
226{ 233{
227 if (!pcm_is_playing() || pcm_is_paused() || crossfade_init || crossfade_active) 234 if (!pcm_is_playing() || pcm_is_paused() || crossfade_init || crossfade_active)
228 return false; 235 return false;
229 236
230 if (pcmbuf_unplayed_bytes < CHUNK_SIZE * 4) 237 if (pcmbuf_unplayed_bytes < pcmbuf_watermark - CHUNK_SIZE)
231 return true; 238 return true;
232 239
233 return false; 240 return false;
@@ -237,7 +244,7 @@ bool pcmbuf_crossfade_init(bool manual_skip)
237{ 244{
238 if (pcmbuf_size - audiobuffer_free < CHUNK_SIZE * 8 245 if (pcmbuf_size - audiobuffer_free < CHUNK_SIZE * 8
239 || !pcmbuf_is_crossfade_enabled() 246 || !pcmbuf_is_crossfade_enabled()
240 || crossfade_active || crossfade_init) { 247 || crossfade_active || crossfade_init || low_latency_mode) {
241 pcmbuf_flush_audio(); 248 pcmbuf_flush_audio();
242 return false; 249 return false;
243 } 250 }
@@ -422,7 +429,7 @@ static void crossfade_start(void)
422 int fade_in_delay = 0; 429 int fade_in_delay = 0;
423 430
424 crossfade_init = 0; 431 crossfade_init = 0;
425 if (bytesleft < CHUNK_SIZE * 4) { 432 if (bytesleft < NATIVE_FREQUENCY * 4 / 2) {
426 logf("crossfade rejected"); 433 logf("crossfade rejected");
427 pcmbuf_play_stop(); 434 pcmbuf_play_stop();
428 return ; 435 return ;
@@ -439,7 +446,7 @@ static void crossfade_start(void)
439 case CFM_MIX: 446 case CFM_MIX:
440 case CFM_CROSSFADE: 447 case CFM_CROSSFADE:
441 /* Initialize the crossfade buffer size. */ 448 /* Initialize the crossfade buffer size. */
442 crossfade_rem = (bytesleft - (CHUNK_SIZE * 2))/2; 449 crossfade_rem = (bytesleft - (NATIVE_FREQUENCY / 4))/2;
443 450
444 /* Get fade out delay from settings. */ 451 /* Get fade out delay from settings. */
445 fade_out_delay = NATIVE_FREQUENCY 452 fade_out_delay = NATIVE_FREQUENCY
@@ -593,6 +600,14 @@ static bool prepare_insert(long length)
593{ 600{
594 if (crossfade_init) 601 if (crossfade_init)
595 crossfade_start(); 602 crossfade_start();
603
604 if (low_latency_mode)
605 {
606 /* 1/4s latency. */
607 if (pcmbuf_unplayed_bytes > NATIVE_FREQUENCY * 4 / 4
608 && pcm_is_playing())
609 return false;
610 }
596 611
597 if (audiobuffer_free < length + audiobuffer_fillpos 612 if (audiobuffer_free < length + audiobuffer_fillpos
598 + CHUNK_SIZE && !crossfade_active) { 613 + CHUNK_SIZE && !crossfade_active) {
@@ -603,7 +618,8 @@ static bool prepare_insert(long length)
603 if (!pcm_is_playing()) { 618 if (!pcm_is_playing()) {
604 pcmbuf_boost(true); 619 pcmbuf_boost(true);
605 crossfade_active = false; 620 crossfade_active = false;
606 if (audiobuffer_free < pcmbuf_size - CHUNK_SIZE*4) { 621 /* Pre-buffer 1s. */
622 if (audiobuffer_free < pcmbuf_size - NATIVE_FREQUENCY*4) {
607 logf("pcm starting"); 623 logf("pcm starting");
608 pcmbuf_play_start(); 624 pcmbuf_play_start();
609 } 625 }
@@ -840,7 +856,7 @@ void pcmbuf_crossfade_enable(bool on_off)
840 crossfade_enabled = on_off; 856 crossfade_enabled = on_off;
841 857
842 if (crossfade_enabled) { 858 if (crossfade_enabled) {
843 pcmbuf_set_watermark_bytes(pcmbuf_size - (CHUNK_SIZE*6)); 859 pcmbuf_set_watermark_bytes(pcmbuf_size - (NATIVE_FREQUENCY*4/2));
844 } else { 860 } else {
845 pcmbuf_set_watermark_bytes(PCMBUF_WATERMARK); 861 pcmbuf_set_watermark_bytes(PCMBUF_WATERMARK);
846 } 862 }
diff --git a/apps/pcmbuf.h b/apps/pcmbuf.h
index afc62021aa..2476857f88 100644
--- a/apps/pcmbuf.h
+++ b/apps/pcmbuf.h
@@ -45,6 +45,7 @@ bool pcmbuf_crossfade_init(bool manual_skip);
45void pcmbuf_add_event(void (*event_handler)(void)); 45void pcmbuf_add_event(void (*event_handler)(void));
46void pcmbuf_set_position_callback(void (*callback)(int size)); 46void pcmbuf_set_position_callback(void (*callback)(int size));
47unsigned int pcmbuf_get_latency(void); 47unsigned int pcmbuf_get_latency(void);
48void pcmbuf_set_low_latency(bool state);
48bool pcmbuf_insert_buffer(char *buf, long length); 49bool pcmbuf_insert_buffer(char *buf, long length);
49void pcmbuf_flush_buffer(long length); 50void pcmbuf_flush_buffer(long length);
50void* pcmbuf_request_buffer(long length, long *realsize); 51void* pcmbuf_request_buffer(long length, long *realsize);
diff --git a/apps/sound_menu.c b/apps/sound_menu.c
index 2bd0ff6e59..9c8d398029 100644
--- a/apps/sound_menu.c
+++ b/apps/sound_menu.c
@@ -46,6 +46,7 @@
46#if CONFIG_CODEC == SWCODEC 46#if CONFIG_CODEC == SWCODEC
47#include "dsp.h" 47#include "dsp.h"
48#include "eq_menu.h" 48#include "eq_menu.h"
49#include "pcmbuf.h"
49#endif 50#endif
50 51
51int selected_setting; /* Used by the callback */ 52int selected_setting; /* Used by the callback */
@@ -394,11 +395,19 @@ bool sound_menu(void)
394#endif 395#endif
395 }; 396 };
396 397
398#if CONFIG_CODEC == SWCODEC
399 pcmbuf_set_low_latency(true);
400#endif
401
397 m=menu_init( items, sizeof(items) / sizeof(*items), NULL, 402 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
398 NULL, NULL, NULL); 403 NULL, NULL, NULL);
399 result = menu_run(m); 404 result = menu_run(m);
400 menu_exit(m); 405 menu_exit(m);
401 406
407#if CONFIG_CODEC == SWCODEC
408 pcmbuf_set_low_latency(false);
409#endif
410
402 return result; 411 return result;
403} 412}
404 413