summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/codec_thread.c56
-rw-r--r--apps/codecs.c2
-rw-r--r--apps/gui/bitmap/list-skinned.c2
-rw-r--r--apps/gui/bitmap/list.c2
-rw-r--r--apps/gui/option_select.c1
-rw-r--r--apps/main.c7
-rw-r--r--apps/menus/eq_menu.c12
-rw-r--r--apps/pcmbuf.c40
-rw-r--r--apps/plugin.c12
-rw-r--r--apps/plugin.h22
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/mpegplayer/audio_thread.c56
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.c8
-rw-r--r--apps/plugins/test_codec.c51
-rw-r--r--apps/settings.c11
-rw-r--r--apps/settings.h18
-rw-r--r--apps/settings_list.c2
-rw-r--r--apps/voice_thread.c37
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)
213static void codec_pcmbuf_insert_callback( 213static 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
353static void codec_configure_callback(int setting, intptr_t value) 345static 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
361static enum codec_command_action 350static enum codec_command_action
@@ -611,8 +600,7 @@ static void NORETURN_ATTR codec_thread(void)
611void codec_thread_init(void) 600void 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
172void codec_get_full_path(char *path, const char *codec_root_fn) 172void 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 */
71static void eq_apply(void) 71static 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
33shopper.c 33shopper.c
34resistor.c 34resistor.c
35 35
36test_codec.c
36 37
37#ifdef USB_ENABLE_HID 38#ifdef USB_ENABLE_HID
38remote_control.c 39remote_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
165static unsigned char *wavbuffer; 165static unsigned char *wavbuffer;
166static unsigned char *dspbuffer; 166static unsigned char *dspbuffer;
167static int dspbuffer_count;
167 168
168void init_wav(char* filename) 169void init_wav(char* filename)
169{ 170{
@@ -215,34 +216,31 @@ static void* codec_get_buffer(size_t *size)
215 216
216static int process_dsp(const void *ch1, const void *ch2, int count) 217static 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 */
265static void voice_data_init(struct voice_thread_data *td) 264static 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);