summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/pcm_mixer.h10
-rw-r--r--firmware/pcm_mixer.c22
2 files changed, 31 insertions, 1 deletions
diff --git a/firmware/export/pcm_mixer.h b/firmware/export/pcm_mixer.h
index 69d2b894df..d424083002 100644
--- a/firmware/export/pcm_mixer.h
+++ b/firmware/export/pcm_mixer.h
@@ -106,7 +106,8 @@ enum channel_status mixer_channel_status(enum pcm_mixer_channel channel);
106size_t mixer_channel_get_bytes_waiting(enum pcm_mixer_channel channel); 106size_t mixer_channel_get_bytes_waiting(enum pcm_mixer_channel channel);
107 107
108/* Return pointer to channel's playing audio data and the size remaining */ 108/* Return pointer to channel's playing audio data and the size remaining */
109const void * mixer_channel_get_buffer(enum pcm_mixer_channel channel, int *count); 109const void * mixer_channel_get_buffer(enum pcm_mixer_channel channel,
110 int *count);
110 111
111/* Calculate peak values for channel */ 112/* Calculate peak values for channel */
112void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel, 113void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
@@ -116,6 +117,13 @@ void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
116void mixer_adjust_channel_address(enum pcm_mixer_channel channel, 117void mixer_adjust_channel_address(enum pcm_mixer_channel channel,
117 off_t offset); 118 off_t offset);
118 119
120/* Set a hook that is called upon getting a new source buffer for a channel
121 NOTE: Called for each buffer, not each mixer chunk */
122typedef void (*chan_buffer_hook_fn_type)(const void *start, size_t size);
123
124void mixer_channel_set_buffer_hook(enum pcm_mixer_channel channel,
125 chan_buffer_hook_fn_type fn);
126
119/* Stop ALL channels and PCM and reset state */ 127/* Stop ALL channels and PCM and reset state */
120void mixer_reset(void); 128void mixer_reset(void);
121 129
diff --git a/firmware/pcm_mixer.c b/firmware/pcm_mixer.c
index cddff431ec..34852e97e9 100644
--- a/firmware/pcm_mixer.c
+++ b/firmware/pcm_mixer.c
@@ -45,6 +45,7 @@ struct mixer_channel
45 pcm_play_callback_type get_more; /* Registered callback */ 45 pcm_play_callback_type get_more; /* Registered callback */
46 enum channel_status status; /* Playback status */ 46 enum channel_status status; /* Playback status */
47 uint32_t amplitude; /* Amp. factor: 0x0000 = mute, 0x10000 = unity */ 47 uint32_t amplitude; /* Amp. factor: 0x0000 = mute, 0x10000 = unity */
48 chan_buffer_hook_fn_type buffer_hook; /* Callback for new buffer */
48}; 49};
49 50
50/* Forget about boost here for the moment */ 51/* Forget about boost here for the moment */
@@ -106,6 +107,12 @@ static void mixer_pcm_callback(const void **addr, size_t *size)
106 *size = next_size; 107 *size = next_size;
107} 108}
108 109
110static inline void chan_call_buffer_hook(struct mixer_channel *chan)
111{
112 if (UNLIKELY(chan->buffer_hook))
113 chan->buffer_hook(chan->start, chan->size);
114}
115
109/* Buffering callback - calls sub-callbacks and mixes the data for next 116/* Buffering callback - calls sub-callbacks and mixes the data for next
110 buffer to be sent from mixer_pcm_callback() */ 117 buffer to be sent from mixer_pcm_callback() */
111static enum pcm_dma_status MIXER_CALLBACK_ICODE 118static enum pcm_dma_status MIXER_CALLBACK_ICODE
@@ -149,6 +156,8 @@ fill_frame:
149 channel_stopped(chan); 156 channel_stopped(chan);
150 continue; 157 continue;
151 } 158 }
159
160 chan_call_buffer_hook(chan);
152 } 161 }
153 162
154 /* Channel will play for at least part of this frame */ 163 /* Channel will play for at least part of this frame */
@@ -298,6 +307,7 @@ void mixer_channel_play_data(enum pcm_mixer_channel channel,
298 chan->get_more = get_more; 307 chan->get_more = get_more;
299 308
300 mixer_activate_channel(chan); 309 mixer_activate_channel(chan);
310 chan_call_buffer_hook(chan);
301 mixer_start_pcm(); 311 mixer_start_pcm();
302 } 312 }
303 else 313 else
@@ -406,6 +416,18 @@ void mixer_adjust_channel_address(enum pcm_mixer_channel channel,
406 pcm_play_unlock(); 416 pcm_play_unlock();
407} 417}
408 418
419/* Set a hook that is called upon getting a new source buffer for a channel
420 NOTE: Called for each buffer, not each mixer chunk */
421void mixer_channel_set_buffer_hook(enum pcm_mixer_channel channel,
422 chan_buffer_hook_fn_type fn)
423{
424 struct mixer_channel *chan = &channels[channel];
425
426 pcm_play_lock();
427 chan->buffer_hook = fn;
428 pcm_play_unlock();
429}
430
409/* Stop ALL channels and PCM and reset state */ 431/* Stop ALL channels and PCM and reset state */
410void mixer_reset(void) 432void mixer_reset(void)
411{ 433{