diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2012-12-19 17:34:57 -0500 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2013-05-04 13:43:33 -0400 |
commit | 78a45b47dede5ddf35dfc53e965b486a79177b18 (patch) | |
tree | edb3ad7c101e600a7cc3be4b40380430cbeb3e55 /lib/rbcodec/dsp/dsp_core.c | |
parent | cdb71c707bb434f44368b72f2db3becc37b7a46c (diff) | |
download | rockbox-78a45b47dede5ddf35dfc53e965b486a79177b18.tar.gz rockbox-78a45b47dede5ddf35dfc53e965b486a79177b18.zip |
Cleanup and simplify latest DSP code incarnation.
Some things can just be a bit simpler in handling the list of stages
and some things, especially format change handling, can be simplified
for each stage implementation. Format changes are sent through the
configure() callback.
Hide some internal details and variables from processing stages and
let the core deal with it.
Do some miscellaneous cleanup and keep things a bit better factored.
Change-Id: I19dd8ce1d0b792ba914d426013088a49a52ecb7e
Diffstat (limited to 'lib/rbcodec/dsp/dsp_core.c')
-rw-r--r-- | lib/rbcodec/dsp/dsp_core.c | 342 |
1 files changed, 160 insertions, 182 deletions
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) |