diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2012-12-19 17:34:57 -0500 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2013-05-04 13:43:33 -0400 |
commit | 78a45b47dede5ddf35dfc53e965b486a79177b18 (patch) | |
tree | edb3ad7c101e600a7cc3be4b40380430cbeb3e55 /lib/rbcodec/dsp/tdspeed.c | |
parent | cdb71c707bb434f44368b72f2db3becc37b7a46c (diff) | |
download | rockbox-78a45b47dede5ddf35dfc53e965b486a79177b18.tar.gz rockbox-78a45b47dede5ddf35dfc53e965b486a79177b18.zip |
Cleanup and simplify latest DSP code incarnation.
Some things can just be a bit simpler in handling the list of stages
and some things, especially format change handling, can be simplified
for each stage implementation. Format changes are sent through the
configure() callback.
Hide some internal details and variables from processing stages and
let the core deal with it.
Do some miscellaneous cleanup and keep things a bit better factored.
Change-Id: I19dd8ce1d0b792ba914d426013088a49a52ecb7e
Diffstat (limited to 'lib/rbcodec/dsp/tdspeed.c')
-rw-r--r-- | lib/rbcodec/dsp/tdspeed.c | 100 |
1 files changed, 44 insertions, 56 deletions
diff --git a/lib/rbcodec/dsp/tdspeed.c b/lib/rbcodec/dsp/tdspeed.c index 6a495bd989..e668c85032 100644 --- a/lib/rbcodec/dsp/tdspeed.c +++ b/lib/rbcodec/dsp/tdspeed.c | |||
@@ -53,7 +53,6 @@ enum tdspeed_ops | |||
53 | static struct tdspeed_state_s | 53 | 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 */ | ||
57 | int channels; /* number of audio channels */ | 56 | int channels; /* number of audio channels */ |
58 | int32_t samplerate; /* current samplerate of input data */ | 57 | int32_t samplerate; /* current samplerate of input data */ |
59 | int32_t factor; /* stretch factor (perdecimille) */ | 58 | int32_t factor; /* stretch factor (perdecimille) */ |
@@ -131,6 +130,10 @@ static bool tdspeed_update(int32_t samplerate, int32_t factor) | |||
131 | st->samplerate = samplerate; | 130 | st->samplerate = samplerate; |
132 | st->factor = factor; | 131 | st->factor = factor; |
133 | 132 | ||
133 | /* just discard remaining input data */ | ||
134 | st->ovl_size = 0; | ||
135 | st->ovl_shift = 0; | ||
136 | |||
134 | /* Check parameters */ | 137 | /* Check parameters */ |
135 | if (factor == PITCH_SPEED_100) | 138 | if (factor == PITCH_SPEED_100) |
136 | return false; | 139 | return false; |
@@ -161,10 +164,6 @@ static bool tdspeed_update(int32_t samplerate, int32_t factor) | |||
161 | st->shift_max = (st->dst_step > st->src_step) ? | 164 | st->shift_max = (st->dst_step > st->src_step) ? |
162 | st->dst_step : st->src_step; | 165 | st->dst_step : st->src_step; |
163 | 166 | ||
164 | /* just discard remaining input data */ | ||
165 | st->ovl_size = 0; | ||
166 | st->ovl_shift = 0; | ||
167 | |||
168 | st->ovl_buff[0] = overlap_buffer[0]; | 167 | st->ovl_buff[0] = overlap_buffer[0]; |
169 | st->ovl_buff[1] = overlap_buffer[1]; /* ignored if mono */ | 168 | st->ovl_buff[1] = overlap_buffer[1]; /* ignored if mono */ |
170 | 169 | ||
@@ -378,17 +377,14 @@ skip:; | |||
378 | 377 | ||
379 | /** DSP interface **/ | 378 | /** DSP interface **/ |
380 | 379 | ||
381 | static void tdspeed_process_new_format(struct dsp_proc_entry *this, | ||
382 | struct dsp_buffer **buf_p); | ||
383 | |||
384 | /* Enable or disable the availability of timestretch */ | 380 | /* Enable or disable the availability of timestretch */ |
385 | void dsp_timestretch_enable(bool enabled) | 381 | void dsp_timestretch_enable(bool enabled) |
386 | { | 382 | { |
387 | if (enabled != !tdspeed_state.this) | 383 | if (enabled != !tdspeed_state.this) |
388 | return; /* No change */ | 384 | return; /* No change */ |
389 | 385 | ||
390 | dsp_proc_enable(dsp_get_config(CODEC_IDX_AUDIO), DSP_PROC_TIMESTRETCH, | 386 | struct dsp_config *dsp = dsp_get_config(CODEC_IDX_AUDIO); |
391 | enabled); | 387 | dsp_proc_enable(dsp, DSP_PROC_TIMESTRETCH, enabled); |
392 | } | 388 | } |
393 | 389 | ||
394 | /* Set the timestretch ratio */ | 390 | /* Set the timestretch ratio */ |
@@ -405,7 +401,8 @@ void dsp_set_timestretch(int32_t percent) | |||
405 | if (percent == st->factor) | 401 | if (percent == st->factor) |
406 | return; /* no change */ | 402 | return; /* no change */ |
407 | 403 | ||
408 | dsp_configure(st->dsp, TIMESTRETCH_SET_FACTOR, percent); | 404 | struct dsp_config *dsp = dsp_get_config(CODEC_IDX_AUDIO); |
405 | dsp_configure(dsp, TIMESTRETCH_SET_FACTOR, percent); | ||
409 | } | 406 | } |
410 | 407 | ||
411 | /* Return the timestretch ratio */ | 408 | /* Return the timestretch ratio */ |
@@ -459,27 +456,22 @@ static void tdspeed_process(struct dsp_proc_entry *this, | |||
459 | } | 456 | } |
460 | 457 | ||
461 | /* Process format changes and settings changes */ | 458 | /* Process format changes and settings changes */ |
462 | static void tdspeed_process_new_format(struct dsp_proc_entry *this, | 459 | static intptr_t tdspeed_new_format(struct dsp_proc_entry *this, |
463 | struct dsp_buffer **buf_p) | 460 | struct dsp_config *dsp, |
461 | struct sample_format *format) | ||
464 | { | 462 | { |
465 | struct dsp_buffer *src = *buf_p; | ||
466 | struct dsp_buffer *dst = &dsp_outbuf; | 463 | struct dsp_buffer *dst = &dsp_outbuf; |
467 | 464 | ||
468 | if (dst->remcount > 0) | 465 | if (dst->remcount > 0) |
469 | { | 466 | return PROC_NEW_FORMAT_TRANSITION; |
470 | *buf_p = dst; | ||
471 | return; /* output remains from an earlier call */ | ||
472 | } | ||
473 | 467 | ||
474 | DSP_PRINT_FORMAT(DSP_PROC_TIMESTRETCH, DSP_PROC_TIMESTRETCH, src->format); | 468 | DSP_PRINT_FORMAT(DSP_PROC_TIMESTRETCH, *format); |
475 | 469 | ||
470 | bool active = dsp_proc_active(dsp, DSP_PROC_TIMESTRETCH); | ||
476 | struct tdspeed_state_s *st = &tdspeed_state; | 471 | struct tdspeed_state_s *st = &tdspeed_state; |
477 | struct dsp_config *dsp = st->dsp; | ||
478 | struct sample_format *format = &src->format; | ||
479 | int channels = format->num_channels; | 472 | int channels = format->num_channels; |
480 | 473 | ||
481 | if (format->codec_frequency != st->samplerate || | 474 | if (format->codec_frequency != st->samplerate) |
482 | !dsp_proc_active(dsp, DSP_PROC_TIMESTRETCH)) | ||
483 | { | 475 | { |
484 | /* relevent parameters are changing - all overlap will be discarded */ | 476 | /* relevent parameters are changing - all overlap will be discarded */ |
485 | st->channels = channels; | 477 | st->channels = channels; |
@@ -489,17 +481,10 @@ static void tdspeed_process_new_format(struct dsp_proc_entry *this, | |||
489 | channels, | 481 | channels, |
490 | format->codec_frequency, | 482 | format->codec_frequency, |
491 | st->factor / 100, st->factor % 100); | 483 | st->factor / 100, st->factor % 100); |
492 | bool active = tdspeed_update(format->codec_frequency, st->factor); | 484 | active = tdspeed_update(format->codec_frequency, st->factor); |
493 | dsp_proc_activate(dsp, DSP_PROC_TIMESTRETCH, active); | 485 | dsp_proc_activate(dsp, DSP_PROC_TIMESTRETCH, active); |
494 | |||
495 | if (!active) | ||
496 | { | ||
497 | DEBUGF(" DSP_PROC_RESAMPLE- not active\n"); | ||
498 | dst->format = src->format; /* Keep track */ | ||
499 | return; /* no more for now */ | ||
500 | } | ||
501 | } | 486 | } |
502 | else if (channels != st->channels) | 487 | else if (active && channels != st->channels) |
503 | { | 488 | { |
504 | /* channel count transistion - have to make old data in overlap | 489 | /* channel count transistion - have to make old data in overlap |
505 | buffer compatible with new format */ | 490 | buffer compatible with new format */ |
@@ -525,20 +510,25 @@ static void tdspeed_process_new_format(struct dsp_proc_entry *this, | |||
525 | } | 510 | } |
526 | } | 511 | } |
527 | 512 | ||
528 | struct sample_format f = *format; | 513 | dst->format = *format; |
529 | format_change_ack(format); | ||
530 | 514 | ||
531 | if (EQU_SAMPLE_FORMAT(f, dst->format)) | 515 | if (active) |
532 | { | 516 | return PROC_NEW_FORMAT_OK; |
533 | DEBUGF(" DSP_PROC_TIMESTRETCH- same dst format\n"); | ||
534 | format_change_ack(&f); /* nothing changed that matters downstream */ | ||
535 | } | ||
536 | 517 | ||
537 | dst->format = f; | 518 | /* Nothing to do */ |
519 | DEBUGF(" DSP_PROC_RESAMPLE- deactivated\n"); | ||
520 | return PROC_NEW_FORMAT_DEACTIVATED; | ||
538 | 521 | ||
539 | /* return to normal processing */ | 522 | (void)this; |
540 | this->process[0] = tdspeed_process; | 523 | } |
541 | dsp_proc_call(this, buf_p, 0); | 524 | |
525 | static void INIT_ATTR tdspeed_dsp_init(struct tdspeed_state_s *st, | ||
526 | enum dsp_ids dsp_id) | ||
527 | { | ||
528 | /* everything is at 100% until dsp_set_timestretch is called with | ||
529 | some other value and timestretch is enabled at the time */ | ||
530 | if (dsp_id == CODEC_IDX_AUDIO) | ||
531 | st->factor = PITCH_SPEED_100; | ||
542 | } | 532 | } |
543 | 533 | ||
544 | /* DSP message hook */ | 534 | /* DSP message hook */ |
@@ -547,15 +537,14 @@ static intptr_t tdspeed_configure(struct dsp_proc_entry *this, | |||
547 | unsigned int setting, | 537 | unsigned int setting, |
548 | intptr_t value) | 538 | intptr_t value) |
549 | { | 539 | { |
540 | intptr_t retval = 0; | ||
541 | |||
550 | struct tdspeed_state_s *st = &tdspeed_state; | 542 | struct tdspeed_state_s *st = &tdspeed_state; |
551 | 543 | ||
552 | switch (setting) | 544 | switch (setting) |
553 | { | 545 | { |
554 | case DSP_INIT: | 546 | case DSP_INIT: |
555 | /* everything is at 100% until dsp_set_timestretch is called with | 547 | tdspeed_dsp_init(st, (enum dsp_ids)value); |
556 | some other value and timestretch is enabled at the time */ | ||
557 | if (value == CODEC_IDX_AUDIO) | ||
558 | st->factor = PITCH_SPEED_100; | ||
559 | break; | 548 | break; |
560 | 549 | ||
561 | case DSP_FLUSH: | 550 | case DSP_FLUSH: |
@@ -567,10 +556,8 @@ static intptr_t tdspeed_configure(struct dsp_proc_entry *this, | |||
567 | return -1; /* fail the init */ | 556 | return -1; /* fail the init */ |
568 | 557 | ||
569 | st->this = this; | 558 | st->this = this; |
570 | st->dsp = dsp; | 559 | dsp_proc_set_in_place(dsp, DSP_PROC_TIMESTRETCH, false); |
571 | this->ip_mask = 0; /* not in-place */ | 560 | this->process = tdspeed_process; |
572 | this->process[0] = tdspeed_process; | ||
573 | this->process[1] = tdspeed_process_new_format; | ||
574 | break; | 561 | break; |
575 | 562 | ||
576 | case DSP_PROC_CLOSE: | 563 | case DSP_PROC_CLOSE: |
@@ -580,17 +567,18 @@ static intptr_t tdspeed_configure(struct dsp_proc_entry *this, | |||
580 | tdspeed_free_buffers(buffers, NBUFFERS); | 567 | tdspeed_free_buffers(buffers, NBUFFERS); |
581 | break; | 568 | break; |
582 | 569 | ||
570 | case DSP_PROC_NEW_FORMAT: | ||
571 | retval = tdspeed_new_format(this, dsp, (struct sample_format *)value); | ||
572 | break; | ||
573 | |||
583 | case TIMESTRETCH_SET_FACTOR: | 574 | case TIMESTRETCH_SET_FACTOR: |
584 | /* force update as a format change */ | ||
585 | st->samplerate = 0; | 575 | st->samplerate = 0; |
586 | st->factor = (int32_t)value; | 576 | st->factor = (int32_t)value; |
587 | st->this->process[0] = tdspeed_process_new_format; | 577 | dsp_proc_want_format_update(dsp, DSP_PROC_TIMESTRETCH); |
588 | dsp_proc_activate(st->dsp, DSP_PROC_TIMESTRETCH, true); | ||
589 | break; | 578 | break; |
590 | } | 579 | } |
591 | 580 | ||
592 | return 1; | 581 | return retval; |
593 | (void)value; | ||
594 | } | 582 | } |
595 | 583 | ||
596 | void tdspeed_move(int i, void* current, void* new) | 584 | void tdspeed_move(int i, void* current, void* new) |