summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-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 @@
#include "pcm.h"
#include "pcm-internal.h"
#include "pcm_mixer.h"
+#include "pcm_sampr.h"
/* Channels use standard-style PCM callback interface but a latency of one
frame by double-buffering is introduced in order to facilitate mixing and
@@ -33,6 +34,7 @@
parallel (as much as possible) with sending-out data. */
static unsigned int mixer_sampr = HW_SAMPR_DEFAULT;
+static unsigned int mix_frame_size = MIX_FRAME_SAMPLES*4;
/* Define this to nonzero to add a marker pulse at each frame start */
#define FRAME_BOUNDARY_MARKERS 0
@@ -49,13 +51,20 @@ struct mixer_channel
chan_buffer_hook_fn_type buffer_hook; /* Callback for new buffer */
};
-/* Forget about boost here for the moment */
-#define MIX_FRAME_SIZE (MIX_FRAME_SAMPLES*4)
+#if (defined(HW_HAVE_192) || defined(HW_HAVE_176))
+#define FRAME_SIZE_MULT 4
+#elif (defined(HW_HAVE_96) || defined(HW_HAVE_88))
+#define FRAME_SIZE_MULT 2
+#else
+#define FRAME_SIZE_MULT 1
+#endif
+
+#define MAX_MIX_FRAME_SAMPLES (MIX_FRAME_SAMPLES * FRAME_SIZE_MULT)
/* Because of the double-buffering, playback is always from here, otherwise a
mechanism for the channel callbacks not to free buffers too early would be
needed (if we _really_ want it and it's worth it, we _can_ do that ;-) ) */
-static uint32_t downmix_buf[2][MIX_FRAME_SAMPLES] DOWNMIX_BUF_IBSS MEM_ALIGN_ATTR;
+static uint32_t downmix_buf[2][MAX_MIX_FRAME_SAMPLES] DOWNMIX_BUF_IBSS MEM_ALIGN_ATTR;
static int downmix_index = 0; /* Which downmix_buf? */
static size_t next_size = 0; /* Size of buffer to play next time */
@@ -66,7 +75,7 @@ static struct mixer_channel channels[PCM_MIXER_NUM_CHANNELS] IBSS_ATTR;
static struct mixer_channel * active_channels[PCM_MIXER_NUM_CHANNELS+1] IBSS_ATTR;
/* Number of silence frames to play after all data has played */
-#define MAX_IDLE_FRAMES (mixer_sampr*3 / MIX_FRAME_SAMPLES)
+#define MAX_IDLE_FRAMES (mixer_sampr*3 / mix_frame_size / 4)
static unsigned int idle_counter = 0;
/** Mixing routines, CPU optmized **/
@@ -125,7 +134,7 @@ mixer_buffer_callback(enum pcm_dma_status status)
downmix_index ^= 1; /* Next buffer */
void *mixptr = downmix_buf[downmix_index];
- size_t mixsize = MIX_FRAME_SIZE;
+ size_t mixsize = mix_frame_size;
struct mixer_channel **chan_p;
next_size = 0;
@@ -216,11 +225,11 @@ fill_frame:
chan->last_size = mixsize;
next_size += mixsize;
- if (next_size < MIX_FRAME_SIZE)
+ if (next_size < mix_frame_size)
{
/* There is still space remaining in this frame */
mixptr += mixsize;
- mixsize = MIX_FRAME_SIZE - next_size;
+ mixsize = mix_frame_size - next_size;
goto fill_frame;
}
}
@@ -228,9 +237,9 @@ fill_frame:
{
/* Pad incomplete frames with silence */
if (idle_counter <= 3)
- memset(mixptr, 0, MIX_FRAME_SIZE - next_size);
+ memset(mixptr, 0, mix_frame_size - next_size);
- next_size = MIX_FRAME_SIZE;
+ next_size = mix_frame_size;
}
/* else silence period ran out - go to sleep */
@@ -268,7 +277,7 @@ static void mixer_start_pcm(void)
mixer_buffer_callback(PCM_DMAST_STARTED);
pcm_play_data(mixer_pcm_callback, mixer_buffer_callback,
- start, MIX_FRAME_SIZE);
+ start, mix_frame_size);
}
/** Public interfaces **/
@@ -452,6 +461,16 @@ void mixer_set_frequency(unsigned int samplerate)
/* All data is now invalid */
mixer_reset();
mixer_sampr = samplerate;
+
+ /* Work out how much space we really need */
+ if (samplerate > SAMPR_96)
+ mix_frame_size = 4;
+ else if (samplerate > SAMPR_48)
+ mix_frame_size = 2;
+ else
+ mix_frame_size = 1;
+
+ mix_frame_size *= MIX_FRAME_SAMPLES * 4;
}
/* Get output samplerate */