summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2020-10-01 19:35:12 -0400
committerSolomon Peachy <pizza@shaftnet.org>2020-10-03 14:19:17 -0400
commit2e708c48c549a947506c5953ae5fc9d10e932f7c (patch)
tree1786f3501304df913b6cc93c93b400c57b8673e2
parentd4a620e85af6c1eae4c99b92c81d8c098f13eae9 (diff)
downloadrockbox-2e708c48c549a947506c5953ae5fc9d10e932f7c.tar.gz
rockbox-2e708c48c549a947506c5953ae5fc9d10e932f7c.zip
pcm: Dynamically-size the mixer buffer at higher audio bitrates.
Basically, existing sizes apply for <= 48KHz audio. Up to 96K, we double the mix buffer. up to 192K, we double it again. Will help reduce the interrupt load and overall latency, keeping it roughtly constant as a function of time, regardless of bitrate. (It is acutally a fixed-size buffer, statically-allocated to handle the worst-case bitrate the player supports. However, at runtime if we are using a lower bitrate we will only use a portion of it in order to keep latancies down) Change-Id: I61ca23180a86502732b0903fe9691c1a8c2aeaea
-rw-r--r--firmware/pcm_mixer.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/firmware/pcm_mixer.c b/firmware/pcm_mixer.c
index ceba31962e..9467dc4c59 100644
--- a/firmware/pcm_mixer.c
+++ b/firmware/pcm_mixer.c
@@ -25,6 +25,7 @@
25#include "pcm.h" 25#include "pcm.h"
26#include "pcm-internal.h" 26#include "pcm-internal.h"
27#include "pcm_mixer.h" 27#include "pcm_mixer.h"
28#include "pcm_sampr.h"
28 29
29/* Channels use standard-style PCM callback interface but a latency of one 30/* Channels use standard-style PCM callback interface but a latency of one
30 frame by double-buffering is introduced in order to facilitate mixing and 31 frame by double-buffering is introduced in order to facilitate mixing and
@@ -33,6 +34,7 @@
33 parallel (as much as possible) with sending-out data. */ 34 parallel (as much as possible) with sending-out data. */
34 35
35static unsigned int mixer_sampr = HW_SAMPR_DEFAULT; 36static unsigned int mixer_sampr = HW_SAMPR_DEFAULT;
37static unsigned int mix_frame_size = MIX_FRAME_SAMPLES*4;
36 38
37/* Define this to nonzero to add a marker pulse at each frame start */ 39/* Define this to nonzero to add a marker pulse at each frame start */
38#define FRAME_BOUNDARY_MARKERS 0 40#define FRAME_BOUNDARY_MARKERS 0
@@ -49,13 +51,20 @@ struct mixer_channel
49 chan_buffer_hook_fn_type buffer_hook; /* Callback for new buffer */ 51 chan_buffer_hook_fn_type buffer_hook; /* Callback for new buffer */
50}; 52};
51 53
52/* Forget about boost here for the moment */ 54#if (defined(HW_HAVE_192) || defined(HW_HAVE_176))
53#define MIX_FRAME_SIZE (MIX_FRAME_SAMPLES*4) 55#define FRAME_SIZE_MULT 4
56#elif (defined(HW_HAVE_96) || defined(HW_HAVE_88))
57#define FRAME_SIZE_MULT 2
58#else
59#define FRAME_SIZE_MULT 1
60#endif
61
62#define MAX_MIX_FRAME_SAMPLES (MIX_FRAME_SAMPLES * FRAME_SIZE_MULT)
54 63
55/* Because of the double-buffering, playback is always from here, otherwise a 64/* Because of the double-buffering, playback is always from here, otherwise a
56 mechanism for the channel callbacks not to free buffers too early would be 65 mechanism for the channel callbacks not to free buffers too early would be
57 needed (if we _really_ want it and it's worth it, we _can_ do that ;-) ) */ 66 needed (if we _really_ want it and it's worth it, we _can_ do that ;-) ) */
58static uint32_t downmix_buf[2][MIX_FRAME_SAMPLES] DOWNMIX_BUF_IBSS MEM_ALIGN_ATTR; 67static uint32_t downmix_buf[2][MAX_MIX_FRAME_SAMPLES] DOWNMIX_BUF_IBSS MEM_ALIGN_ATTR;
59static int downmix_index = 0; /* Which downmix_buf? */ 68static int downmix_index = 0; /* Which downmix_buf? */
60static size_t next_size = 0; /* Size of buffer to play next time */ 69static size_t next_size = 0; /* Size of buffer to play next time */
61 70
@@ -66,7 +75,7 @@ static struct mixer_channel channels[PCM_MIXER_NUM_CHANNELS] IBSS_ATTR;
66static struct mixer_channel * active_channels[PCM_MIXER_NUM_CHANNELS+1] IBSS_ATTR; 75static struct mixer_channel * active_channels[PCM_MIXER_NUM_CHANNELS+1] IBSS_ATTR;
67 76
68/* Number of silence frames to play after all data has played */ 77/* Number of silence frames to play after all data has played */
69#define MAX_IDLE_FRAMES (mixer_sampr*3 / MIX_FRAME_SAMPLES) 78#define MAX_IDLE_FRAMES (mixer_sampr*3 / mix_frame_size / 4)
70static unsigned int idle_counter = 0; 79static unsigned int idle_counter = 0;
71 80
72/** Mixing routines, CPU optmized **/ 81/** Mixing routines, CPU optmized **/
@@ -125,7 +134,7 @@ mixer_buffer_callback(enum pcm_dma_status status)
125 downmix_index ^= 1; /* Next buffer */ 134 downmix_index ^= 1; /* Next buffer */
126 135
127 void *mixptr = downmix_buf[downmix_index]; 136 void *mixptr = downmix_buf[downmix_index];
128 size_t mixsize = MIX_FRAME_SIZE; 137 size_t mixsize = mix_frame_size;
129 struct mixer_channel **chan_p; 138 struct mixer_channel **chan_p;
130 139
131 next_size = 0; 140 next_size = 0;
@@ -216,11 +225,11 @@ fill_frame:
216 chan->last_size = mixsize; 225 chan->last_size = mixsize;
217 next_size += mixsize; 226 next_size += mixsize;
218 227
219 if (next_size < MIX_FRAME_SIZE) 228 if (next_size < mix_frame_size)
220 { 229 {
221 /* There is still space remaining in this frame */ 230 /* There is still space remaining in this frame */
222 mixptr += mixsize; 231 mixptr += mixsize;
223 mixsize = MIX_FRAME_SIZE - next_size; 232 mixsize = mix_frame_size - next_size;
224 goto fill_frame; 233 goto fill_frame;
225 } 234 }
226 } 235 }
@@ -228,9 +237,9 @@ fill_frame:
228 { 237 {
229 /* Pad incomplete frames with silence */ 238 /* Pad incomplete frames with silence */
230 if (idle_counter <= 3) 239 if (idle_counter <= 3)
231 memset(mixptr, 0, MIX_FRAME_SIZE - next_size); 240 memset(mixptr, 0, mix_frame_size - next_size);
232 241
233 next_size = MIX_FRAME_SIZE; 242 next_size = mix_frame_size;
234 } 243 }
235 /* else silence period ran out - go to sleep */ 244 /* else silence period ran out - go to sleep */
236 245
@@ -268,7 +277,7 @@ static void mixer_start_pcm(void)
268 mixer_buffer_callback(PCM_DMAST_STARTED); 277 mixer_buffer_callback(PCM_DMAST_STARTED);
269 278
270 pcm_play_data(mixer_pcm_callback, mixer_buffer_callback, 279 pcm_play_data(mixer_pcm_callback, mixer_buffer_callback,
271 start, MIX_FRAME_SIZE); 280 start, mix_frame_size);
272} 281}
273 282
274/** Public interfaces **/ 283/** Public interfaces **/
@@ -452,6 +461,16 @@ void mixer_set_frequency(unsigned int samplerate)
452 /* All data is now invalid */ 461 /* All data is now invalid */
453 mixer_reset(); 462 mixer_reset();
454 mixer_sampr = samplerate; 463 mixer_sampr = samplerate;
464
465 /* Work out how much space we really need */
466 if (samplerate > SAMPR_96)
467 mix_frame_size = 4;
468 else if (samplerate > SAMPR_48)
469 mix_frame_size = 2;
470 else
471 mix_frame_size = 1;
472
473 mix_frame_size *= MIX_FRAME_SAMPLES * 4;
455} 474}
456 475
457/* Get output samplerate */ 476/* Get output samplerate */