diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2012-03-27 19:52:15 -0400 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2012-04-29 10:00:56 +0200 |
commit | c9bcbe202d010234f76d1046880a790fe2c3a067 (patch) | |
tree | 2f15438664ad1b196d6ed8b78065cd050d351956 /apps | |
parent | c9c13497736d8be077663f4458948f7bd526841b (diff) | |
download | rockbox-c9bcbe202d010234f76d1046880a790fe2c3a067.tar.gz rockbox-c9bcbe202d010234f76d1046880a790fe2c3a067.zip |
Fundamentally rewrite much of the audio DSP.
Creates a standard buffer passing, local data passing and messaging
system for processing stages. Stages can be moved to their own source
files to reduce clutter and ease assimilation of new ones. dsp.c
becomes dsp_core.c which supports an engine and framework for effects.
Formats and change notifications are passed along with the buffer so
that they arrive at the correct time at each stage in the chain
regardless of the internal delays of a particular one.
Removes restrictions on the number of samples that can be processed at
a time and it pays attention to destination buffer size restrictions
without having to limit input count, which also allows pcmbuf to
remain fuller and safely set its own buffer limits as it sees fit.
There is no longer a need to query input/output counts given a certain
number of input samples; just give it the sizes of the source and
destination buffers.
Works in harmony with stages that are not deterministic in terms of
sample input/output ratio (like both resamplers but most notably
the timestretch). As a result it fixes quirks with timestretch hanging
up with certain settings and it now operates properly throughout its
full settings range.
Change-Id: Ib206ec78f6f6c79259c5af9009fe021d68be9734
Reviewed-on: http://gerrit.rockbox.org/200
Reviewed-by: Michael Sevakis <jethead71@rockbox.org>
Tested-by: Michael Sevakis <jethead71@rockbox.org>
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codec_thread.c | 56 | ||||
-rw-r--r-- | apps/codecs.c | 2 | ||||
-rw-r--r-- | apps/gui/bitmap/list-skinned.c | 2 | ||||
-rw-r--r-- | apps/gui/bitmap/list.c | 2 | ||||
-rw-r--r-- | apps/gui/option_select.c | 1 | ||||
-rw-r--r-- | apps/main.c | 7 | ||||
-rw-r--r-- | apps/menus/eq_menu.c | 12 | ||||
-rw-r--r-- | apps/pcmbuf.c | 40 | ||||
-rw-r--r-- | apps/plugin.c | 12 | ||||
-rw-r--r-- | apps/plugin.h | 22 | ||||
-rw-r--r-- | apps/plugins/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/audio_thread.c | 56 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_settings.c | 8 | ||||
-rw-r--r-- | apps/plugins/test_codec.c | 51 | ||||
-rw-r--r-- | apps/settings.c | 11 | ||||
-rw-r--r-- | apps/settings.h | 18 | ||||
-rw-r--r-- | apps/settings_list.c | 2 | ||||
-rw-r--r-- | apps/voice_thread.c | 37 |
18 files changed, 181 insertions, 159 deletions
diff --git a/apps/codec_thread.c b/apps/codec_thread.c index 39db741054..17ca980e41 100644 --- a/apps/codec_thread.c +++ b/apps/codec_thread.c | |||
@@ -213,49 +213,41 @@ void codec_thread_do_callback(void (*fn)(void), unsigned int *id) | |||
213 | static void codec_pcmbuf_insert_callback( | 213 | static void codec_pcmbuf_insert_callback( |
214 | const void *ch1, const void *ch2, int count) | 214 | const void *ch1, const void *ch2, int count) |
215 | { | 215 | { |
216 | const char *src[2] = { ch1, ch2 }; | 216 | struct dsp_buffer src; |
217 | 217 | ||
218 | while (count > 0) | 218 | src.remcount = count; |
219 | src.pin[0] = ch1; | ||
220 | src.pin[1] = ch2; | ||
221 | src.proc_mask = 0; | ||
222 | |||
223 | while (1) | ||
219 | { | 224 | { |
220 | int out_count = dsp_output_count(ci.dsp, count); | 225 | struct dsp_buffer dst; |
221 | int inp_count; | 226 | dst.remcount = 0; |
222 | char *dest; | 227 | dst.bufcount = MAX(src.remcount, 1024); /* Arbitrary min request */ |
223 | 228 | ||
224 | while (1) | 229 | while ((dst.p16out = pcmbuf_request_buffer(&dst.bufcount)) == NULL) |
225 | { | 230 | { |
226 | if ((dest = pcmbuf_request_buffer(&out_count)) != NULL) | ||
227 | break; | ||
228 | |||
229 | cancel_cpu_boost(); | 231 | cancel_cpu_boost(); |
230 | 232 | ||
231 | /* It will be awhile before space is available but we want | 233 | /* It may be awhile before space is available but we want |
232 | "instant" response to any message */ | 234 | "instant" response to any message */ |
233 | queue_wait_w_tmo(&codec_queue, NULL, HZ/20); | 235 | queue_wait_w_tmo(&codec_queue, NULL, HZ/20); |
234 | 236 | ||
235 | if (!queue_empty(&codec_queue) && | 237 | if (!queue_empty(&codec_queue) && |
236 | codec_check_queue__have_msg() < 0) | 238 | codec_check_queue__have_msg() < 0) |
239 | { | ||
240 | dsp_configure(ci.dsp, DSP_FLUSH, 0); /* Discontinuity */ | ||
237 | return; | 241 | return; |
242 | } | ||
238 | } | 243 | } |
239 | 244 | ||
240 | /* Get the real input_size for output_size bytes, guarding | 245 | dsp_process(ci.dsp, &src, &dst); |
241 | * against resampling buffer overflows. */ | ||
242 | inp_count = dsp_input_count(ci.dsp, out_count); | ||
243 | |||
244 | if (inp_count <= 0) | ||
245 | return; | ||
246 | |||
247 | /* Input size has grown, no error, just don't write more than length */ | ||
248 | if (inp_count > count) | ||
249 | inp_count = count; | ||
250 | 246 | ||
251 | out_count = dsp_process(ci.dsp, dest, src, inp_count); | 247 | if (dst.remcount > 0) |
252 | 248 | pcmbuf_write_complete(dst.remcount, ci.id3->elapsed, ci.id3->offset); | |
253 | if (out_count <= 0) | 249 | else if (src.remcount <= 0) |
254 | return; | 250 | break; /* No input remains and DSP purged */ |
255 | |||
256 | pcmbuf_write_complete(out_count, ci.id3->elapsed, ci.id3->offset); | ||
257 | |||
258 | count -= inp_count; | ||
259 | } | 251 | } |
260 | } | 252 | } |
261 | 253 | ||
@@ -352,10 +344,7 @@ static void codec_seek_complete_callback(void) | |||
352 | 344 | ||
353 | static void codec_configure_callback(int setting, intptr_t value) | 345 | static void codec_configure_callback(int setting, intptr_t value) |
354 | { | 346 | { |
355 | if (!dsp_configure(ci.dsp, setting, value)) | 347 | dsp_configure(ci.dsp, setting, value); |
356 | { | ||
357 | logf("Illegal key: %d", setting); | ||
358 | } | ||
359 | } | 348 | } |
360 | 349 | ||
361 | static enum codec_command_action | 350 | static enum codec_command_action |
@@ -611,8 +600,7 @@ static void NORETURN_ATTR codec_thread(void) | |||
611 | void codec_thread_init(void) | 600 | void codec_thread_init(void) |
612 | { | 601 | { |
613 | /* Init API */ | 602 | /* Init API */ |
614 | ci.dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP, | 603 | ci.dsp = dsp_get_config(CODEC_IDX_AUDIO); |
615 | CODEC_IDX_AUDIO); | ||
616 | ci.codec_get_buffer = codec_get_buffer_callback; | 604 | ci.codec_get_buffer = codec_get_buffer_callback; |
617 | ci.pcmbuf_insert = codec_pcmbuf_insert_callback; | 605 | ci.pcmbuf_insert = codec_pcmbuf_insert_callback; |
618 | ci.set_elapsed = audio_codec_update_elapsed; | 606 | ci.set_elapsed = audio_codec_update_elapsed; |
diff --git a/apps/codecs.c b/apps/codecs.c index fafe4ac7a3..69204b7c4f 100644 --- a/apps/codecs.c +++ b/apps/codecs.c | |||
@@ -118,6 +118,7 @@ struct codec_api ci = { | |||
118 | 118 | ||
119 | commit_dcache, | 119 | commit_dcache, |
120 | commit_discard_dcache, | 120 | commit_discard_dcache, |
121 | commit_discard_idcache, | ||
121 | 122 | ||
122 | /* strings and memory */ | 123 | /* strings and memory */ |
123 | strcpy, | 124 | strcpy, |
@@ -166,7 +167,6 @@ struct codec_api ci = { | |||
166 | /* new stuff at the end, sort into place next time | 167 | /* new stuff at the end, sort into place next time |
167 | the API gets incompatible */ | 168 | the API gets incompatible */ |
168 | 169 | ||
169 | commit_discard_idcache, | ||
170 | }; | 170 | }; |
171 | 171 | ||
172 | void codec_get_full_path(char *path, const char *codec_root_fn) | 172 | void codec_get_full_path(char *path, const char *codec_root_fn) |
diff --git a/apps/gui/bitmap/list-skinned.c b/apps/gui/bitmap/list-skinned.c index 95430ae278..7d3620ed81 100644 --- a/apps/gui/bitmap/list-skinned.c +++ b/apps/gui/bitmap/list-skinned.c | |||
@@ -20,13 +20,13 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "system.h" | ||
23 | #include "lcd.h" | 24 | #include "lcd.h" |
24 | #include "font.h" | 25 | #include "font.h" |
25 | #include "button.h" | 26 | #include "button.h" |
26 | #include "string.h" | 27 | #include "string.h" |
27 | #include "settings.h" | 28 | #include "settings.h" |
28 | #include "kernel.h" | 29 | #include "kernel.h" |
29 | #include "system.h" | ||
30 | #include "file.h" | 30 | #include "file.h" |
31 | 31 | ||
32 | #include "action.h" | 32 | #include "action.h" |
diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c index 0581050091..49479c1cb3 100644 --- a/apps/gui/bitmap/list.c +++ b/apps/gui/bitmap/list.c | |||
@@ -22,13 +22,13 @@ | |||
22 | /* This file contains the code to draw the list widget on BITMAP LCDs. */ | 22 | /* This file contains the code to draw the list widget on BITMAP LCDs. */ |
23 | 23 | ||
24 | #include "config.h" | 24 | #include "config.h" |
25 | #include "system.h" | ||
25 | #include "lcd.h" | 26 | #include "lcd.h" |
26 | #include "font.h" | 27 | #include "font.h" |
27 | #include "button.h" | 28 | #include "button.h" |
28 | #include "string.h" | 29 | #include "string.h" |
29 | #include "settings.h" | 30 | #include "settings.h" |
30 | #include "kernel.h" | 31 | #include "kernel.h" |
31 | #include "system.h" | ||
32 | #include "file.h" | 32 | #include "file.h" |
33 | 33 | ||
34 | #include "action.h" | 34 | #include "action.h" |
diff --git a/apps/gui/option_select.c b/apps/gui/option_select.c index 7c3d34f024..ca206b86da 100644 --- a/apps/gui/option_select.c +++ b/apps/gui/option_select.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <stdlib.h> | 22 | #include <stdlib.h> |
23 | #include "string-extra.h" | 23 | #include "string-extra.h" |
24 | #include "config.h" | 24 | #include "config.h" |
25 | #include "system.h" | ||
25 | #include "option_select.h" | 26 | #include "option_select.h" |
26 | #include "kernel.h" | 27 | #include "kernel.h" |
27 | #include "lang.h" | 28 | #include "lang.h" |
diff --git a/apps/main.c b/apps/main.c index 631236852e..0fff0846a6 100644 --- a/apps/main.c +++ b/apps/main.c | |||
@@ -384,6 +384,9 @@ static void init(void) | |||
384 | viewportmanager_init(); | 384 | viewportmanager_init(); |
385 | 385 | ||
386 | storage_init(); | 386 | storage_init(); |
387 | #if CONFIG_CODEC == SWCODEC | ||
388 | dsp_init(); | ||
389 | #endif | ||
387 | settings_reset(); | 390 | settings_reset(); |
388 | settings_load(SETTINGS_ALL); | 391 | settings_load(SETTINGS_ALL); |
389 | settings_apply(true); | 392 | settings_apply(true); |
@@ -632,6 +635,10 @@ static void init(void) | |||
632 | } | 635 | } |
633 | } | 636 | } |
634 | 637 | ||
638 | #if CONFIG_CODEC == SWCODEC | ||
639 | dsp_init(); | ||
640 | #endif | ||
641 | |||
635 | #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \ | 642 | #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \ |
636 | (CONFIG_KEYPAD == IRIVER_H10_PAD) | 643 | (CONFIG_KEYPAD == IRIVER_H10_PAD) |
637 | #ifdef SETTINGS_RESET | 644 | #ifdef SETTINGS_RESET |
diff --git a/apps/menus/eq_menu.c b/apps/menus/eq_menu.c index 2cfb80f76a..60b2687050 100644 --- a/apps/menus/eq_menu.c +++ b/apps/menus/eq_menu.c | |||
@@ -70,13 +70,11 @@ const char* eq_precut_format(char* buffer, size_t buffer_size, int value, const | |||
70 | */ | 70 | */ |
71 | static void eq_apply(void) | 71 | static void eq_apply(void) |
72 | { | 72 | { |
73 | dsp_set_eq(global_settings.eq_enabled); | 73 | dsp_eq_enable(global_settings.eq_enabled); |
74 | dsp_set_eq_precut(global_settings.eq_precut); | 74 | dsp_set_eq_precut(global_settings.eq_precut); |
75 | /* Update all bands */ | 75 | /* Update all bands */ |
76 | for(int i = 0; i < 5; i++) { | 76 | for(int i = 0; i < EQ_NUM_BANDS; i++) { |
77 | dsp_set_eq_coefs(i, global_settings.eq_band_settings[i].cutoff, | 77 | dsp_set_eq_coefs(i, &global_settings.eq_band_settings[i]); |
78 | global_settings.eq_band_settings[i].q, | ||
79 | global_settings.eq_band_settings[i].gain); | ||
80 | } | 78 | } |
81 | } | 79 | } |
82 | 80 | ||
@@ -580,9 +578,7 @@ bool eq_menu_graphical(void) | |||
580 | /* Update the filter if the user changed something */ | 578 | /* Update the filter if the user changed something */ |
581 | if (has_changed) { | 579 | if (has_changed) { |
582 | dsp_set_eq_coefs(current_band, | 580 | dsp_set_eq_coefs(current_band, |
583 | global_settings.eq_band_settings[current_band].cutoff, | 581 | &global_settings.eq_band_settings[current_band]); |
584 | global_settings.eq_band_settings[current_band].q, | ||
585 | global_settings.eq_band_settings[current_band].gain); | ||
586 | has_changed = false; | 582 | has_changed = false; |
587 | } | 583 | } |
588 | } | 584 | } |
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index d36883fc5b..9cedae0b67 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -47,16 +47,23 @@ | |||
47 | smaller math - must be < 65536 bytes */ | 47 | smaller math - must be < 65536 bytes */ |
48 | #define PCMBUF_CHUNK_SIZE 8192u | 48 | #define PCMBUF_CHUNK_SIZE 8192u |
49 | 49 | ||
50 | /* Massive size is a nasty temp fix */ | 50 | /* Small guard buf to give decent space near end */ |
51 | #define PCMBUF_GUARD_SIZE (1024u*12*((NATIVE_FREQUENCY+7999)/8000)) | 51 | #define PCMBUF_GUARD_SIZE (PCMBUF_CHUNK_SIZE / 8) |
52 | 52 | ||
53 | /* Mnemonics for common data commit thresholds */ | 53 | /* Mnemonics for common data commit thresholds */ |
54 | #define COMMIT_CHUNKS PCMBUF_CHUNK_SIZE | 54 | #define COMMIT_CHUNKS PCMBUF_CHUNK_SIZE |
55 | #define COMMIT_ALL_DATA 1u | 55 | #define COMMIT_ALL_DATA 1u |
56 | 56 | ||
57 | /* Size of the crossfade buffer where codec data is written to be faded | 57 | /* Size of the crossfade buffer where codec data is written to be faded |
58 | on commit */ | 58 | on commit */ |
59 | #define CROSSFADE_BUFSIZE 8192u | 59 | #define CROSSFADE_BUFSIZE PCMBUF_CHUNK_SIZE |
60 | |||
61 | /* Maximum contiguous space that PCM buffer will allow (to avoid excessive | ||
62 | draining between inserts and observe low-latency mode) */ | ||
63 | #define PCMBUF_MAX_BUFFER (PCMBUF_CHUNK_SIZE * 4) | ||
64 | |||
65 | /* Forced buffer insert constraint can thus be from 1KB to 32KB using 8KB | ||
66 | chunks */ | ||
60 | 67 | ||
61 | /* Return data level in 1/4-second increments */ | 68 | /* Return data level in 1/4-second increments */ |
62 | #define DATA_LEVEL(quarter_secs) (NATIVE_FREQUENCY * (quarter_secs)) | 69 | #define DATA_LEVEL(quarter_secs) (NATIVE_FREQUENCY * (quarter_secs)) |
@@ -383,7 +390,11 @@ void * pcmbuf_request_buffer(int *count) | |||
383 | /* If crossfade has begun, put the new track samples in crossfade_buffer */ | 390 | /* If crossfade has begun, put the new track samples in crossfade_buffer */ |
384 | if (crossfade_status != CROSSFADE_INACTIVE && size > CROSSFADE_BUFSIZE) | 391 | if (crossfade_status != CROSSFADE_INACTIVE && size > CROSSFADE_BUFSIZE) |
385 | size = CROSSFADE_BUFSIZE; | 392 | size = CROSSFADE_BUFSIZE; |
386 | #endif | 393 | else |
394 | #endif /* HAVE_CROSSFADE */ | ||
395 | |||
396 | if (size > PCMBUF_MAX_BUFFER) | ||
397 | size = PCMBUF_MAX_BUFFER; /* constrain */ | ||
387 | 398 | ||
388 | enum channel_status status = mixer_channel_status(PCM_MIXER_CHAN_PLAYBACK); | 399 | enum channel_status status = mixer_channel_status(PCM_MIXER_CHAN_PLAYBACK); |
389 | size_t remaining = pcmbuf_unplayed_bytes(); | 400 | size_t remaining = pcmbuf_unplayed_bytes(); |
@@ -432,11 +443,22 @@ void * pcmbuf_request_buffer(int *count) | |||
432 | pcmbuf_play_start(); | 443 | pcmbuf_play_start(); |
433 | } | 444 | } |
434 | 445 | ||
435 | void *buf = | 446 | void *buf; |
447 | |||
436 | #ifdef HAVE_CROSSFADE | 448 | #ifdef HAVE_CROSSFADE |
437 | crossfade_status != CROSSFADE_INACTIVE ? crossfade_buffer : | 449 | if (crossfade_status != CROSSFADE_INACTIVE) |
450 | { | ||
451 | buf = crossfade_buffer; /* always CROSSFADE_BUFSIZE */ | ||
452 | } | ||
453 | else | ||
438 | #endif | 454 | #endif |
439 | get_write_buffer(&size); | 455 | { |
456 | /* Give the maximum amount available if there's more */ | ||
457 | if (size + PCMBUF_CHUNK_SIZE < freespace) | ||
458 | size = freespace - PCMBUF_CHUNK_SIZE; | ||
459 | |||
460 | buf = get_write_buffer(&size); | ||
461 | } | ||
440 | 462 | ||
441 | *count = size / 4; | 463 | *count = size / 4; |
442 | return buf; | 464 | return buf; |
diff --git a/apps/plugin.c b/apps/plugin.c index 5406610e23..129fd6954e 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -565,13 +565,15 @@ static const struct plugin_api rockbox_api = { | |||
565 | audio_set_output_source, | 565 | audio_set_output_source, |
566 | audio_set_input_source, | 566 | audio_set_input_source, |
567 | #endif | 567 | #endif |
568 | dsp_set_crossfeed, | 568 | dsp_crossfeed_enable, |
569 | dsp_set_eq, | 569 | dsp_eq_enable, |
570 | dsp_dither_enable, | 570 | dsp_dither_enable, |
571 | #ifdef HAVE_PITCHSCREEN | ||
572 | dsp_set_timestretch, | ||
573 | #endif | ||
571 | dsp_configure, | 574 | dsp_configure, |
575 | dsp_get_config, | ||
572 | dsp_process, | 576 | dsp_process, |
573 | dsp_input_count, | ||
574 | dsp_output_count, | ||
575 | 577 | ||
576 | mixer_channel_status, | 578 | mixer_channel_status, |
577 | mixer_channel_get_buffer, | 579 | mixer_channel_get_buffer, |
@@ -584,7 +586,7 @@ static const struct plugin_api rockbox_api = { | |||
584 | 586 | ||
585 | system_sound_play, | 587 | system_sound_play, |
586 | keyclick_click, | 588 | keyclick_click, |
587 | #endif | 589 | #endif /* CONFIG_CODEC == SWCODEC */ |
588 | /* playback control */ | 590 | /* playback control */ |
589 | playlist_amount, | 591 | playlist_amount, |
590 | playlist_resume, | 592 | playlist_resume, |
diff --git a/apps/plugin.h b/apps/plugin.h index 8123414ff0..3820c7ede6 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -153,12 +153,12 @@ void* plugin_get_buffer(size_t *buffer_size); | |||
153 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ | 153 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ |
154 | 154 | ||
155 | /* increase this every time the api struct changes */ | 155 | /* increase this every time the api struct changes */ |
156 | #define PLUGIN_API_VERSION 218 | 156 | #define PLUGIN_API_VERSION 219 |
157 | 157 | ||
158 | /* update this to latest version if a change to the api struct breaks | 158 | /* update this to latest version if a change to the api struct breaks |
159 | backwards compatibility (and please take the opportunity to sort in any | 159 | backwards compatibility (and please take the opportunity to sort in any |
160 | new function which are "waiting" at the end of the function table) */ | 160 | new function which are "waiting" at the end of the function table) */ |
161 | #define PLUGIN_MIN_API_VERSION 218 | 161 | #define PLUGIN_MIN_API_VERSION 219 |
162 | 162 | ||
163 | /* plugin return codes */ | 163 | /* plugin return codes */ |
164 | /* internal returns start at 0x100 to make exit(1..255) work */ | 164 | /* internal returns start at 0x100 to make exit(1..255) work */ |
@@ -680,15 +680,17 @@ struct plugin_api { | |||
680 | void (*audio_set_output_source)(int monitor); | 680 | void (*audio_set_output_source)(int monitor); |
681 | void (*audio_set_input_source)(int source, unsigned flags); | 681 | void (*audio_set_input_source)(int source, unsigned flags); |
682 | #endif | 682 | #endif |
683 | void (*dsp_set_crossfeed)(bool enable); | 683 | void (*dsp_crossfeed_enable)(bool enable); |
684 | void (*dsp_set_eq)(bool enable); | 684 | void (*dsp_eq_enable)(bool enable); |
685 | void (*dsp_dither_enable)(bool enable); | 685 | void (*dsp_dither_enable)(bool enable); |
686 | intptr_t (*dsp_configure)(struct dsp_config *dsp, int setting, | 686 | #ifdef HAVE_PITCHSCREEN |
687 | intptr_t value); | 687 | void (*dsp_set_timestretch)(int32_t percent); |
688 | int (*dsp_process)(struct dsp_config *dsp, char *dest, | 688 | #endif |
689 | const char *src[], int count); | 689 | intptr_t (*dsp_configure)(struct dsp_config *dsp, |
690 | int (*dsp_input_count)(struct dsp_config *dsp, int count); | 690 | unsigned int setting, intptr_t value); |
691 | int (*dsp_output_count)(struct dsp_config *dsp, int count); | 691 | struct dsp_config * (*dsp_get_config)(enum dsp_ids id); |
692 | void (*dsp_process)(struct dsp_config *dsp, struct dsp_buffer *src, | ||
693 | struct dsp_buffer *dst); | ||
692 | 694 | ||
693 | enum channel_status (*mixer_channel_status)(enum pcm_mixer_channel channel); | 695 | enum channel_status (*mixer_channel_status)(enum pcm_mixer_channel channel); |
694 | const void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel, | 696 | const void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel, |
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index db690a638a..e5f026c5b4 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES | |||
@@ -33,6 +33,7 @@ flipit.c | |||
33 | shopper.c | 33 | shopper.c |
34 | resistor.c | 34 | resistor.c |
35 | 35 | ||
36 | test_codec.c | ||
36 | 37 | ||
37 | #ifdef USB_ENABLE_HID | 38 | #ifdef USB_ENABLE_HID |
38 | remote_control.c | 39 | remote_control.c |
diff --git a/apps/plugins/mpegplayer/audio_thread.c b/apps/plugins/mpegplayer/audio_thread.c index f976fd6007..b06727f759 100644 --- a/apps/plugins/mpegplayer/audio_thread.c +++ b/apps/plugins/mpegplayer/audio_thread.c | |||
@@ -36,6 +36,7 @@ struct audio_thread_data | |||
36 | unsigned samplerate; /* Current stream sample rate */ | 36 | unsigned samplerate; /* Current stream sample rate */ |
37 | int nchannels; /* Number of audio channels */ | 37 | int nchannels; /* Number of audio channels */ |
38 | struct dsp_config *dsp; /* The DSP we're using */ | 38 | struct dsp_config *dsp; /* The DSP we're using */ |
39 | struct dsp_buffer src; /* Current audio data for DSP processing */ | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | /* The audio thread is stolen from the core codec thread */ | 42 | /* The audio thread is stolen from the core codec thread */ |
@@ -479,12 +480,13 @@ static void audio_thread(void) | |||
479 | /* We need this here to init the EMAC for Coldfire targets */ | 480 | /* We need this here to init the EMAC for Coldfire targets */ |
480 | init_mad(); | 481 | init_mad(); |
481 | 482 | ||
482 | td.dsp = (struct dsp_config *)rb->dsp_configure(NULL, DSP_MYDSP, | 483 | td.dsp = rb->dsp_get_config(CODEC_IDX_AUDIO); |
483 | CODEC_IDX_AUDIO); | ||
484 | #ifdef HAVE_PITCHSCREEN | 484 | #ifdef HAVE_PITCHSCREEN |
485 | rb->sound_set_pitch(PITCH_SPEED_100); | 485 | rb->sound_set_pitch(PITCH_SPEED_100); |
486 | rb->dsp_set_timestretch(PITCH_SPEED_100); | ||
486 | #endif | 487 | #endif |
487 | rb->dsp_configure(td.dsp, DSP_RESET, 0); | 488 | rb->dsp_configure(td.dsp, DSP_RESET, 0); |
489 | rb->dsp_configure(td.dsp, DSP_FLUSH, 0); | ||
488 | rb->dsp_configure(td.dsp, DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); | 490 | rb->dsp_configure(td.dsp, DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); |
489 | 491 | ||
490 | goto message_wait; | 492 | goto message_wait; |
@@ -631,43 +633,53 @@ static void audio_thread(void) | |||
631 | STEREO_MONO : STEREO_NONINTERLEAVED); | 633 | STEREO_MONO : STEREO_NONINTERLEAVED); |
632 | } | 634 | } |
633 | 635 | ||
636 | td.src.remcount = synth.pcm.length; | ||
637 | td.src.pin[0] = synth.pcm.samples[0]; | ||
638 | td.src.pin[1] = synth.pcm.samples[1]; | ||
639 | td.src.proc_mask = 0; | ||
640 | |||
634 | td.state = TSTATE_RENDER_WAIT; | 641 | td.state = TSTATE_RENDER_WAIT; |
635 | 642 | ||
636 | /* Add a frame of audio to the pcm buffer. Maximum is 1152 samples. */ | 643 | /* Add a frame of audio to the pcm buffer. Maximum is 1152 samples. */ |
637 | render_wait: | 644 | render_wait: |
638 | if (synth.pcm.length > 0) | 645 | rb->yield(); |
646 | |||
647 | while (1) | ||
639 | { | 648 | { |
640 | const char *src[2] = | 649 | struct dsp_buffer dst; |
641 | { (char *)synth.pcm.samples[0], (char *)synth.pcm.samples[1] }; | 650 | dst.remcount = 0; |
642 | int out_count = (synth.pcm.length * CLOCK_RATE | 651 | dst.bufcount = MAX(td.src.remcount, 1024); |
643 | + (td.samplerate - 1)) / td.samplerate; | 652 | |
644 | unsigned char *out_buf; | 653 | ssize_t size = dst.bufcount * 2 * sizeof(int16_t); |
645 | ssize_t size = out_count*4; | ||
646 | 654 | ||
647 | /* Wait for required amount of free buffer space */ | 655 | /* Wait for required amount of free buffer space */ |
648 | while ((out_buf = pcm_output_get_buffer(&size)) == NULL) | 656 | while ((dst.p16out = pcm_output_get_buffer(&size)) == NULL) |
649 | { | 657 | { |
650 | /* Wait one frame */ | 658 | /* Wait one frame */ |
651 | int timeout = out_count*HZ / td.samplerate; | 659 | int timeout = dst.bufcount*HZ / td.samplerate; |
652 | str_get_msg_w_tmo(&audio_str, &td.ev, MAX(timeout, 1)); | 660 | str_get_msg_w_tmo(&audio_str, &td.ev, MAX(timeout, 1)); |
653 | if (td.ev.id != SYS_TIMEOUT) | 661 | if (td.ev.id != SYS_TIMEOUT) |
654 | goto message_process; | 662 | goto message_process; |
655 | } | 663 | } |
656 | 664 | ||
657 | out_count = rb->dsp_process(td.dsp, out_buf, src, synth.pcm.length); | 665 | dst.bufcount = size / (2 * sizeof (int16_t)); |
666 | rb->dsp_process(td.dsp, &td.src, &dst); | ||
658 | 667 | ||
659 | if (out_count <= 0) | 668 | if (dst.remcount > 0) |
660 | break; | 669 | { |
661 | 670 | /* Make this data available to DMA */ | |
662 | /* Make this data available to DMA */ | 671 | pcm_output_commit_data(dst.remcount * 2 * sizeof(int16_t), |
663 | pcm_output_commit_data(out_count*4, audio_queue.curr->time); | 672 | audio_queue.curr->time); |
664 | 673 | ||
665 | /* As long as we're on this timestamp, the time is just | 674 | /* As long as we're on this timestamp, the time is just |
666 | incremented by the number of samples */ | 675 | incremented by the number of samples */ |
667 | audio_queue.curr->time += out_count; | 676 | audio_queue.curr->time += dst.remcount; |
677 | } | ||
678 | else if (td.src.remcount <= 0) | ||
679 | { | ||
680 | break; | ||
681 | } | ||
668 | } | 682 | } |
669 | |||
670 | rb->yield(); | ||
671 | } /* end decoding loop */ | 683 | } /* end decoding loop */ |
672 | } | 684 | } |
673 | 685 | ||
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c index 1c3f3c0b92..7f92fb7c69 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.c +++ b/apps/plugins/mpegplayer/mpeg_settings.c | |||
@@ -457,13 +457,13 @@ static void sync_audio_setting(int setting, bool global) | |||
457 | break; | 457 | break; |
458 | 458 | ||
459 | case MPEG_AUDIO_CROSSFEED: | 459 | case MPEG_AUDIO_CROSSFEED: |
460 | rb->dsp_set_crossfeed((global || settings.crossfeed) ? | 460 | rb->dsp_crossfeed_enable((global || settings.crossfeed) ? |
461 | rb->global_settings->crossfeed : false); | 461 | rb->global_settings->crossfeed : false); |
462 | break; | 462 | break; |
463 | 463 | ||
464 | case MPEG_AUDIO_EQUALIZER: | 464 | case MPEG_AUDIO_EQUALIZER: |
465 | rb->dsp_set_eq((global || settings.equalizer) ? | 465 | rb->dsp_eq_enable((global || settings.equalizer) ? |
466 | rb->global_settings->eq_enabled : false); | 466 | rb->global_settings->eq_enabled : false); |
467 | break; | 467 | break; |
468 | 468 | ||
469 | case MPEG_AUDIO_DITHERING: | 469 | case MPEG_AUDIO_DITHERING: |
diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index dafcf35710..920be54d56 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c | |||
@@ -164,6 +164,7 @@ static inline void int2le16(unsigned char* buf, int16_t x) | |||
164 | 164 | ||
165 | static unsigned char *wavbuffer; | 165 | static unsigned char *wavbuffer; |
166 | static unsigned char *dspbuffer; | 166 | static unsigned char *dspbuffer; |
167 | static int dspbuffer_count; | ||
167 | 168 | ||
168 | void init_wav(char* filename) | 169 | void init_wav(char* filename) |
169 | { | 170 | { |
@@ -215,34 +216,31 @@ static void* codec_get_buffer(size_t *size) | |||
215 | 216 | ||
216 | static int process_dsp(const void *ch1, const void *ch2, int count) | 217 | static int process_dsp(const void *ch1, const void *ch2, int count) |
217 | { | 218 | { |
218 | const char *src[2] = { ch1, ch2 }; | 219 | struct dsp_buffer src; |
219 | int written_count = 0; | 220 | src.remcount = count; |
220 | char *dest = dspbuffer; | 221 | src.pin[0] = ch1; |
221 | 222 | src.pin[1] = ch2; | |
222 | while (count > 0) | 223 | src.proc_mask = 0; |
224 | |||
225 | struct dsp_buffer dst; | ||
226 | dst.remcount = 0; | ||
227 | dst.p16out = (int16_t *)dspbuffer; | ||
228 | dst.bufcount = dspbuffer_count; | ||
229 | |||
230 | while (1) | ||
223 | { | 231 | { |
224 | int out_count = rb->dsp_output_count(ci.dsp, count); | 232 | int old_remcount = dst.remcount; |
225 | 233 | rb->dsp_process(ci.dsp, &src, &dst); | |
226 | int inp_count = rb->dsp_input_count(ci.dsp, out_count); | ||
227 | |||
228 | if (inp_count <= 0) | ||
229 | break; | ||
230 | |||
231 | if (inp_count > count) | ||
232 | inp_count = count; | ||
233 | |||
234 | out_count = rb->dsp_process(ci.dsp, dest, src, inp_count); | ||
235 | 234 | ||
236 | if (out_count <= 0) | 235 | if (dst.bufcount <= 0 || |
236 | (src.remcount <= 0 && dst.remcount <= old_remcount)) | ||
237 | { | ||
238 | /* Dest is full or no input left and DSP purged */ | ||
237 | break; | 239 | break; |
238 | 240 | } | |
239 | written_count += out_count; | ||
240 | dest += out_count * 4; | ||
241 | |||
242 | count -= inp_count; | ||
243 | } | 241 | } |
244 | 242 | ||
245 | return written_count; | 243 | return dst.remcount; |
246 | } | 244 | } |
247 | 245 | ||
248 | /* Null output */ | 246 | /* Null output */ |
@@ -502,7 +500,6 @@ static void configure(int setting, intptr_t value) | |||
502 | rb->dsp_configure(ci.dsp, setting, value); | 500 | rb->dsp_configure(ci.dsp, setting, value); |
503 | switch(setting) | 501 | switch(setting) |
504 | { | 502 | { |
505 | case DSP_SWITCH_FREQUENCY: | ||
506 | case DSP_SET_FREQUENCY: | 503 | case DSP_SET_FREQUENCY: |
507 | DEBUGF("samplerate=%d\n",(int)value); | 504 | DEBUGF("samplerate=%d\n",(int)value); |
508 | wavinfo.samplerate = use_dsp ? NATIVE_FREQUENCY : (int)value; | 505 | wavinfo.samplerate = use_dsp ? NATIVE_FREQUENCY : (int)value; |
@@ -525,9 +522,7 @@ static void init_ci(void) | |||
525 | { | 522 | { |
526 | /* --- Our "fake" implementations of the codec API functions. --- */ | 523 | /* --- Our "fake" implementations of the codec API functions. --- */ |
527 | 524 | ||
528 | ci.dsp = (struct dsp_config *)rb->dsp_configure(NULL, DSP_MYDSP, | 525 | ci.dsp = rb->dsp_get_config(CODEC_IDX_AUDIO); |
529 | CODEC_IDX_AUDIO); | ||
530 | |||
531 | ci.codec_get_buffer = codec_get_buffer; | 526 | ci.codec_get_buffer = codec_get_buffer; |
532 | 527 | ||
533 | if (wavinfo.fd >= 0 || checksum) { | 528 | if (wavinfo.fd >= 0 || checksum) { |
@@ -849,6 +844,8 @@ enum plugin_status plugin_start(const void* parameter) | |||
849 | 844 | ||
850 | wavbuffer = rb->plugin_get_buffer(&buffer_size); | 845 | wavbuffer = rb->plugin_get_buffer(&buffer_size); |
851 | dspbuffer = wavbuffer + buffer_size / 2; | 846 | dspbuffer = wavbuffer + buffer_size / 2; |
847 | dspbuffer_count = (buffer_size - (dspbuffer - wavbuffer)) / | ||
848 | (2 * sizeof (int16_t)); | ||
852 | 849 | ||
853 | codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize); | 850 | codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize); |
854 | /* Align codec_mallocbuf to pointer size, tlsf wants that */ | 851 | /* Align codec_mallocbuf to pointer size, tlsf wants that */ |
diff --git a/apps/settings.c b/apps/settings.c index acc38c2388..49d239a2c1 100644 --- a/apps/settings.c +++ b/apps/settings.c | |||
@@ -979,20 +979,17 @@ void settings_apply(bool read_disk) | |||
979 | audio_set_crossfade(global_settings.crossfade); | 979 | audio_set_crossfade(global_settings.crossfade); |
980 | #endif | 980 | #endif |
981 | dsp_set_replaygain(); | 981 | dsp_set_replaygain(); |
982 | dsp_set_crossfeed(global_settings.crossfeed); | 982 | dsp_crossfeed_enable(global_settings.crossfeed); |
983 | dsp_set_crossfeed_direct_gain(global_settings.crossfeed_direct_gain); | 983 | dsp_set_crossfeed_direct_gain(global_settings.crossfeed_direct_gain); |
984 | dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain, | 984 | dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain, |
985 | global_settings.crossfeed_hf_attenuation, | 985 | global_settings.crossfeed_hf_attenuation, |
986 | global_settings.crossfeed_hf_cutoff); | 986 | global_settings.crossfeed_hf_cutoff); |
987 | 987 | ||
988 | /* Configure software equalizer, hardware eq is handled in audio_init() */ | 988 | /* Configure software equalizer, hardware eq is handled in audio_init() */ |
989 | dsp_set_eq(global_settings.eq_enabled); | 989 | dsp_eq_enable(global_settings.eq_enabled); |
990 | dsp_set_eq_precut(global_settings.eq_precut); | 990 | dsp_set_eq_precut(global_settings.eq_precut); |
991 | 991 | for(int i = 0; i < EQ_NUM_BANDS; i++) { | |
992 | for(int i = 0; i < 5; i++) { | 992 | dsp_set_eq_coefs(i, &global_settings.eq_band_settings[i]); |
993 | dsp_set_eq_coefs(i, global_settings.eq_band_settings[i].cutoff, | ||
994 | global_settings.eq_band_settings[i].q, | ||
995 | global_settings.eq_band_settings[i].gain); | ||
996 | } | 993 | } |
997 | 994 | ||
998 | dsp_dither_enable(global_settings.dithering_enabled); | 995 | dsp_dither_enable(global_settings.dithering_enabled); |
diff --git a/apps/settings.h b/apps/settings.h index b312c1e784..4d94ca8ba8 100644 --- a/apps/settings.h +++ b/apps/settings.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "button.h" | 32 | #include "button.h" |
33 | #if CONFIG_CODEC == SWCODEC | 33 | #if CONFIG_CODEC == SWCODEC |
34 | #include "audio.h" | 34 | #include "audio.h" |
35 | #include "dsp.h" | ||
35 | #endif | 36 | #endif |
36 | #include "rbpaths.h" | 37 | #include "rbpaths.h" |
37 | 38 | ||
@@ -339,13 +340,7 @@ struct user_settings | |||
339 | /* EQ */ | 340 | /* EQ */ |
340 | bool eq_enabled; /* Enable equalizer */ | 341 | bool eq_enabled; /* Enable equalizer */ |
341 | unsigned int eq_precut; /* dB */ | 342 | unsigned int eq_precut; /* dB */ |
342 | 343 | struct eq_band_setting eq_band_settings[EQ_NUM_BANDS]; /* for each band */ | |
343 | struct eq_band_setting | ||
344 | { | ||
345 | int cutoff; /* Hz */ | ||
346 | int q; | ||
347 | int gain; /* +/- dB */ | ||
348 | } eq_band_settings[5]; | ||
349 | 344 | ||
350 | /* Misc. swcodec */ | 345 | /* Misc. swcodec */ |
351 | int beep; /* system beep volume when changing tracks etc. */ | 346 | int beep; /* system beep volume when changing tracks etc. */ |
@@ -772,14 +767,7 @@ struct user_settings | |||
772 | #endif | 767 | #endif |
773 | 768 | ||
774 | #if CONFIG_CODEC == SWCODEC | 769 | #if CONFIG_CODEC == SWCODEC |
775 | struct compressor_settings | 770 | struct compressor_settings compressor_settings; |
776 | { | ||
777 | int threshold; | ||
778 | int makeup_gain; | ||
779 | int ratio; | ||
780 | int knee; | ||
781 | int release_time; | ||
782 | } compressor_settings; | ||
783 | #endif | 771 | #endif |
784 | 772 | ||
785 | int sleeptimer_duration; /* In minutes; 0=off */ | 773 | int sleeptimer_duration; /* In minutes; 0=off */ |
diff --git a/apps/settings_list.c b/apps/settings_list.c index af48d11c85..82cccd891f 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c | |||
@@ -1398,7 +1398,7 @@ const struct settings_list settings[] = { | |||
1398 | 1398 | ||
1399 | /* crossfeed */ | 1399 | /* crossfeed */ |
1400 | OFFON_SETTING(F_SOUNDSETTING, crossfeed, LANG_CROSSFEED, false, | 1400 | OFFON_SETTING(F_SOUNDSETTING, crossfeed, LANG_CROSSFEED, false, |
1401 | "crossfeed", dsp_set_crossfeed), | 1401 | "crossfeed", dsp_crossfeed_enable), |
1402 | INT_SETTING_NOWRAP(F_SOUNDSETTING, crossfeed_direct_gain, | 1402 | INT_SETTING_NOWRAP(F_SOUNDSETTING, crossfeed_direct_gain, |
1403 | LANG_CROSSFEED_DIRECT_GAIN, -15, | 1403 | LANG_CROSSFEED_DIRECT_GAIN, -15, |
1404 | "crossfeed direct gain", UNIT_DB, -60, 0, 5, | 1404 | "crossfeed direct gain", UNIT_DB, -60, 0, 5, |
diff --git a/apps/voice_thread.c b/apps/voice_thread.c index 07a67256c4..cff703adfa 100644 --- a/apps/voice_thread.c +++ b/apps/voice_thread.c | |||
@@ -133,9 +133,8 @@ struct voice_thread_data | |||
133 | SpeexBits bits; /* Bit cursor */ | 133 | SpeexBits bits; /* Bit cursor */ |
134 | struct dsp_config *dsp; /* DSP used for voice output */ | 134 | struct dsp_config *dsp; /* DSP used for voice output */ |
135 | struct voice_info vi; /* Copy of clip data */ | 135 | struct voice_info vi; /* Copy of clip data */ |
136 | const char *src[2]; /* Current output buffer pointers */ | ||
137 | int lookahead; /* Number of samples to drop at start of clip */ | 136 | int lookahead; /* Number of samples to drop at start of clip */ |
138 | int count; /* Count of samples remaining to send to PCM */ | 137 | struct dsp_buffer src; /* Speex output buffer/input to DSP */ |
139 | }; | 138 | }; |
140 | 139 | ||
141 | /* Functions called in their repective state that return the next state to | 140 | /* Functions called in their repective state that return the next state to |
@@ -264,9 +263,7 @@ void voice_wait(void) | |||
264 | * setup the DSP parameters */ | 263 | * setup the DSP parameters */ |
265 | static void voice_data_init(struct voice_thread_data *td) | 264 | static void voice_data_init(struct voice_thread_data *td) |
266 | { | 265 | { |
267 | td->dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP, | 266 | td->dsp = dsp_get_config(CODEC_IDX_VOICE); |
268 | CODEC_IDX_VOICE); | ||
269 | |||
270 | dsp_configure(td->dsp, DSP_RESET, 0); | 267 | dsp_configure(td->dsp, DSP_RESET, 0); |
271 | dsp_configure(td->dsp, DSP_SET_FREQUENCY, VOICE_SAMPLE_RATE); | 268 | dsp_configure(td->dsp, DSP_SET_FREQUENCY, VOICE_SAMPLE_RATE); |
272 | dsp_configure(td->dsp, DSP_SET_SAMPLE_DEPTH, VOICE_SAMPLE_DEPTH); | 269 | dsp_configure(td->dsp, DSP_SET_SAMPLE_DEPTH, VOICE_SAMPLE_DEPTH); |
@@ -378,7 +375,8 @@ static enum voice_state voice_decode(struct voice_thread_data *td) | |||
378 | else | 375 | else |
379 | { | 376 | { |
380 | /* If all clips are done and not playing, force pcm playback. */ | 377 | /* If all clips are done and not playing, force pcm playback. */ |
381 | voice_start_playback(); | 378 | if (voice_unplayed_frames() > 0) |
379 | voice_start_playback(); | ||
382 | return VOICE_STATE_MESSAGE; | 380 | return VOICE_STATE_MESSAGE; |
383 | } | 381 | } |
384 | } | 382 | } |
@@ -387,12 +385,14 @@ static enum voice_state voice_decode(struct voice_thread_data *td) | |||
387 | yield(); | 385 | yield(); |
388 | 386 | ||
389 | /* Output the decoded frame */ | 387 | /* Output the decoded frame */ |
390 | td->count = VOICE_FRAME_COUNT - td->lookahead; | 388 | td->src.remcount = VOICE_FRAME_COUNT - td->lookahead; |
391 | td->src[0] = (const char *)&voice_output_buf[td->lookahead]; | 389 | td->src.pin[0] = &voice_output_buf[td->lookahead]; |
392 | td->src[1] = NULL; | 390 | td->src.pin[1] = NULL; |
391 | td->src.proc_mask = 0; | ||
392 | |||
393 | td->lookahead -= MIN(VOICE_FRAME_COUNT, td->lookahead); | 393 | td->lookahead -= MIN(VOICE_FRAME_COUNT, td->lookahead); |
394 | 394 | ||
395 | if (td->count > 0) | 395 | if (td->src.remcount > 0) |
396 | return VOICE_STATE_BUFFER_INSERT; | 396 | return VOICE_STATE_BUFFER_INSERT; |
397 | } | 397 | } |
398 | 398 | ||
@@ -405,12 +405,21 @@ static enum voice_state voice_buffer_insert(struct voice_thread_data *td) | |||
405 | if (!queue_empty(&voice_queue)) | 405 | if (!queue_empty(&voice_queue)) |
406 | return VOICE_STATE_MESSAGE; | 406 | return VOICE_STATE_MESSAGE; |
407 | 407 | ||
408 | char *dest = (char *)voice_buf_get(); | 408 | struct dsp_buffer dst; |
409 | 409 | ||
410 | if (dest != NULL) | 410 | if ((dst.p16out = voice_buf_get()) != NULL) |
411 | { | 411 | { |
412 | voice_buf_commit(dsp_process(td->dsp, dest, td->src, td->count)); | 412 | dst.remcount = 0; |
413 | return VOICE_STATE_DECODE; | 413 | dst.bufcount = VOICE_PCM_FRAME_COUNT; |
414 | |||
415 | dsp_process(td->dsp, &td->src, &dst); | ||
416 | |||
417 | voice_buf_commit(dst.remcount); | ||
418 | |||
419 | /* Unless other effects are introduced to voice that have delays, | ||
420 | all output should have been purged to dst in one call */ | ||
421 | return td->src.remcount > 0 ? | ||
422 | VOICE_STATE_BUFFER_INSERT : VOICE_STATE_DECODE; | ||
414 | } | 423 | } |
415 | 424 | ||
416 | sleep(0); | 425 | sleep(0); |