diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2012-05-10 21:39:13 -0400 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2012-05-10 21:41:26 -0400 |
commit | 0e5dd0a9cff7e2fe72346d9c014a77a87ada1397 (patch) | |
tree | 77b3a84531cb6157ded617bf635f15bd7aa9b96e /lib/rbcodec/dsp | |
parent | 645680d62b82455d24fcb178f1cc5208f9942e38 (diff) | |
download | rockbox-0e5dd0a9cff7e2fe72346d9c014a77a87ada1397.tar.gz rockbox-0e5dd0a9cff7e2fe72346d9c014a77a87ada1397.zip |
TDSpeed: Fix up samples consumed return (FS#12666) + other stuff like...
Wrap up the the stereo case into loops and remove unused calculations
hanging out in tdspeed_update().
A wee little bit of code style and column policing.
Change-Id: I8dd3ab4b3e7e56b55dc00c00f3e32996228cc457
Diffstat (limited to 'lib/rbcodec/dsp')
-rw-r--r-- | lib/rbcodec/dsp/tdspeed.c | 194 |
1 files changed, 82 insertions, 112 deletions
diff --git a/lib/rbcodec/dsp/tdspeed.c b/lib/rbcodec/dsp/tdspeed.c index ea1013e049..7bf1a13ccb 100644 --- a/lib/rbcodec/dsp/tdspeed.c +++ b/lib/rbcodec/dsp/tdspeed.c | |||
@@ -54,7 +54,7 @@ static struct tdspeed_state_s | |||
54 | { | 54 | { |
55 | struct dsp_proc_entry *this; /* this stage */ | 55 | struct dsp_proc_entry *this; /* this stage */ |
56 | struct dsp_config *dsp; /* the DSP we use */ | 56 | struct dsp_config *dsp; /* the DSP we use */ |
57 | unsigned int channels; /* flags parameter to use in call */ | 57 | int channels; /* number of audio channels */ |
58 | int32_t samplerate; /* current samplerate of input data */ | 58 | int32_t samplerate; /* current samplerate of input data */ |
59 | int32_t factor; /* stretch factor (perdecimille) */ | 59 | int32_t factor; /* stretch factor (perdecimille) */ |
60 | int32_t shift_max; /* maximum displacement on a frame */ | 60 | int32_t shift_max; /* maximum displacement on a frame */ |
@@ -63,12 +63,13 @@ static struct tdspeed_state_s | |||
63 | int32_t dst_order; /* power of two for dst_step */ | 63 | int32_t dst_order; /* power of two for dst_step */ |
64 | int32_t ovl_shift; /* overlap buffer frame shift */ | 64 | int32_t ovl_shift; /* overlap buffer frame shift */ |
65 | int32_t ovl_size; /* overlap buffer used size */ | 65 | int32_t ovl_size; /* overlap buffer used size */ |
66 | int32_t ovl_space; /* overlap buffer size */ | ||
67 | int32_t *ovl_buff[2]; /* overlap buffer (L+R) */ | 66 | int32_t *ovl_buff[2]; /* overlap buffer (L+R) */ |
68 | } tdspeed_state; | 67 | } tdspeed_state; |
69 | 68 | ||
70 | static int32_t *buffers[NBUFFERS] = { NULL, NULL, NULL, NULL }; | 69 | static int32_t *buffers[NBUFFERS] = { NULL, NULL, NULL, NULL }; |
71 | static const int buffer_sizes[NBUFFERS] = { | 70 | |
71 | static const int buffer_sizes[NBUFFERS] = | ||
72 | { | ||
72 | FIXED_BUFCOUNT * sizeof(int32_t), | 73 | FIXED_BUFCOUNT * sizeof(int32_t), |
73 | FIXED_BUFCOUNT * sizeof(int32_t), | 74 | FIXED_BUFCOUNT * sizeof(int32_t), |
74 | FIXED_OUTBUFCOUNT * sizeof(int32_t), | 75 | FIXED_OUTBUFCOUNT * sizeof(int32_t), |
@@ -121,21 +122,8 @@ static bool tdspeed_update(int32_t samplerate, int32_t factor) | |||
121 | 122 | ||
122 | st->dst_step = (1 << st->dst_order); | 123 | st->dst_step = (1 << st->dst_order); |
123 | st->src_step = st->dst_step * factor / PITCH_SPEED_100; | 124 | st->src_step = st->dst_step * factor / PITCH_SPEED_100; |
124 | st->shift_max = (st->dst_step > st->src_step) ? st->dst_step : st->src_step; | 125 | st->shift_max = (st->dst_step > st->src_step) ? |
125 | 126 | st->dst_step : st->src_step; | |
126 | int src_frame_sz = st->shift_max + st->dst_step; | ||
127 | |||
128 | if (st->dst_step > st->src_step) | ||
129 | src_frame_sz += st->dst_step - st->src_step; | ||
130 | |||
131 | st->ovl_space = ((src_frame_sz - 2) / st->src_step) * st->src_step | ||
132 | + src_frame_sz; | ||
133 | |||
134 | if (st->src_step > st->dst_step) | ||
135 | st->ovl_space += 2*st->src_step - st->dst_step; | ||
136 | |||
137 | if (st->ovl_space > FIXED_BUFCOUNT) | ||
138 | st->ovl_space = FIXED_BUFCOUNT; | ||
139 | 127 | ||
140 | /* just discard remaining input data */ | 128 | /* just discard remaining input data */ |
141 | st->ovl_size = 0; | 129 | st->ovl_size = 0; |
@@ -151,28 +139,26 @@ static int tdspeed_apply(int32_t *buf_out[2], int32_t *buf_in[2], | |||
151 | int data_len, enum tdspeed_ops op, int *consumed) | 139 | int data_len, enum tdspeed_ops op, int *consumed) |
152 | /* data_len in samples */ | 140 | /* data_len in samples */ |
153 | { | 141 | { |
154 | struct tdspeed_state_s *st = &tdspeed_state; | 142 | struct tdspeed_state_s *const st = &tdspeed_state; |
155 | int32_t *dest[2]; | 143 | int32_t src_frame_sz = st->shift_max + st->dst_step; |
156 | int32_t next_frame, prev_frame, src_frame_sz; | ||
157 | bool stereo = st->channels > 1; | ||
158 | |||
159 | src_frame_sz = st->shift_max + st->dst_step; | ||
160 | 144 | ||
161 | if (st->dst_step > st->src_step) | 145 | if (st->dst_step > st->src_step) |
162 | src_frame_sz += st->dst_step - st->src_step; | 146 | src_frame_sz += st->dst_step - st->src_step; |
163 | 147 | ||
148 | int32_t *dest[2]; | ||
149 | int32_t next_frame, prev_frame; | ||
150 | |||
164 | /* deal with overlap data first, if any */ | 151 | /* deal with overlap data first, if any */ |
165 | if (st->ovl_size) | 152 | if (st->ovl_size) |
166 | { | 153 | { |
167 | int32_t have, copy, steps; | 154 | int32_t have = st->ovl_size; |
168 | have = st->ovl_size; | ||
169 | 155 | ||
170 | if (st->ovl_shift > 0) | 156 | if (st->ovl_shift > 0) |
171 | have -= st->ovl_shift; | 157 | have -= st->ovl_shift; |
172 | 158 | ||
173 | /* append just enough data to have all of the overlap buffer consumed */ | 159 | /* append just enough data to have all of the overlap buffer consumed */ |
174 | steps = (have - 1) / st->src_step; | 160 | int32_t steps = (have - 1) / st->src_step; |
175 | copy = steps * st->src_step + src_frame_sz - have; | 161 | int32_t copy = steps * st->src_step + src_frame_sz - have; |
176 | 162 | ||
177 | if (copy < src_frame_sz - st->dst_step) | 163 | if (copy < src_frame_sz - st->dst_step) |
178 | copy += st->src_step; /* one more step to allow for pregap data */ | 164 | copy += st->src_step; /* one more step to allow for pregap data */ |
@@ -181,14 +167,15 @@ static int tdspeed_apply(int32_t *buf_out[2], int32_t *buf_in[2], | |||
181 | copy = data_len; | 167 | copy = data_len; |
182 | 168 | ||
183 | assert(st->ovl_size + copy <= FIXED_BUFCOUNT); | 169 | assert(st->ovl_size + copy <= FIXED_BUFCOUNT); |
184 | memcpy(st->ovl_buff[0] + st->ovl_size, buf_in[0], | ||
185 | copy * sizeof(int32_t)); | ||
186 | 170 | ||
187 | if (stereo) | 171 | for (int ch = 0; ch < st->channels; ch++) |
188 | memcpy(st->ovl_buff[1] + st->ovl_size, buf_in[1], | 172 | { |
173 | memcpy(st->ovl_buff[ch] + st->ovl_size, buf_in[ch], | ||
189 | copy * sizeof(int32_t)); | 174 | copy * sizeof(int32_t)); |
175 | } | ||
190 | 176 | ||
191 | *consumed += copy; | 177 | if (consumed) |
178 | *consumed = copy; | ||
192 | 179 | ||
193 | if (op == TDSOP_PROCESS && have + copy < src_frame_sz) | 180 | if (op == TDSOP_PROCESS && have + copy < src_frame_sz) |
194 | { | 181 | { |
@@ -201,16 +188,16 @@ static int tdspeed_apply(int32_t *buf_out[2], int32_t *buf_in[2], | |||
201 | have = st->ovl_size; | 188 | have = st->ovl_size; |
202 | st->ovl_size = 0; | 189 | st->ovl_size = 0; |
203 | 190 | ||
191 | assert(have + copy <= FIXED_BUFCOUNT); | ||
192 | |||
204 | if (copy == data_len) | 193 | if (copy == data_len) |
205 | { | 194 | { |
206 | assert(have + copy <= FIXED_BUFCOUNT); | 195 | return tdspeed_apply(buf_out, st->ovl_buff, have + copy, |
207 | return tdspeed_apply(buf_out, st->ovl_buff, have+copy, op, | 196 | op, NULL); |
208 | consumed); | ||
209 | } | 197 | } |
210 | 198 | ||
211 | assert(have + copy <= FIXED_BUFCOUNT); | 199 | int i = tdspeed_apply(buf_out, st->ovl_buff, have + copy, |
212 | int i = tdspeed_apply(buf_out, st->ovl_buff, have+copy, | 200 | TDSOP_LAST, NULL); |
213 | TDSOP_LAST, consumed); | ||
214 | 201 | ||
215 | dest[0] = buf_out[0] + i; | 202 | dest[0] = buf_out[0] + i; |
216 | dest[1] = buf_out[1] + i; | 203 | dest[1] = buf_out[1] + i; |
@@ -227,9 +214,9 @@ static int tdspeed_apply(int32_t *buf_out[2], int32_t *buf_in[2], | |||
227 | next_frame = prev_frame = 0; | 214 | next_frame = prev_frame = 0; |
228 | 215 | ||
229 | if (st->ovl_shift > 0) | 216 | if (st->ovl_shift > 0) |
230 | next_frame += st->ovl_shift; | 217 | next_frame = st->ovl_shift; |
231 | else | 218 | else |
232 | prev_frame += -st->ovl_shift; | 219 | prev_frame = -st->ovl_shift; |
233 | } | 220 | } |
234 | 221 | ||
235 | st->ovl_shift = 0; | 222 | st->ovl_shift = 0; |
@@ -244,33 +231,20 @@ static int tdspeed_apply(int32_t *buf_out[2], int32_t *buf_in[2], | |||
244 | int64_t min_delta = INT64_MAX; /* most positive */ | 231 | int64_t min_delta = INT64_MAX; /* most positive */ |
245 | int shift = 0; | 232 | int shift = 0; |
246 | 233 | ||
247 | /* Power of 2 of a 28bit number requires 56bits, can accumulate | 234 | assert(next_frame + st->shift_max - 1 + st->dst_step <= data_len); |
248 | 256times in a 64bit variable. */ | 235 | assert(prev_frame + st->dst_step <= data_len); |
249 | assert(st->dst_step / INC2 <= 256); | ||
250 | assert(next_frame + st->shift_max - 1 + st->dst_step - 1 < data_len); | ||
251 | assert(prev_frame + st->dst_step - 1 < data_len); | ||
252 | 236 | ||
253 | for (int i = 0; i < st->shift_max; i += INC1) | 237 | for (int i = 0; i < st->shift_max; i += INC1) |
254 | { | 238 | { |
255 | int64_t delta = 0; | 239 | int64_t delta = 0; |
256 | 240 | ||
257 | int32_t *curr = buf_in[0] + next_frame + i; | 241 | for (int ch = 0; ch < st->channels; ch++) |
258 | int32_t *prev = buf_in[0] + prev_frame; | ||
259 | |||
260 | for (int j = 0; j < st->dst_step; j += INC2, curr += INC2, prev += INC2) | ||
261 | { | ||
262 | delta += ad_s32(*curr, *prev); | ||
263 | |||
264 | if (delta >= min_delta) | ||
265 | goto skip; | ||
266 | } | ||
267 | |||
268 | if (stereo) | ||
269 | { | 242 | { |
270 | curr = buf_in[1] + next_frame + i; | 243 | int32_t *curr = buf_in[ch] + next_frame + i; |
271 | prev = buf_in[1] + prev_frame; | 244 | int32_t *prev = buf_in[ch] + prev_frame; |
272 | 245 | ||
273 | for (int j = 0; j < st->dst_step; j += INC2, curr += INC2, prev += INC2) | 246 | for (int j = 0; j < st->dst_step; |
247 | j += INC2, curr += INC2, prev += INC2) | ||
274 | { | 248 | { |
275 | delta += ad_s32(*curr, *prev); | 249 | delta += ad_s32(*curr, *prev); |
276 | 250 | ||
@@ -285,39 +259,25 @@ skip:; | |||
285 | } | 259 | } |
286 | 260 | ||
287 | /* overlap fading-out previous frame with fading-in current frame */ | 261 | /* overlap fading-out previous frame with fading-in current frame */ |
288 | int32_t *curr = buf_in[0] + next_frame + shift; | 262 | for (int ch = 0; ch < st->channels; ch++) |
289 | int32_t *prev = buf_in[0] + prev_frame; | ||
290 | |||
291 | int32_t *d = dest[0]; | ||
292 | |||
293 | assert(next_frame + shift + st->dst_step - 1 < data_len); | ||
294 | assert(prev_frame + st->dst_step - 1 < data_len); | ||
295 | assert(dest[0] - buf_out[0] + st->dst_step - 1 < out_size); | ||
296 | |||
297 | for (int i = 0, j = st->dst_step; j; i++, j--) | ||
298 | { | ||
299 | *d++ = (*curr++ * (int64_t)i + | ||
300 | *prev++ * (int64_t)j) >> st->dst_order; | ||
301 | } | ||
302 | |||
303 | dest[0] = d; | ||
304 | |||
305 | if (stereo) | ||
306 | { | 263 | { |
307 | curr = buf_in[1] + next_frame + shift; | 264 | int32_t *curr = buf_in[ch] + next_frame + shift; |
308 | prev = buf_in[1] + prev_frame; | 265 | int32_t *prev = buf_in[ch] + prev_frame; |
266 | int32_t *d = dest[ch]; | ||
309 | 267 | ||
310 | d = dest[1]; | 268 | assert(next_frame + shift + st->dst_step <= data_len); |
269 | assert(prev_frame + st->dst_step <= data_len); | ||
270 | assert(dest[ch] - buf_out[ch] + st->dst_step <= out_size); | ||
311 | 271 | ||
312 | for (int i = 0, j = st->dst_step; j; i++, j--) | 272 | for (int i = 0, j = st->dst_step; j; i++, j--) |
313 | { | 273 | { |
314 | assert(d < buf_out[1] + out_size); | 274 | assert(d < buf_out[ch] + out_size); |
315 | 275 | ||
316 | *d++ = (*curr++ * (int64_t)i + | 276 | *d++ = (*curr++ * (int64_t)i + |
317 | *prev++ * (int64_t)j) >> st->dst_order; | 277 | *prev++ * (int64_t)j) >> st->dst_order; |
318 | } | 278 | } |
319 | 279 | ||
320 | dest[1] = d; | 280 | dest[ch] = d; |
321 | } | 281 | } |
322 | 282 | ||
323 | /* adjust pointers for next frame */ | 283 | /* adjust pointers for next frame */ |
@@ -326,46 +286,56 @@ skip:; | |||
326 | 286 | ||
327 | /* here next_frame - prev_frame = src_step - dst_step - shift */ | 287 | /* here next_frame - prev_frame = src_step - dst_step - shift */ |
328 | assert(next_frame - prev_frame == st->src_step - st->dst_step - shift); | 288 | assert(next_frame - prev_frame == st->src_step - st->dst_step - shift); |
329 | } | 289 | } /* while */ |
330 | 290 | ||
331 | /* now deal with remaining partial frames */ | 291 | /* now deal with remaining partial frames */ |
332 | if (op == TDSOP_LAST) | 292 | switch (op) |
293 | { | ||
294 | case TDSOP_PROCESS: | ||
295 | { | ||
296 | /* preserve remaining data + needed overlap data for next call */ | ||
297 | st->ovl_shift = next_frame - prev_frame; | ||
298 | int i = (st->ovl_shift < 0) ? next_frame : prev_frame; | ||
299 | st->ovl_size = data_len - i; | ||
300 | assert(st->ovl_size <= FIXED_BUFCOUNT); | ||
301 | |||
302 | for (int ch = 0; ch < st->channels; ch++) | ||
303 | { | ||
304 | memcpy(st->ovl_buff[ch], buf_in[ch] + i, | ||
305 | st->ovl_size * sizeof(int32_t)); | ||
306 | } | ||
307 | |||
308 | if (consumed) | ||
309 | *consumed = data_len; | ||
310 | |||
311 | break; | ||
312 | } /* TDSOP_PROCESS: */ | ||
313 | |||
314 | case TDSOP_LAST: | ||
333 | { | 315 | { |
334 | /* special overlap buffer processing: remember frame shift only */ | 316 | /* special overlap buffer processing: remember frame shift only */ |
335 | st->ovl_shift = next_frame - prev_frame; | 317 | st->ovl_shift = next_frame - prev_frame; |
336 | } | 318 | break; |
337 | else if (op == TDSOP_PURGE) | 319 | } /* TDSOP_LAST: */ |
320 | |||
321 | case TDSOP_PURGE: | ||
338 | { | 322 | { |
339 | /* last call: purge all remaining data to output buffer */ | 323 | /* last call: purge all remaining data to output buffer */ |
340 | int i = data_len - prev_frame; | 324 | int i = data_len - prev_frame; |
341 | 325 | ||
342 | assert(dest[0] + i <= buf_out[0] + out_size); | 326 | for (int ch = 0; ch < st->channels; ch++) |
343 | memcpy(dest[0], buf_in[0] + prev_frame, i * sizeof(int32_t)); | ||
344 | |||
345 | dest[0] += i; | ||
346 | |||
347 | if (stereo) | ||
348 | { | 327 | { |
349 | assert(dest[1] + i <= buf_out[1] + out_size); | 328 | assert(dest[ch] + i <= buf_out[ch] + out_size); |
350 | memcpy(dest[1], buf_in[1] + prev_frame, i * sizeof(int32_t)); | 329 | memcpy(dest[ch], buf_in[ch] + prev_frame, i * sizeof(int32_t)); |
351 | dest[1] += i; | 330 | dest[ch] += i; |
352 | } | 331 | } |
353 | 332 | ||
354 | *consumed += i; | 333 | if (consumed) |
355 | } | 334 | *consumed += i; |
356 | else | ||
357 | { | ||
358 | /* preserve remaining data + needed overlap data for next call */ | ||
359 | st->ovl_shift = next_frame - prev_frame; | ||
360 | int i = (st->ovl_shift < 0) ? next_frame : prev_frame; | ||
361 | st->ovl_size = data_len - i; | ||
362 | 335 | ||
363 | assert(st->ovl_size <= FIXED_BUFCOUNT); | 336 | break; |
364 | memcpy(st->ovl_buff[0], buf_in[0] + i, st->ovl_size * sizeof(int32_t)); | 337 | } /* TDSOP_PURGE: */ |
365 | 338 | } /* switch */ | |
366 | if (stereo) | ||
367 | memcpy(st->ovl_buff[1], buf_in[1] + i, st->ovl_size * sizeof(int32_t)); | ||
368 | } | ||
369 | 339 | ||
370 | return dest[0] - buf_out[0]; | 340 | return dest[0] - buf_out[0]; |
371 | } | 341 | } |
@@ -471,7 +441,7 @@ static void tdspeed_process_new_format(struct dsp_proc_entry *this, | |||
471 | struct tdspeed_state_s *st = &tdspeed_state; | 441 | struct tdspeed_state_s *st = &tdspeed_state; |
472 | struct dsp_config *dsp = st->dsp; | 442 | struct dsp_config *dsp = st->dsp; |
473 | struct sample_format *format = &src->format; | 443 | struct sample_format *format = &src->format; |
474 | unsigned int channels = format->num_channels; | 444 | int channels = format->num_channels; |
475 | 445 | ||
476 | if (format->codec_frequency != st->samplerate) | 446 | if (format->codec_frequency != st->samplerate) |
477 | { | 447 | { |