diff options
Diffstat (limited to 'firmware/pcm.c')
-rw-r--r-- | firmware/pcm.c | 92 |
1 files changed, 44 insertions, 48 deletions
diff --git a/firmware/pcm.c b/firmware/pcm.c index 621ed56e0d..94b0d6eefb 100644 --- a/firmware/pcm.c +++ b/firmware/pcm.c | |||
@@ -102,9 +102,6 @@ unsigned long pcm_sampr SHAREDBSS_ATTR = HW_SAMPR_DEFAULT; | |||
102 | /* samplerate frequency selection index */ | 102 | /* samplerate frequency selection index */ |
103 | int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT; | 103 | int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT; |
104 | 104 | ||
105 | /* peak data for the global peak values - i.e. what the final output is */ | ||
106 | static struct pcm_peaks global_peaks; | ||
107 | |||
108 | /* Called internally by functions to reset the state */ | 105 | /* Called internally by functions to reset the state */ |
109 | static void pcm_play_stopped(void) | 106 | static void pcm_play_stopped(void) |
110 | { | 107 | { |
@@ -125,42 +122,38 @@ static void pcm_wait_for_init(void) | |||
125 | * | 122 | * |
126 | * Used for recording and playback. | 123 | * Used for recording and playback. |
127 | */ | 124 | */ |
128 | static void pcm_peak_peeker(const int32_t *addr, int count, uint16_t peaks[2]) | 125 | static void pcm_peak_peeker(const int16_t *p, int count, |
126 | struct pcm_peaks *peaks) | ||
129 | { | 127 | { |
130 | int peak_l = 0, peak_r = 0; | 128 | uint32_t peak_l = 0, peak_r = 0; |
131 | const int32_t * const end = addr + count; | 129 | const int16_t *pend = p + 2 * count; |
132 | 130 | ||
133 | do | 131 | do |
134 | { | 132 | { |
135 | int32_t value = *addr; | 133 | int32_t s; |
136 | int ch; | 134 | |
137 | 135 | s = p[0]; | |
138 | #ifdef ROCKBOX_BIG_ENDIAN | 136 | |
139 | ch = value >> 16; | 137 | if (s < 0) |
140 | #else | 138 | s = -s; |
141 | ch = (int16_t)value; | 139 | |
142 | #endif | 140 | if ((uint32_t)s > peak_l) |
143 | if (ch < 0) | 141 | peak_l = s; |
144 | ch = -ch; | 142 | |
145 | if (ch > peak_l) | 143 | s = p[1]; |
146 | peak_l = ch; | 144 | |
147 | 145 | if (s < 0) | |
148 | #ifdef ROCKBOX_BIG_ENDIAN | 146 | s = -s; |
149 | ch = (int16_t)value; | 147 | |
150 | #else | 148 | if ((uint32_t)s > peak_r) |
151 | ch = value >> 16; | 149 | peak_r = s; |
152 | #endif | 150 | |
153 | if (ch < 0) | 151 | p += 4 * 2; /* Every 4th sample, interleaved */ |
154 | ch = -ch; | ||
155 | if (ch > peak_r) | ||
156 | peak_r = ch; | ||
157 | |||
158 | addr += 4; | ||
159 | } | 152 | } |
160 | while (addr < end); | 153 | while (p < pend); |
161 | 154 | ||
162 | peaks[0] = peak_l; | 155 | peaks->left = peak_l; |
163 | peaks[1] = peak_r; | 156 | peaks->right = peak_r; |
164 | } | 157 | } |
165 | 158 | ||
166 | void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active, | 159 | void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active, |
@@ -177,7 +170,7 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active, | |||
177 | else if (period > HZ/5) | 170 | else if (period > HZ/5) |
178 | period = HZ/5; | 171 | period = HZ/5; |
179 | 172 | ||
180 | peaks->period = (3*peaks->period + period) >> 2; | 173 | peaks->period = (3*peaks->period + period) / 4; |
181 | peaks->tick = tick; | 174 | peaks->tick = tick; |
182 | 175 | ||
183 | if (active) | 176 | if (active) |
@@ -186,29 +179,32 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active, | |||
186 | count = MIN(framecount, count); | 179 | count = MIN(framecount, count); |
187 | 180 | ||
188 | if (count > 0) | 181 | if (count > 0) |
189 | pcm_peak_peeker((int32_t *)addr, count, peaks->val); | 182 | pcm_peak_peeker(addr, count, peaks); |
190 | /* else keep previous peak values */ | 183 | /* else keep previous peak values */ |
191 | } | 184 | } |
192 | else | 185 | else |
193 | { | 186 | { |
194 | /* peaks are zero */ | 187 | /* peaks are zero */ |
195 | peaks->val[0] = peaks->val[1] = 0; | 188 | peaks->left = peaks->right = 0; |
196 | } | 189 | } |
197 | } | 190 | } |
198 | 191 | ||
199 | void pcm_calculate_peaks(int *left, int *right) | 192 | void pcm_calculate_peaks(int *left, int *right) |
200 | { | 193 | { |
194 | /* peak data for the global peak values - i.e. what the final output is */ | ||
195 | static struct pcm_peaks peaks; | ||
196 | |||
201 | int count; | 197 | int count; |
202 | const void *addr = pcm_play_dma_get_peak_buffer(&count); | 198 | const void *addr = pcm_play_dma_get_peak_buffer(&count); |
203 | 199 | ||
204 | pcm_do_peak_calculation(&global_peaks, pcm_playing && !pcm_paused, | 200 | pcm_do_peak_calculation(&peaks, pcm_playing && !pcm_paused, |
205 | addr, count); | 201 | addr, count); |
206 | 202 | ||
207 | if (left) | 203 | if (left) |
208 | *left = global_peaks.val[0]; | 204 | *left = peaks.left; |
209 | 205 | ||
210 | if (right) | 206 | if (right) |
211 | *right = global_peaks.val[1]; | 207 | *right = peaks.right; |
212 | } | 208 | } |
213 | 209 | ||
214 | const void* pcm_get_peak_buffer(int * count) | 210 | const void* pcm_get_peak_buffer(int * count) |
@@ -471,20 +467,20 @@ static void pcm_recording_stopped(void) | |||
471 | */ | 467 | */ |
472 | void pcm_calculate_rec_peaks(int *left, int *right) | 468 | void pcm_calculate_rec_peaks(int *left, int *right) |
473 | { | 469 | { |
474 | static uint16_t peaks[2]; | 470 | static struct pcm_peaks peaks; |
475 | 471 | ||
476 | if (pcm_recording) | 472 | if (pcm_recording) |
477 | { | 473 | { |
478 | const void *peak_addr = pcm_rec_peak_addr; | 474 | const int16_t *peak_addr = pcm_rec_peak_addr; |
479 | const void *addr = pcm_rec_dma_get_peak_buffer(); | 475 | const int16_t *addr = pcm_rec_dma_get_peak_buffer(); |
480 | 476 | ||
481 | if (addr != NULL) | 477 | if (addr != NULL) |
482 | { | 478 | { |
483 | int count = (int)(((intptr_t)addr - (intptr_t)peak_addr) >> 2); | 479 | int count = (addr - peak_addr) / 2; /* Interleaved L+R */ |
484 | 480 | ||
485 | if (count > 0) | 481 | if (count > 0) |
486 | { | 482 | { |
487 | pcm_peak_peeker((int32_t *)peak_addr, count, peaks); | 483 | pcm_peak_peeker(peak_addr, count, &peaks); |
488 | 484 | ||
489 | if (peak_addr == pcm_rec_peak_addr) | 485 | if (peak_addr == pcm_rec_peak_addr) |
490 | pcm_rec_peak_addr = addr; | 486 | pcm_rec_peak_addr = addr; |
@@ -494,15 +490,15 @@ void pcm_calculate_rec_peaks(int *left, int *right) | |||
494 | } | 490 | } |
495 | else | 491 | else |
496 | { | 492 | { |
497 | peaks[0] = peaks[1] = 0; | 493 | peaks.left = peaks.right = 0; |
498 | } | 494 | } |
499 | 495 | ||
500 | if (left) | 496 | if (left) |
501 | *left = peaks[0]; | 497 | *left = peaks.left; |
502 | 498 | ||
503 | if (right) | 499 | if (right) |
504 | *right = peaks[1]; | 500 | *right = peaks.right; |
505 | } /* pcm_calculate_rec_peaks */ | 501 | } |
506 | 502 | ||
507 | bool pcm_is_recording(void) | 503 | bool pcm_is_recording(void) |
508 | { | 504 | { |