summaryrefslogtreecommitdiff
path: root/firmware/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/pcm.c')
-rw-r--r--firmware/pcm.c92
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 */
103int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT; 103int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
104 104
105/* peak data for the global peak values - i.e. what the final output is */
106static struct pcm_peaks global_peaks;
107
108/* Called internally by functions to reset the state */ 105/* Called internally by functions to reset the state */
109static void pcm_play_stopped(void) 106static 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 */
128static void pcm_peak_peeker(const int32_t *addr, int count, uint16_t peaks[2]) 125static 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
166void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active, 159void 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
199void pcm_calculate_peaks(int *left, int *right) 192void 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
214const void* pcm_get_peak_buffer(int * count) 210const void* pcm_get_peak_buffer(int * count)
@@ -471,20 +467,20 @@ static void pcm_recording_stopped(void)
471 */ 467 */
472void pcm_calculate_rec_peaks(int *left, int *right) 468void 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
507bool pcm_is_recording(void) 503bool pcm_is_recording(void)
508{ 504{