diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/pcm_mixer.c | 39 |
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 | ||
35 | static unsigned int mixer_sampr = HW_SAMPR_DEFAULT; | 36 | static unsigned int mixer_sampr = HW_SAMPR_DEFAULT; |
37 | static 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 ;-) ) */ |
58 | static uint32_t downmix_buf[2][MIX_FRAME_SAMPLES] DOWNMIX_BUF_IBSS MEM_ALIGN_ATTR; | 67 | static uint32_t downmix_buf[2][MAX_MIX_FRAME_SAMPLES] DOWNMIX_BUF_IBSS MEM_ALIGN_ATTR; |
59 | static int downmix_index = 0; /* Which downmix_buf? */ | 68 | static int downmix_index = 0; /* Which downmix_buf? */ |
60 | static size_t next_size = 0; /* Size of buffer to play next time */ | 69 | static 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; | |||
66 | static struct mixer_channel * active_channels[PCM_MIXER_NUM_CHANNELS+1] IBSS_ATTR; | 75 | static 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) |
70 | static unsigned int idle_counter = 0; | 79 | static 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 */ |