diff options
-rw-r--r-- | lib/rbcodec/dsp/channel_mode.c | 98 | ||||
-rw-r--r-- | lib/rbcodec/dsp/compressor.c | 6 | ||||
-rw-r--r-- | lib/rbcodec/dsp/crossfeed.c | 122 | ||||
-rw-r--r-- | lib/rbcodec/dsp/dsp_core.c | 342 | ||||
-rw-r--r-- | lib/rbcodec/dsp/dsp_core.h | 37 | ||||
-rw-r--r-- | lib/rbcodec/dsp/dsp_misc.c | 35 | ||||
-rw-r--r-- | lib/rbcodec/dsp/dsp_proc_entry.h | 43 | ||||
-rw-r--r-- | lib/rbcodec/dsp/dsp_sample_input.c | 92 | ||||
-rw-r--r-- | lib/rbcodec/dsp/dsp_sample_io.h | 23 | ||||
-rw-r--r-- | lib/rbcodec/dsp/dsp_sample_output.c | 33 | ||||
-rw-r--r-- | lib/rbcodec/dsp/eq.c | 8 | ||||
-rw-r--r-- | lib/rbcodec/dsp/lin_resample.c | 97 | ||||
-rw-r--r-- | lib/rbcodec/dsp/pga.c | 7 | ||||
-rw-r--r-- | lib/rbcodec/dsp/tdspeed.c | 100 | ||||
-rw-r--r-- | lib/rbcodec/dsp/tone_controls.c | 10 |
15 files changed, 513 insertions, 540 deletions
diff --git a/lib/rbcodec/dsp/channel_mode.c b/lib/rbcodec/dsp/channel_mode.c index 78e7b8f10c..2ae2d45fd3 100644 --- a/lib/rbcodec/dsp/channel_mode.c +++ b/lib/rbcodec/dsp/channel_mode.c | |||
@@ -49,30 +49,14 @@ static struct channel_mode_data | |||
49 | { | 49 | { |
50 | long sw_gain; /* 00h: for mode: custom */ | 50 | long sw_gain; /* 00h: for mode: custom */ |
51 | long sw_cross; /* 04h: for mode: custom */ | 51 | long sw_cross; /* 04h: for mode: custom */ |
52 | struct dsp_config *dsp; | ||
53 | int mode; | 52 | int mode; |
54 | const dsp_proc_fn_type fns[SOUND_CHAN_NUM_MODES]; | ||
55 | } channel_mode_data = | 53 | } channel_mode_data = |
56 | { | 54 | { |
57 | .sw_gain = 0, | 55 | .sw_gain = 0, |
58 | .sw_cross = 0, | 56 | .sw_cross = 0, |
59 | .mode = SOUND_CHAN_STEREO, | 57 | .mode = SOUND_CHAN_STEREO |
60 | .fns = | ||
61 | { | ||
62 | [SOUND_CHAN_STEREO] = NULL, | ||
63 | [SOUND_CHAN_MONO] = channel_mode_proc_mono, | ||
64 | [SOUND_CHAN_CUSTOM] = channel_mode_proc_custom, | ||
65 | [SOUND_CHAN_MONO_LEFT] = channel_mode_proc_mono_left, | ||
66 | [SOUND_CHAN_MONO_RIGHT] = channel_mode_proc_mono_right, | ||
67 | [SOUND_CHAN_KARAOKE] = channel_mode_proc_karaoke, | ||
68 | }, | ||
69 | }; | 58 | }; |
70 | 59 | ||
71 | static dsp_proc_fn_type get_process_fn(void) | ||
72 | { | ||
73 | return channel_mode_data.fns[channel_mode_data.mode]; | ||
74 | } | ||
75 | |||
76 | #if 0 | 60 | #if 0 |
77 | /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for | 61 | /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for |
78 | * completeness. */ | 62 | * completeness. */ |
@@ -166,33 +150,6 @@ void channel_mode_proc_mono_right(struct dsp_proc_entry *this, | |||
166 | (void)this; | 150 | (void)this; |
167 | } | 151 | } |
168 | 152 | ||
169 | /* This is the initial function pointer when first enabled/changed in order | ||
170 | * to facilitate verification of the format compatibility at the proper time | ||
171 | * This gets called for changes even if stage is inactive. */ | ||
172 | static void channel_mode_process_new_format(struct dsp_proc_entry *this, | ||
173 | struct dsp_buffer **buf_p) | ||
174 | { | ||
175 | struct channel_mode_data *data = (void *)this->data; | ||
176 | struct dsp_buffer *buf = *buf_p; | ||
177 | |||
178 | DSP_PRINT_FORMAT(DSP_PROC_CHANNEL_MODE, DSP_PROC_CHANNEL_MODE, | ||
179 | buf->format); | ||
180 | |||
181 | bool active = buf->format.num_channels >= 2; | ||
182 | dsp_proc_activate(data->dsp, DSP_PROC_CHANNEL_MODE, active); | ||
183 | |||
184 | if (!active) | ||
185 | { | ||
186 | /* Can't do this. Sleep until next change. */ | ||
187 | DEBUGF(" DSP_PROC_CHANNEL_MODE- deactivated\n"); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | /* Switch to the real function and call it once */ | ||
192 | this->process[0] = get_process_fn(); | ||
193 | dsp_proc_call(this, buf_p, (unsigned)buf->format.changed - 1); | ||
194 | } | ||
195 | |||
196 | void channel_mode_set_config(int value) | 153 | void channel_mode_set_config(int value) |
197 | { | 154 | { |
198 | if (value < 0 || value >= SOUND_CHAN_NUM_MODES) | 155 | if (value < 0 || value >= SOUND_CHAN_NUM_MODES) |
@@ -228,34 +185,65 @@ void channel_mode_custom_set_width(int value) | |||
228 | channel_mode_data.sw_cross = cross << 8; | 185 | channel_mode_data.sw_cross = cross << 8; |
229 | } | 186 | } |
230 | 187 | ||
188 | static void update_process_fn(struct dsp_proc_entry *this) | ||
189 | { | ||
190 | static const dsp_proc_fn_type fns[SOUND_CHAN_NUM_MODES] = | ||
191 | { | ||
192 | [SOUND_CHAN_STEREO] = NULL, | ||
193 | [SOUND_CHAN_MONO] = channel_mode_proc_mono, | ||
194 | [SOUND_CHAN_CUSTOM] = channel_mode_proc_custom, | ||
195 | [SOUND_CHAN_MONO_LEFT] = channel_mode_proc_mono_left, | ||
196 | [SOUND_CHAN_MONO_RIGHT] = channel_mode_proc_mono_right, | ||
197 | [SOUND_CHAN_KARAOKE] = channel_mode_proc_karaoke, | ||
198 | }; | ||
199 | |||
200 | this->process = fns[((struct channel_mode_data *)this->data)->mode]; | ||
201 | } | ||
202 | |||
203 | /* Handle format changes and verify the format compatibility */ | ||
204 | static intptr_t channel_mode_new_format(struct dsp_proc_entry *this, | ||
205 | struct dsp_config *dsp, | ||
206 | struct sample_format *format) | ||
207 | { | ||
208 | DSP_PRINT_FORMAT(DSP_PROC_CHANNEL_MODE, format); | ||
209 | |||
210 | bool active = format->num_channels >= 2; | ||
211 | dsp_proc_activate(dsp, DSP_PROC_CHANNEL_MODE, active); | ||
212 | |||
213 | if (active) | ||
214 | return PROC_NEW_FORMAT_OK; | ||
215 | |||
216 | /* Can't do this. Sleep until next change. */ | ||
217 | DEBUGF(" DSP_PROC_CHANNEL_MODE- deactivated\n"); | ||
218 | return PROC_NEW_FORMAT_DEACTIVATED; | ||
219 | |||
220 | (void)this; | ||
221 | } | ||
222 | |||
231 | /* DSP message hook */ | 223 | /* DSP message hook */ |
232 | static intptr_t channel_mode_configure(struct dsp_proc_entry *this, | 224 | static intptr_t channel_mode_configure(struct dsp_proc_entry *this, |
233 | struct dsp_config *dsp, | 225 | struct dsp_config *dsp, |
234 | unsigned int setting, | 226 | unsigned int setting, |
235 | intptr_t value) | 227 | intptr_t value) |
236 | { | 228 | { |
229 | intptr_t retval = 0; | ||
230 | |||
237 | switch (setting) | 231 | switch (setting) |
238 | { | 232 | { |
239 | case DSP_PROC_INIT: | 233 | case DSP_PROC_INIT: |
240 | if (value == 0) | 234 | if (value == 0) |
241 | { | ||
242 | /* New object */ | ||
243 | this->data = (intptr_t)&channel_mode_data; | 235 | this->data = (intptr_t)&channel_mode_data; |
244 | this->process[1] = channel_mode_process_new_format; | ||
245 | ((struct channel_mode_data *)this->data)->dsp = dsp; | ||
246 | } | ||
247 | 236 | ||
248 | /* Force format change call each time */ | 237 | update_process_fn(this); |
249 | this->process[0] = channel_mode_process_new_format; | ||
250 | dsp_proc_activate(dsp, DSP_PROC_CHANNEL_MODE, true); | ||
251 | break; | 238 | break; |
252 | 239 | ||
253 | case DSP_PROC_CLOSE: | 240 | case DSP_PROC_NEW_FORMAT: |
254 | ((struct channel_mode_data *)this->data)->dsp = NULL; | 241 | retval = channel_mode_new_format(this, dsp, |
242 | (struct sample_format *)value); | ||
255 | break; | 243 | break; |
256 | } | 244 | } |
257 | 245 | ||
258 | return 1; | 246 | return retval; |
259 | } | 247 | } |
260 | 248 | ||
261 | /* Database entry */ | 249 | /* Database entry */ |
diff --git a/lib/rbcodec/dsp/compressor.c b/lib/rbcodec/dsp/compressor.c index 22a60e4c7e..bdcc37be91 100644 --- a/lib/rbcodec/dsp/compressor.c +++ b/lib/rbcodec/dsp/compressor.c | |||
@@ -386,14 +386,16 @@ static intptr_t compressor_configure(struct dsp_proc_entry *this, | |||
386 | case DSP_PROC_INIT: | 386 | case DSP_PROC_INIT: |
387 | if (value != 0) | 387 | if (value != 0) |
388 | break; /* Already enabled */ | 388 | break; /* Already enabled */ |
389 | this->process[0] = compressor_process; | 389 | |
390 | this->process = compressor_process; | ||
391 | /* Fall-through */ | ||
390 | case DSP_RESET: | 392 | case DSP_RESET: |
391 | case DSP_FLUSH: | 393 | case DSP_FLUSH: |
392 | release_gain = UNITY; | 394 | release_gain = UNITY; |
393 | break; | 395 | break; |
394 | } | 396 | } |
395 | 397 | ||
396 | return 1; | 398 | return 0; |
397 | (void)dsp; | 399 | (void)dsp; |
398 | } | 400 | } |
399 | 401 | ||
diff --git a/lib/rbcodec/dsp/crossfeed.c b/lib/rbcodec/dsp/crossfeed.c index 3fb51a7594..bd8ee95042 100644 --- a/lib/rbcodec/dsp/crossfeed.c +++ b/lib/rbcodec/dsp/crossfeed.c | |||
@@ -68,8 +68,7 @@ static struct crossfeed_state | |||
68 | }; | 68 | }; |
69 | }; | 69 | }; |
70 | int32_t *index; /* 88h: Current pointer into the delay line */ | 70 | int32_t *index; /* 88h: Current pointer into the delay line */ |
71 | struct dsp_config *dsp; /* 8ch: Current DSP */ | 71 | /* 8ch */ |
72 | /* 90h */ | ||
73 | } crossfeed_state IBSS_ATTR; | 72 | } crossfeed_state IBSS_ATTR; |
74 | 73 | ||
75 | static int crossfeed_type = CROSSFEED_TYPE_NONE; | 74 | static int crossfeed_type = CROSSFEED_TYPE_NONE; |
@@ -79,62 +78,21 @@ static void crossfeed_flush(struct dsp_proc_entry *this) | |||
79 | { | 78 | { |
80 | struct crossfeed_state *state = (void *)this->data; | 79 | struct crossfeed_state *state = (void *)this->data; |
81 | 80 | ||
82 | if (crossfeed_type == CROSSFEED_TYPE_CUSTOM) | 81 | if (crossfeed_type != CROSSFEED_TYPE_CUSTOM) |
83 | { | 82 | { |
84 | memset(state->history, 0, | 83 | state->vcl = state->vcr = state->vdiff = 0; |
85 | sizeof (state->history) + sizeof (state->delay)); | ||
86 | state->index = state->delay; | ||
87 | } | 84 | } |
88 | else | 85 | else |
89 | { | 86 | { |
90 | state->vcl = state->vcr = state->vdiff = 0; | 87 | memset(state->history, 0, |
88 | sizeof (state->history) + sizeof (state->delay)); | ||
89 | state->index = state->delay; | ||
91 | } | 90 | } |
92 | } | 91 | } |
93 | 92 | ||
94 | 93 | ||
95 | /** DSP interface **/ | 94 | /** DSP interface **/ |
96 | 95 | ||
97 | /* Crossfeed boot/format change function */ | ||
98 | static void crossfeed_process_new_format(struct dsp_proc_entry *this, | ||
99 | struct dsp_buffer **buf_p) | ||
100 | { | ||
101 | struct crossfeed_state *state = (void *)this->data; | ||
102 | struct dsp_buffer *buf = *buf_p; | ||
103 | |||
104 | DSP_PRINT_FORMAT(DSP_PROC_CROSSFEED, DSP_PROC_CROSSFEED, buf->format); | ||
105 | |||
106 | bool was_active = dsp_proc_active(state->dsp, DSP_PROC_CROSSFEED); | ||
107 | bool active = buf->format.num_channels >= 2; | ||
108 | dsp_proc_activate(state->dsp, DSP_PROC_CROSSFEED, active); | ||
109 | |||
110 | if (!active) | ||
111 | { | ||
112 | /* Can't do this. Sleep until next change */ | ||
113 | DEBUGF(" DSP_PROC_CROSSFEED- deactivated\n"); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | dsp_proc_fn_type fn = crossfeed_process; | ||
118 | |||
119 | if (crossfeed_type != CROSSFEED_TYPE_CUSTOM) | ||
120 | { | ||
121 | /* 1 / (F.Rforward.C) */ | ||
122 | state->coef1 = (0x7fffffff / NATIVE_FREQUENCY) * 2128; | ||
123 | /* 1 / (F.Rcross.C) */ | ||
124 | state->coef2 = (0x7fffffff / NATIVE_FREQUENCY) * 1000; | ||
125 | fn = crossfeed_meier_process; | ||
126 | } | ||
127 | |||
128 | if (!was_active || this->process[0] != fn) | ||
129 | { | ||
130 | crossfeed_flush(this); /* Going online or actual type change */ | ||
131 | this->process[0] = fn; /* Set real function */ | ||
132 | } | ||
133 | |||
134 | /* Call it once */ | ||
135 | dsp_proc_call(this, buf_p, (unsigned)buf->format.changed - 1); | ||
136 | } | ||
137 | |||
138 | /* Set the type of crossfeed to use */ | 96 | /* Set the type of crossfeed to use */ |
139 | void dsp_set_crossfeed_type(int type) | 97 | void dsp_set_crossfeed_type(int type) |
140 | { | 98 | { |
@@ -273,39 +231,83 @@ void crossfeed_meier_process(struct dsp_proc_entry *this, | |||
273 | } | 231 | } |
274 | #endif /* CPU */ | 232 | #endif /* CPU */ |
275 | 233 | ||
234 | /* Update the processing function according to crossfeed type */ | ||
235 | static void update_process_fn(struct dsp_proc_entry *this, | ||
236 | struct dsp_config *dsp) | ||
237 | { | ||
238 | struct crossfeed_state *state = (struct crossfeed_state *)this->data; | ||
239 | dsp_proc_fn_type fn = crossfeed_process; | ||
240 | |||
241 | if (crossfeed_type != CROSSFEED_TYPE_CUSTOM) | ||
242 | { | ||
243 | /* Set up for Meier */ | ||
244 | /* 1 / (F.Rforward.C) */ | ||
245 | state->coef1 = (0x7fffffff / NATIVE_FREQUENCY) * 2128; | ||
246 | /* 1 / (F.Rcross.C) */ | ||
247 | state->coef2 = (0x7fffffff / NATIVE_FREQUENCY) * 1000; | ||
248 | fn = crossfeed_meier_process; | ||
249 | } | ||
250 | |||
251 | if (this->process != fn) | ||
252 | { | ||
253 | this->process = fn; /* Set proper function */ | ||
254 | if (dsp_proc_active(dsp, DSP_PROC_CROSSFEED)) | ||
255 | crossfeed_flush(this); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | /* Crossfeed boot/format change function */ | ||
260 | static intptr_t crossfeed_new_format(struct dsp_proc_entry *this, | ||
261 | struct dsp_config *dsp, | ||
262 | struct sample_format *format) | ||
263 | { | ||
264 | DSP_PRINT_FORMAT(DSP_PROC_CROSSFEED, format); | ||
265 | |||
266 | bool was_active = dsp_proc_active(dsp, DSP_PROC_CROSSFEED); | ||
267 | bool active = format->num_channels >= 2; | ||
268 | dsp_proc_activate(dsp, DSP_PROC_CROSSFEED, active); | ||
269 | |||
270 | if (active) | ||
271 | { | ||
272 | if (!was_active) | ||
273 | crossfeed_flush(this); /* Going online */ | ||
274 | |||
275 | return PROC_NEW_FORMAT_OK; | ||
276 | } | ||
277 | |||
278 | /* Can't do this. Sleep until next change */ | ||
279 | DEBUGF(" DSP_PROC_CROSSFEED- deactivated\n"); | ||
280 | return PROC_NEW_FORMAT_DEACTIVATED; | ||
281 | } | ||
282 | |||
276 | /* DSP message hook */ | 283 | /* DSP message hook */ |
277 | static intptr_t crossfeed_configure(struct dsp_proc_entry *this, | 284 | static intptr_t crossfeed_configure(struct dsp_proc_entry *this, |
278 | struct dsp_config *dsp, | 285 | struct dsp_config *dsp, |
279 | unsigned int setting, | 286 | unsigned int setting, |
280 | intptr_t value) | 287 | intptr_t value) |
281 | { | 288 | { |
289 | intptr_t retval = 0; | ||
290 | |||
282 | switch (setting) | 291 | switch (setting) |
283 | { | 292 | { |
284 | case DSP_PROC_INIT: | 293 | case DSP_PROC_INIT: |
285 | if (value == 0) | 294 | if (value == 0) |
286 | { | ||
287 | /* New object */ | ||
288 | this->data = (intptr_t)&crossfeed_state; | 295 | this->data = (intptr_t)&crossfeed_state; |
289 | this->process[1] = crossfeed_process_new_format; | ||
290 | ((struct crossfeed_state *)this->data)->dsp = dsp; | ||
291 | } | ||
292 | 296 | ||
293 | /* Force format change call each time */ | 297 | update_process_fn(this, dsp); |
294 | this->process[0] = crossfeed_process_new_format; | ||
295 | dsp_proc_activate(dsp, DSP_PROC_CROSSFEED, true); | ||
296 | break; | 298 | break; |
297 | 299 | ||
298 | case DSP_FLUSH: | 300 | case DSP_FLUSH: |
299 | crossfeed_flush(this); | 301 | crossfeed_flush(this); |
300 | break; | 302 | break; |
301 | 303 | ||
302 | case DSP_PROC_CLOSE: | 304 | case DSP_PROC_NEW_FORMAT: |
303 | ((struct crossfeed_state *)this->data)->dsp = NULL; | 305 | retval = crossfeed_new_format(this, dsp, |
306 | (struct sample_format *)value); | ||
304 | break; | 307 | break; |
305 | } | 308 | } |
306 | 309 | ||
307 | return 1; | 310 | return retval; |
308 | (void)value; | ||
309 | } | 311 | } |
310 | 312 | ||
311 | /* Database entry */ | 313 | /* Database entry */ |
diff --git a/lib/rbcodec/dsp/dsp_core.c b/lib/rbcodec/dsp/dsp_core.c index 84a23a4c83..c54bda17a9 100644 --- a/lib/rbcodec/dsp/dsp_core.c +++ b/lib/rbcodec/dsp/dsp_core.c | |||
@@ -34,6 +34,13 @@ | |||
34 | #define DSP_PROC_DB_CREATE | 34 | #define DSP_PROC_DB_CREATE |
35 | #include "dsp_proc_entry.h" | 35 | #include "dsp_proc_entry.h" |
36 | 36 | ||
37 | #ifndef DSP_PROCESS_START | ||
38 | /* These do nothing if not previously defined */ | ||
39 | #define DSP_PROCESS_START() | ||
40 | #define DSP_PROCESS_LOOP() | ||
41 | #define DSP_PROCESS_END() | ||
42 | #endif /* !DSP_PROCESS_START */ | ||
43 | |||
37 | /* Linked lists give fewer loads in processing loop compared to some index | 44 | /* Linked lists give fewer loads in processing loop compared to some index |
38 | * list, which is more important than keeping occasionally executed code | 45 | * list, which is more important than keeping occasionally executed code |
39 | * simple */ | 46 | * simple */ |
@@ -41,24 +48,23 @@ | |||
41 | struct dsp_config | 48 | struct dsp_config |
42 | { | 49 | { |
43 | /** General DSP-local data **/ | 50 | /** General DSP-local data **/ |
44 | struct sample_io_data io_data; /* Sample input-output data (first) */ | 51 | struct sample_io_data io_data; /* Sample input-output data (first) */ |
45 | uint32_t slot_free_mask; /* Mask of free slots for this DSP */ | 52 | uint32_t slot_free_mask; /* Mask of free slots for this DSP */ |
46 | uint32_t proc_masks[2]; /* Mask of active/enabled stages */ | 53 | uint32_t proc_mask_enabled; /* Mask of enabled stages */ |
54 | uint32_t proc_mask_active; /* Mask of active stages */ | ||
47 | struct dsp_proc_slot | 55 | struct dsp_proc_slot |
48 | { | 56 | { |
49 | struct dsp_proc_entry proc_entry; /* This enabled stage */ | 57 | struct dsp_proc_entry proc_entry; /* This enabled stage */ |
50 | struct dsp_proc_slot *next[2]; /* [0]=active next, [1]=enabled next */ | 58 | struct dsp_proc_slot *next; /* Next enabled slot */ |
51 | const struct dsp_proc_db_entry *db_entry; | 59 | uint32_t mask; /* In place operation mask/flag */ |
52 | } *proc_slots[2]; /* Pointer to first in list of | 60 | uint8_t version; /* Sample format version */ |
53 | active/enabled stages */ | 61 | uint8_t db_index; /* Index in database array */ |
54 | 62 | } *proc_slots; /* Pointer to first in list of enabled | |
55 | /** Misc. extra stuff **/ | 63 | stages */ |
56 | #if 0 /* Not needed now but enable if something must know this */ | ||
57 | bool processing; /* DSP is processing (to thwart inopportune | ||
58 | buffer moves) */ | ||
59 | #endif | ||
60 | }; | 64 | }; |
61 | 65 | ||
66 | #define NACT_BIT BIT_N(___DSP_PROC_ID_RESERVED) | ||
67 | |||
62 | /* Pool of slots for stages - supports 32 or fewer combined as-is atm. */ | 68 | /* Pool of slots for stages - supports 32 or fewer combined as-is atm. */ |
63 | static struct dsp_proc_slot | 69 | static struct dsp_proc_slot |
64 | dsp_proc_slot_arr[DSP_NUM_PROC_STAGES+DSP_VOICE_NUM_PROC_STAGES] IBSS_ATTR; | 70 | dsp_proc_slot_arr[DSP_NUM_PROC_STAGES+DSP_VOICE_NUM_PROC_STAGES] IBSS_ATTR; |
@@ -67,6 +73,11 @@ dsp_proc_slot_arr[DSP_NUM_PROC_STAGES+DSP_VOICE_NUM_PROC_STAGES] IBSS_ATTR; | |||
67 | static struct dsp_config dsp_conf[DSP_COUNT] IBSS_ATTR; | 73 | static struct dsp_config dsp_conf[DSP_COUNT] IBSS_ATTR; |
68 | 74 | ||
69 | /** Processing stages support functions **/ | 75 | /** Processing stages support functions **/ |
76 | static const struct dsp_proc_db_entry * | ||
77 | proc_db_entry(const struct dsp_proc_slot *s) | ||
78 | { | ||
79 | return dsp_proc_database[s->db_index]; | ||
80 | } | ||
70 | 81 | ||
71 | /* Find the slot for a given enabled id */ | 82 | /* Find the slot for a given enabled id */ |
72 | static struct dsp_proc_slot * find_proc_slot(struct dsp_config *dsp, | 83 | static struct dsp_proc_slot * find_proc_slot(struct dsp_config *dsp, |
@@ -74,17 +85,17 @@ static struct dsp_proc_slot * find_proc_slot(struct dsp_config *dsp, | |||
74 | { | 85 | { |
75 | const uint32_t mask = BIT_N(id); | 86 | const uint32_t mask = BIT_N(id); |
76 | 87 | ||
77 | if ((dsp->proc_masks[1] & mask) == 0) | 88 | if (!(dsp->proc_mask_enabled & mask)) |
78 | return NULL; /* Not enabled */ | 89 | return NULL; /* Not enabled */ |
79 | 90 | ||
80 | struct dsp_proc_slot *s = dsp->proc_slots[1]; | 91 | struct dsp_proc_slot *s = dsp->proc_slots; |
81 | 92 | ||
82 | while (1) /* In proc_masks == it must be there */ | 93 | while (1) /* In proc_mask_enabled == it must be there */ |
83 | { | 94 | { |
84 | if (BIT_N(s->db_entry->id) == mask) | 95 | if (BIT_N(proc_db_entry(s)->id) == mask) |
85 | return s; | 96 | return s; |
86 | 97 | ||
87 | s = s->next[1]; | 98 | s = s->next; |
88 | } | 99 | } |
89 | } | 100 | } |
90 | 101 | ||
@@ -94,54 +105,23 @@ static intptr_t proc_broadcast(struct dsp_config *dsp, unsigned int setting, | |||
94 | intptr_t value) | 105 | intptr_t value) |
95 | { | 106 | { |
96 | bool multi = setting < DSP_PROC_SETTING; | 107 | bool multi = setting < DSP_PROC_SETTING; |
97 | struct dsp_proc_slot *s = multi ? | 108 | struct dsp_proc_slot *s = multi ? dsp->proc_slots : |
98 | dsp->proc_slots[1] : find_proc_slot(dsp, setting - DSP_PROC_SETTING); | 109 | find_proc_slot(dsp, setting - DSP_PROC_SETTING); |
99 | 110 | ||
100 | while (s != NULL) | 111 | while (s != NULL) |
101 | { | 112 | { |
102 | intptr_t ret = s->db_entry->configure(&s->proc_entry, dsp, setting, | 113 | intptr_t ret = proc_db_entry(s)->configure( |
103 | value); | 114 | &s->proc_entry, dsp, setting, value); |
115 | |||
104 | if (!multi) | 116 | if (!multi) |
105 | return ret; | 117 | return ret; |
106 | 118 | ||
107 | s = s->next[1]; | 119 | s = s->next; |
108 | } | 120 | } |
109 | 121 | ||
110 | return multi ? 1 : 0; | 122 | return multi ? 1 : 0; |
111 | } | 123 | } |
112 | 124 | ||
113 | /* Generic handler for this->process[0] */ | ||
114 | static void dsp_process_null(struct dsp_proc_entry *this, | ||
115 | struct dsp_buffer **buf_p) | ||
116 | { | ||
117 | (void)this; (void)buf_p; | ||
118 | } | ||
119 | |||
120 | /* Generic handler for this->process[1] */ | ||
121 | static void dsp_format_change_process(struct dsp_proc_entry *this, | ||
122 | struct dsp_buffer **buf_p) | ||
123 | { | ||
124 | enum dsp_proc_ids id = | ||
125 | TYPE_FROM_MEMBER(struct dsp_proc_slot, this, proc_entry)->db_entry->id; | ||
126 | |||
127 | DSP_PRINT_FORMAT(<Default Handler>, id, (*buf_p)->format); | ||
128 | |||
129 | /* We don't keep back references to the DSP, so just search for it */ | ||
130 | struct dsp_config *dsp; | ||
131 | for (unsigned int i = 0; (dsp = dsp_get_config(i)); i++) | ||
132 | { | ||
133 | /* Found one with the id, check if it's this one | ||
134 | (NULL return doesn't matter) */ | ||
135 | if (&find_proc_slot(dsp, id)->proc_entry == this) | ||
136 | { | ||
137 | if (dsp_proc_active(dsp, id)) | ||
138 | dsp_proc_call(this, buf_p, 0); | ||
139 | |||
140 | break; | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /* Add an item to the enabled list */ | 125 | /* Add an item to the enabled list */ |
146 | static struct dsp_proc_slot * | 126 | static struct dsp_proc_slot * |
147 | dsp_proc_enable_enlink(struct dsp_config *dsp, uint32_t mask) | 127 | dsp_proc_enable_enlink(struct dsp_config *dsp, uint32_t mask) |
@@ -156,44 +136,42 @@ dsp_proc_enable_enlink(struct dsp_config *dsp, uint32_t mask) | |||
156 | return NULL; | 136 | return NULL; |
157 | } | 137 | } |
158 | 138 | ||
159 | const struct dsp_proc_db_entry *db_entry_prev = NULL; | 139 | unsigned int db_index = 0, db_index_prev = DSP_NUM_PROC_STAGES; |
160 | const struct dsp_proc_db_entry *db_entry; | ||
161 | 140 | ||
162 | /* Order of enabled list is same as DB array */ | 141 | /* Order of enabled list is same as DB array */ |
163 | for (unsigned int i = 0;; i++) | 142 | while (1) |
164 | { | 143 | { |
165 | if (i >= DSP_NUM_PROC_STAGES) | 144 | uint32_t m = BIT_N(dsp_proc_database[db_index]->id); |
166 | return NULL; | ||
167 | |||
168 | db_entry = dsp_proc_database[i]; | ||
169 | |||
170 | uint32_t m = BIT_N(db_entry->id); | ||
171 | 145 | ||
172 | if (m == mask) | 146 | if (m == mask) |
173 | break; /* This is the one */ | 147 | break; /* This is the one */ |
174 | 148 | ||
175 | if (dsp->proc_masks[1] & m) | 149 | if (dsp->proc_mask_enabled & m) |
176 | db_entry_prev = db_entry; | 150 | db_index_prev = db_index; |
151 | |||
152 | if (++db_index >= DSP_NUM_PROC_STAGES) | ||
153 | return NULL; | ||
177 | } | 154 | } |
178 | 155 | ||
179 | struct dsp_proc_slot *s = &dsp_proc_slot_arr[slot]; | 156 | struct dsp_proc_slot *s = &dsp_proc_slot_arr[slot]; |
180 | 157 | ||
181 | if (db_entry_prev != NULL) | 158 | if (db_index_prev < DSP_NUM_PROC_STAGES) |
182 | { | 159 | { |
183 | struct dsp_proc_slot *prev = find_proc_slot(dsp, db_entry_prev->id); | 160 | struct dsp_proc_slot *prev = |
184 | s->next[0] = prev->next[0]; | 161 | find_proc_slot(dsp, dsp_proc_database[db_index_prev]->id); |
185 | s->next[1] = prev->next[1]; | 162 | s->next = prev->next; |
186 | prev->next[1] = s; | 163 | prev->next = s; |
187 | } | 164 | } |
188 | else | 165 | else |
189 | { | 166 | { |
190 | s->next[0] = dsp->proc_slots[0]; | 167 | s->next = dsp->proc_slots; |
191 | s->next[1] = dsp->proc_slots[1]; | 168 | dsp->proc_slots = s; |
192 | dsp->proc_slots[1] = s; | ||
193 | } | 169 | } |
194 | 170 | ||
195 | s->db_entry = db_entry; /* record DB entry */ | 171 | s->mask = mask | NACT_BIT; |
196 | dsp->proc_masks[1] |= mask; | 172 | s->version = 0; |
173 | s->db_index = db_index; | ||
174 | dsp->proc_mask_enabled |= mask; | ||
197 | dsp->slot_free_mask &= ~BIT_N(slot); | 175 | dsp->slot_free_mask &= ~BIT_N(slot); |
198 | 176 | ||
199 | return s; | 177 | return s; |
@@ -203,33 +181,33 @@ dsp_proc_enable_enlink(struct dsp_config *dsp, uint32_t mask) | |||
203 | static struct dsp_proc_slot * | 181 | static struct dsp_proc_slot * |
204 | dsp_proc_enable_delink(struct dsp_config *dsp, uint32_t mask) | 182 | dsp_proc_enable_delink(struct dsp_config *dsp, uint32_t mask) |
205 | { | 183 | { |
206 | struct dsp_proc_slot *s = dsp->proc_slots[1]; | 184 | struct dsp_proc_slot *s = dsp->proc_slots; |
207 | struct dsp_proc_slot *prev = NULL; | 185 | struct dsp_proc_slot *prev = NULL; |
208 | 186 | ||
209 | while (1) /* In proc_masks == it must be there */ | 187 | while (1) /* In proc_mask_enabled == it must be there */ |
210 | { | 188 | { |
211 | if (BIT_N(s->db_entry->id) == mask) | 189 | if (BIT_N(proc_db_entry(s)->id) == mask) |
212 | { | 190 | { |
213 | if (prev) | 191 | if (prev) |
214 | prev->next[1] = s->next[1]; | 192 | prev->next = s->next; |
215 | else | 193 | else |
216 | dsp->proc_slots[1] = s->next[1]; | 194 | dsp->proc_slots = s->next; |
217 | 195 | ||
218 | dsp->proc_masks[1] &= ~mask; | 196 | dsp->proc_mask_enabled &= ~mask; |
219 | dsp->slot_free_mask |= BIT_N(s - dsp_proc_slot_arr); | 197 | dsp->slot_free_mask |= BIT_N(s - dsp_proc_slot_arr); |
220 | return s; | 198 | return s; |
221 | } | 199 | } |
222 | 200 | ||
223 | prev = s; | 201 | prev = s; |
224 | s = s->next[1]; | 202 | s = s->next; |
225 | } | 203 | } |
226 | } | 204 | } |
227 | 205 | ||
228 | void dsp_proc_enable(struct dsp_config *dsp, enum dsp_proc_ids id, | 206 | void dsp_proc_enable(struct dsp_config *dsp, enum dsp_proc_ids id, |
229 | bool enable) | 207 | bool enable) |
230 | { | 208 | { |
231 | uint32_t mask = BIT_N(id); | 209 | const uint32_t mask = BIT_N(id); |
232 | bool enabled = dsp->proc_masks[1] & mask; | 210 | bool enabled = dsp->proc_mask_enabled & mask; |
233 | 211 | ||
234 | if (enable) | 212 | if (enable) |
235 | { | 213 | { |
@@ -247,13 +225,11 @@ void dsp_proc_enable(struct dsp_config *dsp, enum dsp_proc_ids id, | |||
247 | { | 225 | { |
248 | /* New entry - set defaults */ | 226 | /* New entry - set defaults */ |
249 | s->proc_entry.data = 0; | 227 | s->proc_entry.data = 0; |
250 | s->proc_entry.ip_mask = mask; | 228 | s->proc_entry.process = NULL; |
251 | s->proc_entry.process[0] = dsp_process_null; | ||
252 | s->proc_entry.process[1] = dsp_format_change_process; | ||
253 | } | 229 | } |
254 | 230 | ||
255 | enabled = s->db_entry->configure(&s->proc_entry, dsp, DSP_PROC_INIT, | 231 | enabled = proc_db_entry(s)->configure(&s->proc_entry, dsp, |
256 | enabled) >= 0; | 232 | DSP_PROC_INIT, enabled) >= 0; |
257 | if (enabled) | 233 | if (enabled) |
258 | return; | 234 | return; |
259 | 235 | ||
@@ -267,38 +243,7 @@ void dsp_proc_enable(struct dsp_config *dsp, enum dsp_proc_ids id, | |||
267 | 243 | ||
268 | dsp_proc_activate(dsp, id, false); /* Deactivate it first */ | 244 | dsp_proc_activate(dsp, id, false); /* Deactivate it first */ |
269 | struct dsp_proc_slot *s = dsp_proc_enable_delink(dsp, mask); | 245 | struct dsp_proc_slot *s = dsp_proc_enable_delink(dsp, mask); |
270 | s->db_entry->configure(&s->proc_entry, dsp, DSP_PROC_CLOSE, 0); | 246 | proc_db_entry(s)->configure(&s->proc_entry, dsp, DSP_PROC_CLOSE, 0); |
271 | } | ||
272 | |||
273 | /* Maintain the list structure for the active list where each enabled entry | ||
274 | * has a link to the next active item, even if not active which facilitates | ||
275 | * switching out of format change mode by a stage during a format change. | ||
276 | * When that happens, the iterator must jump over inactive but enabled | ||
277 | * stages after its current position. */ | ||
278 | static struct dsp_proc_slot * | ||
279 | dsp_proc_activate_link(struct dsp_config *dsp, uint32_t mask, | ||
280 | struct dsp_proc_slot *s) | ||
281 | { | ||
282 | uint32_t m = BIT_N(s->db_entry->id); | ||
283 | uint32_t mor = m | mask; | ||
284 | |||
285 | if (mor == m) /* Only if same single bit in common */ | ||
286 | { | ||
287 | dsp->proc_masks[0] |= mask; | ||
288 | return s; | ||
289 | } | ||
290 | else if (~mor == 0) /* Only if bits complement */ | ||
291 | { | ||
292 | dsp->proc_masks[0] &= mask; | ||
293 | return s->next[0]; | ||
294 | } | ||
295 | |||
296 | struct dsp_proc_slot *next = s->next[1]; | ||
297 | next = dsp_proc_activate_link(dsp, mask, next); | ||
298 | |||
299 | s->next[0] = next; | ||
300 | |||
301 | return (m & dsp->proc_masks[0]) ? s : next; | ||
302 | } | 247 | } |
303 | 248 | ||
304 | /* Activate or deactivate a stage */ | 249 | /* Activate or deactivate a stage */ |
@@ -307,55 +252,109 @@ void dsp_proc_activate(struct dsp_config *dsp, enum dsp_proc_ids id, | |||
307 | { | 252 | { |
308 | const uint32_t mask = BIT_N(id); | 253 | const uint32_t mask = BIT_N(id); |
309 | 254 | ||
310 | if (!(dsp->proc_masks[1] & mask)) | 255 | if (!(dsp->proc_mask_enabled & mask)) |
311 | return; /* Not enabled */ | 256 | return; /* Not enabled */ |
312 | 257 | ||
313 | if (activate != !(dsp->proc_masks[0] & mask)) | 258 | if (activate != !(dsp->proc_mask_active & mask)) |
314 | return; /* No change in state */ | 259 | return; /* No change in state */ |
315 | 260 | ||
316 | /* Send mask bit if activating and ones complement if deactivating */ | 261 | struct dsp_proc_slot *s = find_proc_slot(dsp, id); |
317 | dsp->proc_slots[0] = dsp_proc_activate_link( | 262 | |
318 | dsp, activate ? mask : ~mask, dsp->proc_slots[1]); | 263 | if (activate) |
264 | { | ||
265 | dsp->proc_mask_active |= mask; | ||
266 | s->mask &= ~NACT_BIT; | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | dsp->proc_mask_active &= ~mask; | ||
271 | s->mask |= NACT_BIT; | ||
272 | } | ||
319 | } | 273 | } |
320 | 274 | ||
321 | /* Is the stage specified by the id currently active? */ | 275 | /* Is the stage specified by the id currently active? */ |
322 | bool dsp_proc_active(struct dsp_config *dsp, enum dsp_proc_ids id) | 276 | bool dsp_proc_active(struct dsp_config *dsp, enum dsp_proc_ids id) |
323 | { | 277 | { |
324 | return (dsp->proc_masks[0] & BIT_N(id)) != 0; | 278 | return (dsp->proc_mask_active & BIT_N(id)) != 0; |
325 | } | 279 | } |
326 | 280 | ||
327 | /* Determine by the rules if the processing function should be called */ | 281 | /* Force the specified stage to receive a format update before the next |
328 | static FORCE_INLINE bool dsp_proc_should_call(struct dsp_proc_entry *this, | 282 | * buffer is sent to process() */ |
329 | struct dsp_buffer *buf, | 283 | void dsp_proc_want_format_update(struct dsp_config *dsp, |
330 | unsigned int fmt) | 284 | enum dsp_proc_ids id) |
331 | { | 285 | { |
332 | uint32_t ip_mask = this->ip_mask; | 286 | struct dsp_proc_slot *s = find_proc_slot(dsp, id); |
333 | 287 | ||
334 | return UNLIKELY(fmt != 0) || /* Also pass override value */ | 288 | if (s) |
335 | ip_mask == 0 || /* Not in-place */ | 289 | s->version = 0; /* Set invalid */ |
336 | ((ip_mask & buf->proc_mask) == 0 && | ||
337 | (buf->proc_mask |= ip_mask, buf->remcount > 0)); | ||
338 | } | 290 | } |
339 | 291 | ||
340 | /* Call this->process[fmt] according to the rules (for external call) */ | 292 | /* Set or unset in-place operation */ |
341 | bool dsp_proc_call(struct dsp_proc_entry *this, struct dsp_buffer **buf_p, | 293 | void dsp_proc_set_in_place(struct dsp_config *dsp, enum dsp_proc_ids id, |
342 | unsigned int fmt) | 294 | bool in_place) |
343 | { | 295 | { |
344 | if (dsp_proc_should_call(this, *buf_p, fmt)) | 296 | struct dsp_proc_slot *s = find_proc_slot(dsp, id); |
297 | |||
298 | if (!s) | ||
299 | return; | ||
300 | |||
301 | const uint32_t mask = BIT_N(id); | ||
302 | |||
303 | if (in_place) | ||
304 | s->mask |= mask; | ||
305 | else | ||
306 | s->mask &= ~mask; | ||
307 | } | ||
308 | |||
309 | /* Determine by the rules if the processing function should be called */ | ||
310 | static NO_INLINE bool dsp_proc_new_format(struct dsp_proc_slot *s, | ||
311 | struct dsp_config *dsp, | ||
312 | struct dsp_buffer *buf) | ||
313 | { | ||
314 | struct dsp_proc_entry *this = &s->proc_entry; | ||
315 | struct sample_format *format = &buf->format; | ||
316 | |||
317 | switch (proc_db_entry(s)->configure( | ||
318 | this, dsp, DSP_PROC_NEW_FORMAT, (intptr_t)format)) | ||
345 | { | 319 | { |
346 | this->process[fmt == (0u-1u) ? 0 : fmt](this, buf_p); | 320 | case PROC_NEW_FORMAT_OK: |
321 | s->version = format->version; | ||
347 | return true; | 322 | return true; |
348 | } | ||
349 | 323 | ||
350 | return false; | 324 | case PROC_NEW_FORMAT_TRANSITION: |
325 | return true; | ||
326 | |||
327 | case PROC_NEW_FORMAT_DEACTIVATED: | ||
328 | s->version = format->version; | ||
329 | return false; | ||
330 | |||
331 | default: | ||
332 | return false; | ||
333 | } | ||
351 | } | 334 | } |
352 | 335 | ||
353 | #ifndef DSP_PROCESS_START | 336 | static FORCE_INLINE void dsp_proc_call(struct dsp_proc_slot *s, |
354 | /* These do nothing if not previously defined */ | 337 | struct dsp_config *dsp, |
355 | #define DSP_PROCESS_START() | 338 | struct dsp_buffer **buf_p) |
356 | #define DSP_PROCESS_LOOP() | 339 | { |
357 | #define DSP_PROCESS_END() | 340 | struct dsp_buffer *buf = *buf_p; |
358 | #endif /* !DSP_PROCESS_START */ | 341 | |
342 | if (UNLIKELY(buf->format.version != s->version)) | ||
343 | { | ||
344 | if (!dsp_proc_new_format(s, dsp, buf)) | ||
345 | return; | ||
346 | } | ||
347 | |||
348 | if (s->mask) | ||
349 | { | ||
350 | if ((s->mask & (buf->proc_mask | NACT_BIT)) || buf->remcount <= 0) | ||
351 | return; | ||
352 | |||
353 | buf->proc_mask |= s->mask; | ||
354 | } | ||
355 | |||
356 | s->proc_entry.process(&s->proc_entry, buf_p); | ||
357 | } | ||
359 | 358 | ||
360 | /** | 359 | /** |
361 | * dsp_process: | 360 | * dsp_process: |
@@ -411,9 +410,6 @@ void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src, | |||
411 | } | 410 | } |
412 | 411 | ||
413 | DSP_PROCESS_START(); | 412 | DSP_PROCESS_START(); |
414 | #if 0 /* Not needed now but enable if something must know this */ | ||
415 | dsp->processing = true; | ||
416 | #endif | ||
417 | 413 | ||
418 | /* Tag input with codec-specified sample format */ | 414 | /* Tag input with codec-specified sample format */ |
419 | src->format = dsp->io_data.format; | 415 | src->format = dsp->io_data.format; |
@@ -423,36 +419,29 @@ void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src, | |||
423 | /* Out-of-place-processing stages take the current buf as input | 419 | /* Out-of-place-processing stages take the current buf as input |
424 | * and switch the buffer to their own output buffer */ | 420 | * and switch the buffer to their own output buffer */ |
425 | struct dsp_buffer *buf = src; | 421 | struct dsp_buffer *buf = src; |
426 | unsigned int fmt = buf->format.changed; | ||
427 | 422 | ||
428 | /* Convert input samples to internal format */ | 423 | if (UNLIKELY(buf->format.version != dsp->io_data.sample_buf.format.version)) |
429 | dsp->io_data.input_samples[fmt](&dsp->io_data, &buf); | 424 | dsp_sample_input_format_change(&dsp->io_data, &buf->format); |
430 | fmt = buf->format.changed; | ||
431 | 425 | ||
432 | struct dsp_proc_slot *s = dsp->proc_slots[fmt]; | 426 | /* Convert input samples to internal format */ |
427 | dsp->io_data.input_samples(&dsp->io_data, &buf); | ||
433 | 428 | ||
434 | /* Call all active/enabled stages depending if format is | 429 | /* Call all active/enabled stages depending if format is |
435 | same/changed on the last output buffer */ | 430 | same/changed on the last output buffer */ |
436 | while (s != NULL) | 431 | for (struct dsp_proc_slot *s = dsp->proc_slots; s; s = s->next) |
437 | { | 432 | dsp_proc_call(s, dsp, &buf); |
438 | if (dsp_proc_should_call(&s->proc_entry, buf, fmt)) | ||
439 | { | ||
440 | s->proc_entry.process[fmt](&s->proc_entry, &buf); | ||
441 | fmt = buf->format.changed; | ||
442 | } | ||
443 | |||
444 | /* The buffer may have changed along with the format flag */ | ||
445 | s = s->next[fmt]; | ||
446 | } | ||
447 | 433 | ||
448 | /* Don't overread/write src/destination */ | 434 | /* Don't overread/write src/destination */ |
449 | int outcount = MIN(dst->bufcount, buf->remcount); | 435 | int outcount = MIN(dst->bufcount, buf->remcount); |
450 | 436 | ||
451 | if (fmt == 0 && outcount <= 0) | 437 | if (outcount <= 0) |
452 | break; /* Output full or purged internal buffers */ | 438 | break; /* Output full or purged internal buffers */ |
453 | 439 | ||
440 | if (UNLIKELY(buf->format.version != dsp->io_data.output_version)) | ||
441 | dsp_sample_output_format_change(&dsp->io_data, &buf->format); | ||
442 | |||
454 | dsp->io_data.outcount = outcount; | 443 | dsp->io_data.outcount = outcount; |
455 | dsp->io_data.output_samples[fmt](&dsp->io_data, buf, dst); | 444 | dsp->io_data.output_samples(&dsp->io_data, buf, dst); |
456 | 445 | ||
457 | /* Advance buffers by what output consumed and produced */ | 446 | /* Advance buffers by what output consumed and produced */ |
458 | dsp_advance_buffer32(buf, outcount); | 447 | dsp_advance_buffer32(buf, outcount); |
@@ -461,10 +450,6 @@ void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src, | |||
461 | DSP_PROCESS_LOOP(); | 450 | DSP_PROCESS_LOOP(); |
462 | } /* while */ | 451 | } /* while */ |
463 | 452 | ||
464 | #if 0 /* Not needed now but enable if something must know this */ | ||
465 | dsp->process = false; | ||
466 | #endif | ||
467 | |||
468 | DSP_PROCESS_END(); | 453 | DSP_PROCESS_END(); |
469 | } | 454 | } |
470 | 455 | ||
@@ -495,13 +480,6 @@ enum dsp_ids dsp_get_id(const struct dsp_config *dsp) | |||
495 | return (enum dsp_ids)id; | 480 | return (enum dsp_ids)id; |
496 | } | 481 | } |
497 | 482 | ||
498 | #if 0 /* Not needed now but enable if something must know this */ | ||
499 | bool dsp_is_busy(const struct dsp_config *dsp) | ||
500 | { | ||
501 | return dsp->processing; | ||
502 | } | ||
503 | #endif /* 0 */ | ||
504 | |||
505 | /* Do what needs initializing before enable/disable calls can be made. | 483 | /* Do what needs initializing before enable/disable calls can be made. |
506 | * Must be done before changing settings for the first time. */ | 484 | * Must be done before changing settings for the first time. */ |
507 | void INIT_ATTR dsp_init(void) | 485 | void INIT_ATTR dsp_init(void) |
diff --git a/lib/rbcodec/dsp/dsp_core.h b/lib/rbcodec/dsp/dsp_core.h index 0119da8af6..713190debc 100644 --- a/lib/rbcodec/dsp/dsp_core.h +++ b/lib/rbcodec/dsp/dsp_core.h | |||
@@ -39,8 +39,10 @@ enum dsp_settings | |||
39 | DSP_SET_SAMPLE_DEPTH, | 39 | DSP_SET_SAMPLE_DEPTH, |
40 | DSP_SET_STEREO_MODE, | 40 | DSP_SET_STEREO_MODE, |
41 | DSP_FLUSH, | 41 | DSP_FLUSH, |
42 | DSP_SET_PITCH, | ||
42 | DSP_PROC_INIT, | 43 | DSP_PROC_INIT, |
43 | DSP_PROC_CLOSE, | 44 | DSP_PROC_CLOSE, |
45 | DSP_PROC_NEW_FORMAT, | ||
44 | DSP_PROC_SETTING, /* stage-specific should be this + id */ | 46 | DSP_PROC_SETTING, /* stage-specific should be this + id */ |
45 | }; | 47 | }; |
46 | 48 | ||
@@ -54,10 +56,13 @@ enum dsp_stereo_modes | |||
54 | STEREO_NUM_MODES, | 56 | STEREO_NUM_MODES, |
55 | }; | 57 | }; |
56 | 58 | ||
57 | /* Format into for the buffer (if .valid == true) */ | 59 | /* Format into for the buffer */ |
58 | struct sample_format | 60 | struct sample_format |
59 | { | 61 | { |
60 | uint8_t changed; /* 00h: 0=no change, 1=changed (is also index) */ | 62 | uint8_t version; /* 00h: format version number (never == 0, |
63 | 0 is used to detect format calls for | ||
64 | individual stages, such as when they | ||
65 | are newly enabled) */ | ||
61 | uint8_t num_channels; /* 01h: number of channels of data */ | 66 | uint8_t num_channels; /* 01h: number of channels of data */ |
62 | uint8_t frac_bits; /* 02h: number of fractional bits */ | 67 | uint8_t frac_bits; /* 02h: number of fractional bits */ |
63 | uint8_t output_scale; /* 03h: output scaling shift */ | 68 | uint8_t output_scale; /* 03h: output scaling shift */ |
@@ -66,16 +71,6 @@ struct sample_format | |||
66 | /* 0ch */ | 71 | /* 0ch */ |
67 | }; | 72 | }; |
68 | 73 | ||
69 | /* Compare format data only */ | ||
70 | #define EQU_SAMPLE_FORMAT(f1, f2) \ | ||
71 | (!memcmp(&(f1).num_channels, &(f2).num_channels, \ | ||
72 | sizeof (f1) - sizeof ((f1).changed))) | ||
73 | |||
74 | static inline void format_change_set(struct sample_format *f) | ||
75 | { f->changed = 1; } | ||
76 | static inline void format_change_ack(struct sample_format *f) | ||
77 | { f->changed = 0; } | ||
78 | |||
79 | /* Used by ASM routines - keep field order or else fix the functions */ | 74 | /* Used by ASM routines - keep field order or else fix the functions */ |
80 | struct dsp_buffer | 75 | struct dsp_buffer |
81 | { | 76 | { |
@@ -133,30 +128,12 @@ static inline void dsp_advance_buffer32(struct dsp_buffer *buf, | |||
133 | buf->p32[1] += by_count; | 128 | buf->p32[1] += by_count; |
134 | } | 129 | } |
135 | 130 | ||
136 | /** For use by processing stages **/ | ||
137 | |||
138 | #define DSP_PRINT_FORMAT(name, id, format) \ | ||
139 | DEBUGF("DSP format- " #name "\n" \ | ||
140 | " id:%d chg:%c ch:%u fb:%u os:%u hz:%u chz:%u\n", \ | ||
141 | (int)id, \ | ||
142 | (format).changed ? 'y' : 'n', \ | ||
143 | (unsigned int)(format).num_channels, \ | ||
144 | (unsigned int)(format).frac_bits, \ | ||
145 | (unsigned int)(format).output_scale, \ | ||
146 | (unsigned int)(format).frequency, \ | ||
147 | (unsigned int)(format).codec_frequency); | ||
148 | |||
149 | /* Get DSP pointer */ | 131 | /* Get DSP pointer */ |
150 | struct dsp_config * dsp_get_config(enum dsp_ids id); | 132 | struct dsp_config * dsp_get_config(enum dsp_ids id); |
151 | 133 | ||
152 | /* Get DSP id */ | 134 | /* Get DSP id */ |
153 | enum dsp_ids dsp_get_id(const struct dsp_config *dsp); | 135 | enum dsp_ids dsp_get_id(const struct dsp_config *dsp); |
154 | 136 | ||
155 | #if 0 /* Not needed now but enable if something must know this */ | ||
156 | /* Is the DSP processing a buffer? */ | ||
157 | bool dsp_is_busy(const struct dsp_config *dsp); | ||
158 | #endif /* 0 */ | ||
159 | |||
160 | /** General DSP processing **/ | 137 | /** General DSP processing **/ |
161 | 138 | ||
162 | /* Process the given buffer - see implementation in dsp.c for more */ | 139 | /* Process the given buffer - see implementation in dsp.c for more */ |
diff --git a/lib/rbcodec/dsp/dsp_misc.c b/lib/rbcodec/dsp/dsp_misc.c index 672212b267..a19ef52883 100644 --- a/lib/rbcodec/dsp/dsp_misc.c +++ b/lib/rbcodec/dsp/dsp_misc.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include "fixedpoint.h" | 26 | #include "fixedpoint.h" |
27 | #include "replaygain.h" | 27 | #include "replaygain.h" |
28 | #include "dsp_proc_entry.h" | 28 | #include "dsp_proc_entry.h" |
29 | #include "dsp_sample_io.h" | ||
30 | #include "dsp_misc.h" | 29 | #include "dsp_misc.h" |
31 | #include "pga.h" | 30 | #include "pga.h" |
32 | #include "channel_mode.h" | 31 | #include "channel_mode.h" |
@@ -113,20 +112,21 @@ static int32_t pitch_ratio = PITCH_SPEED_100; | |||
113 | 112 | ||
114 | static void dsp_pitch_update(struct dsp_config *dsp) | 113 | static void dsp_pitch_update(struct dsp_config *dsp) |
115 | { | 114 | { |
116 | /* Account for playback speed adjustment when setting dsp->frequency | 115 | dsp_configure(dsp, DSP_SET_PITCH, |
117 | if we're called from the main audio thread. Voice playback thread | 116 | fp_div(pitch_ratio, PITCH_SPEED_100, 16)); |
118 | does not support this feature. */ | ||
119 | struct sample_io_data *data = (void *)dsp; | ||
120 | data->format.frequency = | ||
121 | (int64_t)pitch_ratio * data->format.codec_frequency / PITCH_SPEED_100; | ||
122 | } | 117 | } |
123 | 118 | ||
124 | static void dsp_set_pitch(int32_t percent) | 119 | static void dsp_set_pitch(int32_t percent) |
125 | { | 120 | { |
126 | pitch_ratio = percent > 0 ? percent : PITCH_SPEED_100; | 121 | if (percent <= 0) |
127 | struct dsp_config *dsp = dsp_get_config(CODEC_IDX_AUDIO); | 122 | percent = PITCH_SPEED_100; |
128 | struct sample_io_data *data = (void *)dsp; | 123 | |
129 | dsp_configure(dsp, DSP_SWITCH_FREQUENCY, data->format.codec_frequency); | 124 | if (percent == pitch_ratio) |
125 | return; | ||
126 | |||
127 | pitch_ratio = percent; | ||
128 | |||
129 | dsp_pitch_update(dsp_get_config(CODEC_IDX_AUDIO)); | ||
130 | } | 130 | } |
131 | #endif /* HAVE_PITCHCONTROL */ | 131 | #endif /* HAVE_PITCHCONTROL */ |
132 | 132 | ||
@@ -173,6 +173,13 @@ int dsp_callback(int msg, intptr_t param) | |||
173 | return retval; | 173 | return retval; |
174 | } | 174 | } |
175 | 175 | ||
176 | static void INIT_ATTR misc_dsp_init(struct dsp_config *dsp, | ||
177 | enum dsp_ids dsp_id) | ||
178 | { | ||
179 | /* Enable us for the audio DSP at startup */ | ||
180 | if (dsp_id == CODEC_IDX_AUDIO) | ||
181 | dsp_proc_enable(dsp, DSP_PROC_MISC_HANDLER, true); | ||
182 | } | ||
176 | 183 | ||
177 | /* This is a null-processing stage that monitors as an enabled stage but never | 184 | /* This is a null-processing stage that monitors as an enabled stage but never |
178 | * becomes active in processing samples. It only hooks messages. */ | 185 | * becomes active in processing samples. It only hooks messages. */ |
@@ -186,9 +193,7 @@ static intptr_t misc_handler_configure(struct dsp_proc_entry *this, | |||
186 | switch (setting) | 193 | switch (setting) |
187 | { | 194 | { |
188 | case DSP_INIT: | 195 | case DSP_INIT: |
189 | /* Enable us for the audio DSP at startup */ | 196 | misc_dsp_init(dsp, (enum dsp_ids)value); |
190 | if (value == CODEC_IDX_AUDIO) | ||
191 | dsp_proc_enable(dsp, DSP_PROC_MISC_HANDLER, true); | ||
192 | break; | 197 | break; |
193 | 198 | ||
194 | case DSP_PROC_CLOSE: | 199 | case DSP_PROC_CLOSE: |
@@ -212,7 +217,7 @@ static intptr_t misc_handler_configure(struct dsp_proc_entry *this, | |||
212 | #endif | 217 | #endif |
213 | } | 218 | } |
214 | 219 | ||
215 | return 1; | 220 | return 0; |
216 | (void)this; | 221 | (void)this; |
217 | } | 222 | } |
218 | 223 | ||
diff --git a/lib/rbcodec/dsp/dsp_proc_entry.h b/lib/rbcodec/dsp/dsp_proc_entry.h index c53443713b..902385f08d 100644 --- a/lib/rbcodec/dsp/dsp_proc_entry.h +++ b/lib/rbcodec/dsp/dsp_proc_entry.h | |||
@@ -79,7 +79,7 @@ struct dsp_proc_db_entry; | |||
79 | #define DSP_PROC_DB_START \ | 79 | #define DSP_PROC_DB_START \ |
80 | enum dsp_proc_ids \ | 80 | enum dsp_proc_ids \ |
81 | { \ | 81 | { \ |
82 | ___DSP_PROC_ID_FIRST = -1, | 82 | ___DSP_PROC_ID_RESERVED = 0, |
83 | 83 | ||
84 | #define DSP_PROC_DB_ITEM(name) \ | 84 | #define DSP_PROC_DB_ITEM(name) \ |
85 | DSP_PROC_##name, | 85 | DSP_PROC_##name, |
@@ -102,19 +102,24 @@ typedef void (*dsp_proc_fn_type)(struct dsp_proc_entry *this, | |||
102 | * The structure allocated to every stage when enabled. | 102 | * The structure allocated to every stage when enabled. |
103 | * | 103 | * |
104 | * default settings: | 104 | * default settings: |
105 | * .data = 0 | 105 | * .data = 0 |
106 | * .ip_mask = BIT_N(dsp_proc_db_entry.id) | 106 | * .process = NULL |
107 | * .process[0] = dsp_process_null | ||
108 | * .process[1] = dsp_format_change_process | ||
109 | * | 107 | * |
110 | * DSP_PROC_INIT handler just has to change what it needs to change. It may | 108 | * DSP_PROC_INIT handler just has to change what it needs to change. It may |
111 | * also be modified at any time to implement the stage's demands. | 109 | * also be modified at any time to implement the stage's demands. |
112 | */ | 110 | */ |
113 | struct dsp_proc_entry | 111 | struct dsp_proc_entry |
114 | { | 112 | { |
115 | intptr_t data; /* 00h: any value, at beginning for easy asm use */ | 113 | intptr_t data; /* 00h: any value, used by asm */ |
116 | uint32_t ip_mask; /* In-place id bit (0 or id bit flag if in-place) */ | 114 | dsp_proc_fn_type process; /* Processing vector */ |
117 | dsp_proc_fn_type process[2]; /* Processing normal/format changes */ | 115 | }; |
116 | |||
117 | /* Return values for DSP_PROC_NEW_FORMAT setting */ | ||
118 | enum | ||
119 | { | ||
120 | PROC_NEW_FORMAT_OK = 0, /* Acks, calls process() (default) */ | ||
121 | PROC_NEW_FORMAT_DEACTIVATED, /* Acks, does not call process() */ | ||
122 | PROC_NEW_FORMAT_TRANSITION /* Does not ack, calls process() */ | ||
118 | }; | 123 | }; |
119 | 124 | ||
120 | /* DSP transform configure function prototype */ | 125 | /* DSP transform configure function prototype */ |
@@ -137,10 +142,24 @@ void dsp_proc_activate(struct dsp_config *dsp, enum dsp_proc_ids id, | |||
137 | /* Is the specified stage active on the DSP? */ | 142 | /* Is the specified stage active on the DSP? */ |
138 | bool dsp_proc_active(struct dsp_config *dsp, enum dsp_proc_ids id); | 143 | bool dsp_proc_active(struct dsp_config *dsp, enum dsp_proc_ids id); |
139 | 144 | ||
140 | /* Call this->process[fmt] according to the rules | 145 | /* Force the specified stage to receive a format update before the next |
141 | * pass (unsigned)-1 to call function 0 with no restriction */ | 146 | * buffer is sent to process() */ |
142 | bool dsp_proc_call(struct dsp_proc_entry *this, struct dsp_buffer **buf_p, | 147 | void dsp_proc_want_format_update(struct dsp_config *dsp, |
143 | unsigned int fmt); | 148 | enum dsp_proc_ids id); |
149 | |||
150 | /* Set or unset in-place operation */ | ||
151 | void dsp_proc_set_in_place(struct dsp_config *dsp, enum dsp_proc_ids id, | ||
152 | bool in_place); | ||
153 | |||
154 | #define DSP_PRINT_FORMAT(id, format) \ | ||
155 | DEBUGF("DSP format- " #id "\n" \ | ||
156 | " ver:%u ch:%u fb:%u os:%u hz:%u chz:%u\n", \ | ||
157 | (unsigned int)(format).version \ | ||
158 | (unsigned int)(format).num_channels, \ | ||
159 | (unsigned int)(format).frac_bits, \ | ||
160 | (unsigned int)(format).output_scale, \ | ||
161 | (unsigned int)(format).frequency, \ | ||
162 | (unsigned int)(format).codec_frequency); | ||
144 | 163 | ||
145 | struct dsp_proc_db_entry | 164 | struct dsp_proc_db_entry |
146 | { | 165 | { |
diff --git a/lib/rbcodec/dsp/dsp_sample_input.c b/lib/rbcodec/dsp/dsp_sample_input.c index 284f34c96a..65d2a110e1 100644 --- a/lib/rbcodec/dsp/dsp_sample_input.c +++ b/lib/rbcodec/dsp/dsp_sample_input.c | |||
@@ -21,12 +21,12 @@ | |||
21 | ****************************************************************************/ | 21 | ****************************************************************************/ |
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "fixedpoint.h" | ||
24 | #include "dsp_core.h" | 25 | #include "dsp_core.h" |
25 | #include "dsp_sample_io.h" | 26 | #include "dsp_sample_io.h" |
27 | #include "dsp_proc_entry.h" | ||
26 | 28 | ||
27 | #if 1 | 29 | #if 0 |
28 | #include <debug.h> | ||
29 | #else | ||
30 | #undef DEBUGF | 30 | #undef DEBUGF |
31 | #define DEBUGF(...) | 31 | #define DEBUGF(...) |
32 | #endif | 32 | #endif |
@@ -50,6 +50,8 @@ | |||
50 | 50 | ||
51 | extern void dsp_sample_output_init(struct sample_io_data *this); | 51 | extern void dsp_sample_output_init(struct sample_io_data *this); |
52 | extern void dsp_sample_output_flush(struct sample_io_data *this); | 52 | extern void dsp_sample_output_flush(struct sample_io_data *this); |
53 | extern void dsp_sample_output_format_change(struct sample_io_data *this, | ||
54 | struct sample_format *format); | ||
53 | 55 | ||
54 | #define SAMPLE_BUF_COUNT 128 /* Per channel, per DSP */ | 56 | #define SAMPLE_BUF_COUNT 128 /* Per channel, per DSP */ |
55 | /* CODEC_IDX_AUDIO = left and right, CODEC_IDX_VOICE = mono */ | 57 | /* CODEC_IDX_AUDIO = left and right, CODEC_IDX_VOICE = mono */ |
@@ -75,8 +77,8 @@ static FORCE_INLINE int sample_input_setup(struct sample_io_data *this, | |||
75 | int count = MIN(s->remcount, SAMPLE_BUF_COUNT); | 77 | int count = MIN(s->remcount, SAMPLE_BUF_COUNT); |
76 | 78 | ||
77 | d->remcount = count; | 79 | d->remcount = count; |
78 | d->p32[0] = this->sample_buf_arr[0]; | 80 | d->p32[0] = this->sample_buf_p[0]; |
79 | d->p32[1] = this->sample_buf_arr[channels - 1]; | 81 | d->p32[1] = this->sample_buf_p[channels - 1]; |
80 | d->proc_mask = s->proc_mask; | 82 | d->proc_mask = s->proc_mask; |
81 | 83 | ||
82 | return count; | 84 | return count; |
@@ -210,9 +212,9 @@ static void sample_input_ni_stereo32(struct sample_io_data *this, | |||
210 | } | 212 | } |
211 | 213 | ||
212 | /* set the to-native sample conversion function based on dsp sample | 214 | /* set the to-native sample conversion function based on dsp sample |
213 | * parameters */ | 215 | * parameters - depends upon stereo_mode and sample_depth */ |
214 | static void dsp_sample_input_format_change(struct sample_io_data *this, | 216 | void dsp_sample_input_format_change(struct sample_io_data *this, |
215 | struct dsp_buffer **buf_p) | 217 | struct sample_format *format) |
216 | { | 218 | { |
217 | static const sample_input_fn_type fns[STEREO_NUM_MODES][2] = | 219 | static const sample_input_fn_type fns[STEREO_NUM_MODES][2] = |
218 | { | 220 | { |
@@ -227,33 +229,35 @@ static void dsp_sample_input_format_change(struct sample_io_data *this, | |||
227 | sample_input_mono32 }, | 229 | sample_input_mono32 }, |
228 | }; | 230 | }; |
229 | 231 | ||
230 | struct dsp_buffer *src = *buf_p; | 232 | if (this->sample_buf.remcount > 0) |
231 | struct dsp_buffer *dst = &this->sample_buf; | 233 | return; |
232 | |||
233 | /* Ack configured format change */ | ||
234 | format_change_ack(&this->format); | ||
235 | 234 | ||
236 | if (dst->remcount > 0) | 235 | DSP_PRINT_FORMAT(DSP Input, this->format); |
237 | { | ||
238 | *buf_p = dst; | ||
239 | return; /* data still remains */ | ||
240 | } | ||
241 | 236 | ||
242 | DSP_PRINT_FORMAT(DSP Input, -1, src->format); | 237 | this->format_dirty = 0; |
238 | this->sample_buf.format = *format; | ||
239 | this->input_samples = fns[this->stereo_mode] | ||
240 | [this->sample_depth > NATIVE_DEPTH ? 1 : 0]; | ||
241 | } | ||
243 | 242 | ||
244 | /* new format - remember it and pass it along */ | 243 | /* increment the format version counter */ |
245 | dst->format = src->format; | 244 | static void format_change_set(struct sample_io_data *this) |
246 | this->input_samples[0] = fns[this->stereo_mode] | 245 | { |
247 | [this->sample_depth > NATIVE_DEPTH ? 1 : 0]; | 246 | if (this->format_dirty) |
247 | return; | ||
248 | 248 | ||
249 | this->input_samples[0](this, buf_p); | 249 | this->format.version = (uint8_t)(this->format.version + 1) ?: 1; |
250 | this->format_dirty = 1; | ||
251 | } | ||
250 | 252 | ||
251 | if (*buf_p == dst) /* buffer switch? */ | 253 | /* discard the sample buffer */ |
252 | format_change_ack(&src->format); | 254 | static void dsp_sample_input_flush(struct sample_io_data *this) |
255 | { | ||
256 | this->sample_buf.remcount = 0; | ||
253 | } | 257 | } |
254 | 258 | ||
255 | static void dsp_sample_input_init(struct sample_io_data *this, | 259 | static void INIT_ATTR dsp_sample_input_init(struct sample_io_data *this, |
256 | enum dsp_ids dsp_id) | 260 | enum dsp_ids dsp_id) |
257 | { | 261 | { |
258 | int32_t *lbuf, *rbuf; | 262 | int32_t *lbuf, *rbuf; |
259 | 263 | ||
@@ -274,17 +278,15 @@ static void dsp_sample_input_init(struct sample_io_data *this, | |||
274 | return; | 278 | return; |
275 | } | 279 | } |
276 | 280 | ||
277 | this->sample_buf_arr[0] = lbuf; | 281 | this->sample_buf_p[0] = lbuf; |
278 | this->sample_buf_arr[1] = rbuf; | 282 | this->sample_buf_p[1] = rbuf; |
279 | |||
280 | this->input_samples[0] = sample_input_ni_stereo32; | ||
281 | this->input_samples[1] = dsp_sample_input_format_change; | ||
282 | } | 283 | } |
283 | 284 | ||
284 | /* discard the sample buffer */ | 285 | static void INIT_ATTR dsp_sample_io_init(struct sample_io_data *this, |
285 | static void dsp_sample_input_flush(struct sample_io_data *this) | 286 | enum dsp_ids dsp_id) |
286 | { | 287 | { |
287 | this->sample_buf.remcount = 0; | 288 | dsp_sample_input_init(this, dsp_id); |
289 | dsp_sample_output_init(this); | ||
288 | } | 290 | } |
289 | 291 | ||
290 | void dsp_sample_io_configure(struct sample_io_data *this, | 292 | void dsp_sample_io_configure(struct sample_io_data *this, |
@@ -294,13 +296,12 @@ void dsp_sample_io_configure(struct sample_io_data *this, | |||
294 | switch (setting) | 296 | switch (setting) |
295 | { | 297 | { |
296 | case DSP_INIT: | 298 | case DSP_INIT: |
297 | dsp_sample_input_init(this, (enum dsp_ids)value); | 299 | dsp_sample_io_init(this, (enum dsp_ids)value); |
298 | dsp_sample_output_init(this); | ||
299 | break; | 300 | break; |
300 | 301 | ||
301 | case DSP_RESET: | 302 | case DSP_RESET: |
302 | /* Reset all sample descriptions to default */ | 303 | /* Reset all sample descriptions to default */ |
303 | format_change_set(&this->format); | 304 | format_change_set(this); |
304 | this->format.num_channels = 2; | 305 | this->format.num_channels = 2; |
305 | this->format.frac_bits = WORD_FRACBITS; | 306 | this->format.frac_bits = WORD_FRACBITS; |
306 | this->format.output_scale = WORD_FRACBITS + 1 - NATIVE_DEPTH; | 307 | this->format.output_scale = WORD_FRACBITS + 1 - NATIVE_DEPTH; |
@@ -311,14 +312,14 @@ void dsp_sample_io_configure(struct sample_io_data *this, | |||
311 | break; | 312 | break; |
312 | 313 | ||
313 | case DSP_SET_FREQUENCY: | 314 | case DSP_SET_FREQUENCY: |
315 | format_change_set(this); | ||
314 | value = value > 0 ? value : NATIVE_FREQUENCY; | 316 | value = value > 0 ? value : NATIVE_FREQUENCY; |
315 | format_change_set(&this->format); | ||
316 | this->format.frequency = value; | 317 | this->format.frequency = value; |
317 | this->format.codec_frequency = value; | 318 | this->format.codec_frequency = value; |
318 | break; | 319 | break; |
319 | 320 | ||
320 | case DSP_SET_SAMPLE_DEPTH: | 321 | case DSP_SET_SAMPLE_DEPTH: |
321 | format_change_set(&this->format); | 322 | format_change_set(this); |
322 | this->format.frac_bits = | 323 | this->format.frac_bits = |
323 | value <= NATIVE_DEPTH ? WORD_FRACBITS : value; | 324 | value <= NATIVE_DEPTH ? WORD_FRACBITS : value; |
324 | this->format.output_scale = | 325 | this->format.output_scale = |
@@ -327,7 +328,7 @@ void dsp_sample_io_configure(struct sample_io_data *this, | |||
327 | break; | 328 | break; |
328 | 329 | ||
329 | case DSP_SET_STEREO_MODE: | 330 | case DSP_SET_STEREO_MODE: |
330 | format_change_set(&this->format); | 331 | format_change_set(this); |
331 | this->format.num_channels = value == STEREO_MONO ? 1 : 2; | 332 | this->format.num_channels = value == STEREO_MONO ? 1 : 2; |
332 | this->stereo_mode = value; | 333 | this->stereo_mode = value; |
333 | break; | 334 | break; |
@@ -336,5 +337,12 @@ void dsp_sample_io_configure(struct sample_io_data *this, | |||
336 | dsp_sample_input_flush(this); | 337 | dsp_sample_input_flush(this); |
337 | dsp_sample_output_flush(this); | 338 | dsp_sample_output_flush(this); |
338 | break; | 339 | break; |
340 | |||
341 | case DSP_SET_PITCH: | ||
342 | format_change_set(this); | ||
343 | value = value > 0 ? value : (1 << 16); | ||
344 | this->format.frequency = | ||
345 | fp_mul(value, this->format.codec_frequency, 16); | ||
346 | break; | ||
339 | } | 347 | } |
340 | } | 348 | } |
diff --git a/lib/rbcodec/dsp/dsp_sample_io.h b/lib/rbcodec/dsp/dsp_sample_io.h index 0afe75c6ca..22b7a4a3f4 100644 --- a/lib/rbcodec/dsp/dsp_sample_io.h +++ b/lib/rbcodec/dsp/dsp_sample_io.h | |||
@@ -42,16 +42,25 @@ typedef void (*sample_output_fn_type)(struct sample_io_data *this, | |||
42 | /* This becomes part of the DSP aggregate */ | 42 | /* This becomes part of the DSP aggregate */ |
43 | struct sample_io_data | 43 | struct sample_io_data |
44 | { | 44 | { |
45 | int outcount; /* 00h: Output count */ | 45 | int outcount; /* 00h: Output count */ |
46 | struct sample_format format; /* General format info */ | 46 | struct sample_format format; /* Format for next dsp_process call */ |
47 | int sample_depth; /* Codec-specified sample depth */ | 47 | int sample_depth; /* Codec-specified sample depth */ |
48 | int stereo_mode; /* Codec-specified input format */ | 48 | int stereo_mode; /* Codec-specified channel format */ |
49 | sample_input_fn_type input_samples[2]; /* input functions */ | 49 | sample_input_fn_type input_samples; /* Initial input function */ |
50 | struct dsp_buffer sample_buf; /* Buffer descriptor for converted samples */ | 50 | struct dsp_buffer sample_buf; /* Buffer descriptor for converted samples */ |
51 | int32_t *sample_buf_arr[2]; /* Internal format buffer pointers */ | 51 | int32_t *sample_buf_p[2]; /* Internal format buffer pointers */ |
52 | sample_output_fn_type output_samples[2]; /* Final output functions */ | 52 | sample_output_fn_type output_samples; /* Final output function */ |
53 | uint8_t format_dirty; /* Format change set, avoids superfluous | ||
54 | increments before carrying it out */ | ||
55 | uint8_t output_version; /* Format version of src buffer at output */ | ||
53 | }; | 56 | }; |
54 | 57 | ||
58 | void dsp_sample_input_format_change(struct sample_io_data *this, | ||
59 | struct sample_format *format); | ||
60 | |||
61 | void dsp_sample_output_format_change(struct sample_io_data *this, | ||
62 | struct sample_format *format); | ||
63 | |||
55 | /* Sample IO watches the format setting from the codec */ | 64 | /* Sample IO watches the format setting from the codec */ |
56 | void dsp_sample_io_configure(struct sample_io_data *this, | 65 | void dsp_sample_io_configure(struct sample_io_data *this, |
57 | unsigned int setting, | 66 | unsigned int setting, |
diff --git a/lib/rbcodec/dsp/dsp_sample_output.c b/lib/rbcodec/dsp/dsp_sample_output.c index 4a8050b082..d57d236cbb 100644 --- a/lib/rbcodec/dsp/dsp_sample_output.c +++ b/lib/rbcodec/dsp/dsp_sample_output.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "dsp_core.h" | 24 | #include "dsp_core.h" |
25 | #include "dsp_sample_io.h" | 25 | #include "dsp_sample_io.h" |
26 | #include "dsp_proc_entry.h" | ||
26 | #include "dsp-util.h" | 27 | #include "dsp-util.h" |
27 | #include <string.h> | 28 | #include <string.h> |
28 | 29 | ||
@@ -159,9 +160,8 @@ void sample_output_dithered(struct sample_io_data *this, | |||
159 | } | 160 | } |
160 | 161 | ||
161 | /* Initialize the output function for settings and format */ | 162 | /* Initialize the output function for settings and format */ |
162 | static void dsp_sample_output_format_change(struct sample_io_data *this, | 163 | void dsp_sample_output_format_change(struct sample_io_data *this, |
163 | struct dsp_buffer *src, | 164 | struct sample_format *format) |
164 | struct dsp_buffer *dst) | ||
165 | { | 165 | { |
166 | static const sample_output_fn_type fns[2][2] = | 166 | static const sample_output_fn_type fns[2][2] = |
167 | { | 167 | { |
@@ -171,25 +171,20 @@ static void dsp_sample_output_format_change(struct sample_io_data *this, | |||
171 | sample_output_dithered }, | 171 | sample_output_dithered }, |
172 | }; | 172 | }; |
173 | 173 | ||
174 | struct sample_format *format = &src->format; | ||
175 | bool dither = dsp_get_id((void *)this) == CODEC_IDX_AUDIO && | 174 | bool dither = dsp_get_id((void *)this) == CODEC_IDX_AUDIO && |
176 | dither_data.enabled; | 175 | dither_data.enabled; |
177 | int channels = format->num_channels; | 176 | int channels = format->num_channels; |
178 | 177 | ||
179 | DSP_PRINT_FORMAT(DSP Output, -1, *format); | 178 | DSP_PRINT_FORMAT(DSP Output, *format); |
180 | 179 | ||
181 | this->output_samples[0] = fns[dither ? 1 : 0][channels - 1]; | 180 | this->output_samples = fns[dither ? 1 : 0][channels - 1]; |
182 | format_change_ack(format); /* always ack, we're last */ | 181 | this->output_version = format->version; |
183 | |||
184 | /* The real function mustn't be called with no data */ | ||
185 | if (this->outcount > 0) | ||
186 | this->output_samples[0](this, src, dst); | ||
187 | } | 182 | } |
188 | 183 | ||
189 | void dsp_sample_output_init(struct sample_io_data *this) | 184 | void INIT_ATTR dsp_sample_output_init(struct sample_io_data *this) |
190 | { | 185 | { |
191 | this->output_samples[0] = sample_output_stereo; | 186 | this->output_version = 0; |
192 | this->output_samples[1] = dsp_sample_output_format_change; | 187 | this->output_samples = sample_output_stereo; |
193 | } | 188 | } |
194 | 189 | ||
195 | /* Flush the dither history */ | 190 | /* Flush the dither history */ |
@@ -199,6 +194,7 @@ void dsp_sample_output_flush(struct sample_io_data *this) | |||
199 | memset(dither_data.state, 0, sizeof (dither_data.state)); | 194 | memset(dither_data.state, 0, sizeof (dither_data.state)); |
200 | } | 195 | } |
201 | 196 | ||
197 | |||
202 | /** Output settings **/ | 198 | /** Output settings **/ |
203 | 199 | ||
204 | /* Set the tri-pdf dithered output */ | 200 | /* Set the tri-pdf dithered output */ |
@@ -207,8 +203,11 @@ void dsp_dither_enable(bool enable) | |||
207 | if (enable == dither_data.enabled) | 203 | if (enable == dither_data.enabled) |
208 | return; | 204 | return; |
209 | 205 | ||
210 | struct sample_io_data *data = (void *)dsp_get_config(CODEC_IDX_AUDIO); | ||
211 | dsp_sample_output_flush(data); | ||
212 | dither_data.enabled = enable; | 206 | dither_data.enabled = enable; |
213 | data->output_samples[0] = dsp_sample_output_format_change; | 207 | struct sample_io_data *data = (void *)dsp_get_config(CODEC_IDX_AUDIO); |
208 | |||
209 | if (enable) | ||
210 | dsp_sample_output_flush(data); | ||
211 | |||
212 | data->output_version = 0; /* Force format update */ | ||
214 | } | 213 | } |
diff --git a/lib/rbcodec/dsp/eq.c b/lib/rbcodec/dsp/eq.c index d58f0959b2..372ef9bbad 100644 --- a/lib/rbcodec/dsp/eq.c +++ b/lib/rbcodec/dsp/eq.c | |||
@@ -156,8 +156,10 @@ static intptr_t eq_configure(struct dsp_proc_entry *this, | |||
156 | { | 156 | { |
157 | case DSP_PROC_INIT: | 157 | case DSP_PROC_INIT: |
158 | if (value != 0) | 158 | if (value != 0) |
159 | break; | 159 | break; /* Already enabled */ |
160 | this->process[0] = eq_process; | 160 | |
161 | this->process = eq_process; | ||
162 | /* Fall-through */ | ||
161 | case DSP_PROC_CLOSE: | 163 | case DSP_PROC_CLOSE: |
162 | pga_enable_gain(PGA_EQ_PRECUT, setting == DSP_PROC_INIT); | 164 | pga_enable_gain(PGA_EQ_PRECUT, setting == DSP_PROC_INIT); |
163 | break; | 165 | break; |
@@ -167,7 +169,7 @@ static intptr_t eq_configure(struct dsp_proc_entry *this, | |||
167 | break; | 169 | break; |
168 | } | 170 | } |
169 | 171 | ||
170 | return 1; | 172 | return 0; |
171 | (void)dsp; | 173 | (void)dsp; |
172 | } | 174 | } |
173 | 175 | ||
diff --git a/lib/rbcodec/dsp/lin_resample.c b/lib/rbcodec/dsp/lin_resample.c index 34dc35b2dd..20bb78e68d 100644 --- a/lib/rbcodec/dsp/lin_resample.c +++ b/lib/rbcodec/dsp/lin_resample.c | |||
@@ -51,9 +51,8 @@ static struct resample_data | |||
51 | int32_t last_sample[2]; /* 08h: Last samples for interpolation (L+R) */ | 51 | int32_t last_sample[2]; /* 08h: Last samples for interpolation (L+R) */ |
52 | /* 10h */ | 52 | /* 10h */ |
53 | int32_t frequency; /* Virtual samplerate */ | 53 | int32_t frequency; /* Virtual samplerate */ |
54 | struct dsp_config *dsp; /* The DSP for this resampler */ | ||
55 | struct dsp_buffer resample_buf; /* Buffer descriptor for resampled data */ | 54 | struct dsp_buffer resample_buf; /* Buffer descriptor for resampled data */ |
56 | int32_t *resample_buf_arr[2]; /* Actual output data pointers */ | 55 | int32_t *resample_out_p[2]; /* Actual output buffer pointers */ |
57 | } resample_data[DSP_COUNT] IBSS_ATTR; | 56 | } resample_data[DSP_COUNT] IBSS_ATTR; |
58 | 57 | ||
59 | /* Actual worker function. Implemented here or in target assembly code. */ | 58 | /* Actual worker function. Implemented here or in target assembly code. */ |
@@ -75,9 +74,9 @@ static void lin_resample_flush(struct dsp_proc_entry *this) | |||
75 | } | 74 | } |
76 | 75 | ||
77 | static bool lin_resample_new_delta(struct resample_data *data, | 76 | static bool lin_resample_new_delta(struct resample_data *data, |
78 | struct dsp_buffer *buf) | 77 | struct sample_format *format) |
79 | { | 78 | { |
80 | int32_t frequency = buf->format.frequency; /* virtual samplerate */ | 79 | int32_t frequency = format->frequency; /* virtual samplerate */ |
81 | 80 | ||
82 | data->frequency = frequency; | 81 | data->frequency = frequency; |
83 | data->delta = fp_div(frequency, NATIVE_FREQUENCY, 16); | 82 | data->delta = fp_div(frequency, NATIVE_FREQUENCY, 16); |
@@ -169,8 +168,8 @@ static void lin_resample_process(struct dsp_proc_entry *this, | |||
169 | return; /* data still remains */ | 168 | return; /* data still remains */ |
170 | 169 | ||
171 | dst->remcount = 0; | 170 | dst->remcount = 0; |
172 | dst->p32[0] = data->resample_buf_arr[0]; | 171 | dst->p32[0] = data->resample_out_p[0]; |
173 | dst->p32[1] = data->resample_buf_arr[1]; | 172 | dst->p32[1] = data->resample_out_p[1]; |
174 | 173 | ||
175 | if (src->remcount > 0) | 174 | if (src->remcount > 0) |
176 | { | 175 | { |
@@ -189,63 +188,44 @@ static void lin_resample_process(struct dsp_proc_entry *this, | |||
189 | } | 188 | } |
190 | 189 | ||
191 | /* Finish draining old samples then switch format or shut off */ | 190 | /* Finish draining old samples then switch format or shut off */ |
192 | static void lin_resample_new_format(struct dsp_proc_entry *this, | 191 | static intptr_t lin_resample_new_format(struct dsp_proc_entry *this, |
193 | struct dsp_buffer **buf_p) | 192 | struct dsp_config *dsp, |
193 | struct sample_format *format) | ||
194 | { | 194 | { |
195 | struct resample_data *data = (void *)this->data; | 195 | struct resample_data *data = (void *)this->data; |
196 | struct dsp_buffer *src = *buf_p; | ||
197 | struct dsp_buffer *dst = &data->resample_buf; | 196 | struct dsp_buffer *dst = &data->resample_buf; |
198 | 197 | ||
199 | if (dst->remcount > 0) | 198 | if (dst->remcount > 0) |
200 | { | 199 | return PROC_NEW_FORMAT_TRANSITION; |
201 | *buf_p = dst; | ||
202 | return; /* data still remains */ | ||
203 | } | ||
204 | 200 | ||
205 | DSP_PRINT_FORMAT(DSP_PROC_RESAMPLE, DSP_PROC_RESAMPLE, src->format); | 201 | DSP_PRINT_FORMAT(DSP_PROC_RESAMPLE, *format); |
206 | 202 | ||
207 | struct dsp_config *dsp = data->dsp; | ||
208 | int32_t frequency = data->frequency; | 203 | int32_t frequency = data->frequency; |
209 | bool active = dsp_proc_active(dsp, DSP_PROC_RESAMPLE); | 204 | bool active = dsp_proc_active(dsp, DSP_PROC_RESAMPLE); |
210 | 205 | ||
211 | if (src->format.frequency != frequency) | 206 | if (format->frequency != frequency) |
212 | { | 207 | { |
213 | DEBUGF(" DSP_PROC_RESAMPLE- new delta\n"); | 208 | DEBUGF(" DSP_PROC_RESAMPLE- new delta\n"); |
214 | active = lin_resample_new_delta(data, src); | 209 | active = lin_resample_new_delta(data, format); |
215 | dsp_proc_activate(dsp, DSP_PROC_RESAMPLE, active); | 210 | dsp_proc_activate(dsp, DSP_PROC_RESAMPLE, active); |
216 | } | 211 | } |
217 | 212 | ||
218 | /* Everything after us is NATIVE_FREQUENCY */ | 213 | /* Everything after us is NATIVE_FREQUENCY */ |
219 | struct sample_format f = src->format; | 214 | dst->format = *format; |
220 | f.frequency = NATIVE_FREQUENCY; | 215 | dst->format.frequency = NATIVE_FREQUENCY; |
221 | f.codec_frequency = NATIVE_FREQUENCY; | 216 | dst->format.codec_frequency = NATIVE_FREQUENCY; |
222 | |||
223 | if (!active) | ||
224 | { | ||
225 | DEBUGF(" DSP_PROC_RESAMPLE- not active\n"); | ||
226 | dst->format = f; /* Keep track */ | ||
227 | return; /* No resampling required */ | ||
228 | } | ||
229 | |||
230 | format_change_ack(&src->format); | ||
231 | 217 | ||
232 | if (EQU_SAMPLE_FORMAT(f, dst->format)) | 218 | if (active) |
233 | { | 219 | return PROC_NEW_FORMAT_OK; |
234 | DEBUGF(" DSP_PROC_RESAMPLE- same dst format\n"); | ||
235 | format_change_ack(&f); /* Nothing changed that matters downstream */ | ||
236 | } | ||
237 | 220 | ||
238 | dst->format = f; | 221 | /* No longer needed */ |
239 | dsp_proc_call(this, buf_p, 0); | 222 | DEBUGF(" DSP_PROC_RESAMPLE- deactivated\n"); |
223 | return PROC_NEW_FORMAT_DEACTIVATED; | ||
240 | } | 224 | } |
241 | 225 | ||
242 | static void lin_resample_init(struct dsp_config *dsp, | 226 | static void INIT_ATTR lin_resample_dsp_init(struct dsp_config *dsp, |
243 | enum dsp_ids dsp_id) | 227 | enum dsp_ids dsp_id) |
244 | { | 228 | { |
245 | /* Always enable resampler so that format changes may be monitored and | ||
246 | * it self-activated when required */ | ||
247 | dsp_proc_enable(dsp, DSP_PROC_RESAMPLE, true); | ||
248 | |||
249 | int32_t *lbuf, *rbuf; | 229 | int32_t *lbuf, *rbuf; |
250 | 230 | ||
251 | switch (dsp_id) | 231 | switch (dsp_id) |
@@ -265,8 +245,19 @@ static void lin_resample_init(struct dsp_config *dsp, | |||
265 | return; | 245 | return; |
266 | } | 246 | } |
267 | 247 | ||
268 | resample_data[dsp_id].resample_buf_arr[0] = lbuf; | 248 | /* Always enable resampler so that format changes may be monitored and |
269 | resample_data[dsp_id].resample_buf_arr[1] = rbuf; | 249 | * it self-activated when required */ |
250 | dsp_proc_enable(dsp, DSP_PROC_RESAMPLE, true); | ||
251 | resample_data[dsp_id].resample_out_p[0] = lbuf; | ||
252 | resample_data[dsp_id].resample_out_p[1] = rbuf; | ||
253 | } | ||
254 | |||
255 | static void INIT_ATTR lin_resample_proc_init(struct dsp_proc_entry *this, | ||
256 | struct dsp_config *dsp) | ||
257 | { | ||
258 | dsp_proc_set_in_place(dsp, DSP_PROC_RESAMPLE, false); | ||
259 | this->data = (intptr_t)&resample_data[dsp_get_id(dsp)]; | ||
260 | this->process = lin_resample_process; | ||
270 | } | 261 | } |
271 | 262 | ||
272 | /* DSP message hook */ | 263 | /* DSP message hook */ |
@@ -275,10 +266,12 @@ static intptr_t lin_resample_configure(struct dsp_proc_entry *this, | |||
275 | unsigned int setting, | 266 | unsigned int setting, |
276 | intptr_t value) | 267 | intptr_t value) |
277 | { | 268 | { |
269 | intptr_t retval = 0; | ||
270 | |||
278 | switch (setting) | 271 | switch (setting) |
279 | { | 272 | { |
280 | case DSP_INIT: | 273 | case DSP_INIT: |
281 | lin_resample_init(dsp, (enum dsp_ids)value); | 274 | lin_resample_dsp_init(dsp, (enum dsp_ids)value); |
282 | break; | 275 | break; |
283 | 276 | ||
284 | case DSP_FLUSH: | 277 | case DSP_FLUSH: |
@@ -286,21 +279,21 @@ static intptr_t lin_resample_configure(struct dsp_proc_entry *this, | |||
286 | break; | 279 | break; |
287 | 280 | ||
288 | case DSP_PROC_INIT: | 281 | case DSP_PROC_INIT: |
289 | this->data = (intptr_t)&resample_data[dsp_get_id(dsp)]; | 282 | lin_resample_proc_init(this, dsp); |
290 | this->ip_mask = 0; /* Not in-place */ | ||
291 | this->process[0] = lin_resample_process; | ||
292 | this->process[1] = lin_resample_new_format; | ||
293 | ((struct resample_data *)this->data)->dsp = dsp; | ||
294 | break; | 283 | break; |
295 | 284 | ||
296 | case DSP_PROC_CLOSE: | 285 | case DSP_PROC_CLOSE: |
297 | /* This stage should be enabled at all times */ | 286 | /* This stage should be enabled at all times */ |
298 | DEBUGF("DSP_PROC_RESAMPLE- Error: Closing!\n"); | 287 | DEBUGF("DSP_PROC_RESAMPLE- Error: Closing!\n"); |
299 | break; | 288 | break; |
289 | |||
290 | case DSP_PROC_NEW_FORMAT: | ||
291 | retval = lin_resample_new_format(this, dsp, | ||
292 | (struct sample_format *)value); | ||
293 | break; | ||
300 | } | 294 | } |
301 | 295 | ||
302 | return 1; | 296 | return retval; |
303 | (void)value; | ||
304 | } | 297 | } |
305 | 298 | ||
306 | /* Database entry */ | 299 | /* Database entry */ |
diff --git a/lib/rbcodec/dsp/pga.c b/lib/rbcodec/dsp/pga.c index de852d01d4..522789fcf2 100644 --- a/lib/rbcodec/dsp/pga.c +++ b/lib/rbcodec/dsp/pga.c | |||
@@ -129,13 +129,14 @@ static intptr_t pga_configure(struct dsp_proc_entry *this, | |||
129 | { | 129 | { |
130 | case DSP_PROC_INIT: | 130 | case DSP_PROC_INIT: |
131 | if (value != 0) | 131 | if (value != 0) |
132 | break; /* Already initialized */ | 132 | break; /* Already enabled */ |
133 | |||
133 | this->data = (intptr_t)&pga_data; | 134 | this->data = (intptr_t)&pga_data; |
134 | this->process[0] = pga_process; | 135 | this->process = pga_process; |
135 | break; | 136 | break; |
136 | } | 137 | } |
137 | 138 | ||
138 | return 1; | 139 | return 0; |
139 | (void)dsp; | 140 | (void)dsp; |
140 | } | 141 | } |
141 | 142 | ||
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) |
diff --git a/lib/rbcodec/dsp/tone_controls.c b/lib/rbcodec/dsp/tone_controls.c index 922c966e3f..01381ea330 100644 --- a/lib/rbcodec/dsp/tone_controls.c +++ b/lib/rbcodec/dsp/tone_controls.c | |||
@@ -90,7 +90,7 @@ static void tone_process(struct dsp_proc_entry *this, | |||
90 | struct dsp_buffer **buf_p) | 90 | struct dsp_buffer **buf_p) |
91 | { | 91 | { |
92 | struct dsp_buffer *buf = *buf_p; | 92 | struct dsp_buffer *buf = *buf_p; |
93 | filter_process((void *)this->data, buf->p32, buf->remcount, | 93 | filter_process((struct dsp_filter *)this->data, buf->p32, buf->remcount, |
94 | buf->format.num_channels); | 94 | buf->format.num_channels); |
95 | } | 95 | } |
96 | 96 | ||
@@ -104,15 +104,17 @@ static intptr_t tone_configure(struct dsp_proc_entry *this, | |||
104 | { | 104 | { |
105 | case DSP_PROC_INIT: | 105 | case DSP_PROC_INIT: |
106 | if (value != 0) | 106 | if (value != 0) |
107 | break; | 107 | break; /* Already enabled */ |
108 | |||
108 | this->data = (intptr_t)&tone_filters[dsp_get_id(dsp)]; | 109 | this->data = (intptr_t)&tone_filters[dsp_get_id(dsp)]; |
109 | this->process[0] = tone_process; | 110 | this->process = tone_process; |
111 | /* Fall-through */ | ||
110 | case DSP_FLUSH: | 112 | case DSP_FLUSH: |
111 | filter_flush((struct dsp_filter *)this->data); | 113 | filter_flush((struct dsp_filter *)this->data); |
112 | break; | 114 | break; |
113 | } | 115 | } |
114 | 116 | ||
115 | return 1; | 117 | return 0; |
116 | } | 118 | } |
117 | 119 | ||
118 | /* Database entry */ | 120 | /* Database entry */ |