diff options
Diffstat (limited to 'firmware/pcm.c')
-rw-r--r-- | firmware/pcm.c | 53 |
1 files changed, 27 insertions, 26 deletions
diff --git a/firmware/pcm.c b/firmware/pcm.c index b7415f329b..c2ebc67687 100644 --- a/firmware/pcm.c +++ b/firmware/pcm.c | |||
@@ -93,6 +93,9 @@ unsigned long pcm_sampr SHAREDBSS_ATTR = HW_SAMPR_DEFAULT; | |||
93 | /* samplerate frequency selection index */ | 93 | /* samplerate frequency selection index */ |
94 | int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT; | 94 | int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT; |
95 | 95 | ||
96 | /* peak data for the global peak values - i.e. what the final output is */ | ||
97 | static struct pcm_peaks global_peaks; | ||
98 | |||
96 | /* Called internally by functions to reset the state */ | 99 | /* Called internally by functions to reset the state */ |
97 | static void pcm_play_stopped(void) | 100 | static void pcm_play_stopped(void) |
98 | { | 101 | { |
@@ -107,7 +110,7 @@ static void pcm_play_stopped(void) | |||
107 | * | 110 | * |
108 | * Used for recording and playback. | 111 | * Used for recording and playback. |
109 | */ | 112 | */ |
110 | static void pcm_peak_peeker(const int32_t *addr, int count, int peaks[2]) | 113 | static void pcm_peak_peeker(const int32_t *addr, int count, uint16_t peaks[2]) |
111 | { | 114 | { |
112 | int peak_l = 0, peak_r = 0; | 115 | int peak_l = 0, peak_r = 0; |
113 | const int32_t * const end = addr + count; | 116 | const int32_t * const end = addr + count; |
@@ -145,18 +148,13 @@ static void pcm_peak_peeker(const int32_t *addr, int count, int peaks[2]) | |||
145 | peaks[1] = peak_r; | 148 | peaks[1] = peak_r; |
146 | } | 149 | } |
147 | 150 | ||
148 | void pcm_calculate_peaks(int *left, int *right) | 151 | void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active, |
152 | const void *addr, int count) | ||
149 | { | 153 | { |
150 | static int peaks[2] = { 0, 0 }; | ||
151 | static unsigned long last_peak_tick = 0; | ||
152 | static unsigned long frame_period = 0; | ||
153 | |||
154 | long tick = current_tick; | 154 | long tick = current_tick; |
155 | int count; | ||
156 | const void *addr; | ||
157 | 155 | ||
158 | /* Throttled peak ahead based on calling period */ | 156 | /* Peak no farther ahead than expected period to avoid overcalculation */ |
159 | long period = tick - last_peak_tick; | 157 | long period = tick - peaks->tick; |
160 | 158 | ||
161 | /* Keep reasonable limits on period */ | 159 | /* Keep reasonable limits on period */ |
162 | if (period < 1) | 160 | if (period < 1) |
@@ -164,33 +162,38 @@ void pcm_calculate_peaks(int *left, int *right) | |||
164 | else if (period > HZ/5) | 162 | else if (period > HZ/5) |
165 | period = HZ/5; | 163 | period = HZ/5; |
166 | 164 | ||
167 | frame_period = (3*frame_period + period) >> 2; | 165 | peaks->period = (3*peaks->period + period) >> 2; |
168 | 166 | peaks->tick = tick; | |
169 | last_peak_tick = tick; | ||
170 | 167 | ||
171 | addr = pcm_play_dma_get_peak_buffer(&count); | 168 | if (active) |
172 | |||
173 | if (pcm_playing && !pcm_paused) | ||
174 | { | 169 | { |
175 | int framecount; | 170 | int framecount = peaks->period*pcm_curr_sampr / HZ; |
176 | |||
177 | framecount = frame_period*pcm_curr_sampr / HZ; | ||
178 | count = MIN(framecount, count); | 171 | count = MIN(framecount, count); |
179 | 172 | ||
180 | if (count > 0) | 173 | if (count > 0) |
181 | pcm_peak_peeker((int32_t *)addr, count, peaks); | 174 | pcm_peak_peeker((int32_t *)addr, count, peaks->val); |
182 | /* else keep previous peak values */ | 175 | /* else keep previous peak values */ |
183 | } | 176 | } |
184 | else | 177 | else |
185 | { | 178 | { |
186 | peaks[0] = peaks[1] = 0; | 179 | /* peaks are zero */ |
180 | peaks->val[0] = peaks->val[1] = 0; | ||
187 | } | 181 | } |
182 | } | ||
183 | |||
184 | void pcm_calculate_peaks(int *left, int *right) | ||
185 | { | ||
186 | int count; | ||
187 | const void *addr = pcm_play_dma_get_peak_buffer(&count); | ||
188 | |||
189 | pcm_do_peak_calculation(&global_peaks, pcm_playing && !pcm_paused, | ||
190 | addr, count); | ||
188 | 191 | ||
189 | if (left) | 192 | if (left) |
190 | *left = peaks[0]; | 193 | *left = global_peaks.val[0]; |
191 | 194 | ||
192 | if (right) | 195 | if (right) |
193 | *right = peaks[1]; | 196 | *right = global_peaks.val[1]; |
194 | } | 197 | } |
195 | 198 | ||
196 | const void* pcm_get_peak_buffer(int * count) | 199 | const void* pcm_get_peak_buffer(int * count) |
@@ -437,7 +440,7 @@ static void pcm_recording_stopped(void) | |||
437 | */ | 440 | */ |
438 | void pcm_calculate_rec_peaks(int *left, int *right) | 441 | void pcm_calculate_rec_peaks(int *left, int *right) |
439 | { | 442 | { |
440 | static int peaks[2]; | 443 | static uint16_t peaks[2]; |
441 | 444 | ||
442 | if (pcm_recording) | 445 | if (pcm_recording) |
443 | { | 446 | { |
@@ -484,10 +487,8 @@ void pcm_init_recording(void) | |||
484 | { | 487 | { |
485 | logf("pcm_init_recording"); | 488 | logf("pcm_init_recording"); |
486 | 489 | ||
487 | #ifndef HAVE_PCM_FULL_DUPLEX | ||
488 | /* Stop the beasty before attempting recording */ | 490 | /* Stop the beasty before attempting recording */ |
489 | mixer_reset(); | 491 | mixer_reset(); |
490 | #endif | ||
491 | 492 | ||
492 | /* Recording init is locked unlike general pcm init since this is not | 493 | /* Recording init is locked unlike general pcm init since this is not |
493 | * just a one-time event at startup and it should and must be safe by | 494 | * just a one-time event at startup and it should and must be safe by |