@@ -25,6 +25,7 @@ extern "C" {
25
25
#include " util.h"
26
26
#include " codec.h"
27
27
#include " sampleconv.h"
28
+ #include " fir.h"
28
29
}
29
30
30
31
struct zita_convolver_state {
@@ -149,82 +150,47 @@ static void write_buf_floatp(sample_t *in, float **out, int channels, ssize_t s)
149
150
}
150
151
}
151
152
152
- struct effect * zita_convolver_effect_init (const struct effect_info *ei, const struct stream_info *istream, const char *channel_selector, const char *dir , int argc, const char * const *argv )
153
+ struct effect * zita_convolver_effect_init_with_filter (const struct effect_info *ei, const struct stream_info *istream, const char *channel_selector, sample_t *filter_data , int filter_channels, ssize_t filter_frames, int min_part_len, int max_part_len )
153
154
{
154
- int i, k;
155
- unsigned int min_part_len = 0 , max_part_len = 0 ;
156
155
struct effect *e;
157
156
struct zita_convolver_state *state;
158
- struct codec *c_filter;
159
- Convproc *cproc;
160
- sample_t *buf_interleaved;
161
- float **buf_planar;
162
- char *endptr, *fp;
163
157
164
- if (argc > 4 || argc < 2 ) {
165
- LOG_FMT (LL_ERROR, " %s: usage: %s" , argv[0 ], ei->usage );
158
+ const int n_channels = num_bits_set (channel_selector, istream->channels );
159
+ if (n_channels > MINIMUM (Convproc::MAXINP, Convproc::MAXOUT)) {
160
+ LOG_FMT (LL_ERROR, " %s: error: number of channels must not exceed %d" , ei->name , MINIMUM (Convproc::MAXINP, Convproc::MAXOUT));
166
161
return NULL ;
167
162
}
168
- if (argc > 2 ) {
169
- min_part_len = strtol (argv[ 1 ], &endptr, 10 );
170
- CHECK_ENDPTR (argv[ 1 ], endptr, " min_part_len " , return NULL ) ;
163
+ if (filter_channels != 1 && filter_channels != n_channels ) {
164
+ LOG_FMT (LL_ERROR, " %s: error: channel mismatch: channels=%d filter_channels=%d " , ei-> name , n_channels, filter_channels );
165
+ return NULL ;
171
166
}
172
- if (argc > 3 ) {
173
- max_part_len = strtol (argv[ 2 ], &endptr, 10 );
174
- CHECK_ENDPTR (argv[ 2 ], endptr, " max_part_len " , return NULL ) ;
167
+ if (filter_frames < 1 ) {
168
+ LOG_FMT (LL_ERROR, " %s: error: filter length must be >= 1 " , ei-> name );
169
+ return NULL ;
175
170
}
171
+
176
172
min_part_len = (min_part_len == 0 ) ? Convproc::MINPART : min_part_len;
177
173
max_part_len = (max_part_len == 0 ) ? Convproc::MAXPART : max_part_len;
178
174
if (min_part_len < Convproc::MINPART || min_part_len > Convproc::MAXPART || max_part_len < Convproc::MINPART || max_part_len > Convproc::MAXPART) {
179
- LOG_FMT (LL_ERROR, " %s: error: partition lengths must be within [%d,%d] or 0 for default" , argv[ 0 ] , Convproc::MINPART, Convproc::MAXPART);
175
+ LOG_FMT (LL_ERROR, " %s: error: partition lengths must be within [%d,%d] or 0 for default" , ei-> name , Convproc::MINPART, Convproc::MAXPART);
180
176
return NULL ;
181
177
}
182
178
if (max_part_len < min_part_len) {
183
- LOG_FMT (LL_ERROR, " %s: warning: max_part_len < min_part_len" , argv[ 0 ] );
179
+ LOG_FMT (LL_ERROR, " %s: warning: max_part_len < min_part_len" , ei-> name );
184
180
max_part_len = min_part_len;
185
181
}
186
182
187
- const int n_channels = num_bits_set (channel_selector, istream->channels );
188
- if (n_channels > MINIMUM (Convproc::MAXINP, Convproc::MAXOUT)) {
189
- LOG_FMT (LL_ERROR, " %s: error: number of channels must not exceed %d" , argv[0 ], MINIMUM (Convproc::MAXINP, Convproc::MAXOUT));
190
- return NULL ;
191
- }
192
- fp = construct_full_path (dir, argv[argc - 1 ]);
193
- struct codec_params c_params = CODEC_PARAMS_AUTO (fp, CODEC_MODE_READ);
194
- c_filter = init_codec (&c_params);
195
- if (c_filter == NULL ) {
196
- LOG_FMT (LL_ERROR, " %s: error: failed to open filter file: %s" , argv[0 ], fp);
197
- free (fp);
198
- return NULL ;
199
- }
200
- free (fp);
201
- if (c_filter->channels != 1 && c_filter->channels != n_channels) {
202
- LOG_FMT (LL_ERROR, " %s: error: channel mismatch: channels=%d filter_channels=%d" , argv[0 ], n_channels, c_filter->channels );
203
- destroy_codec (c_filter);
204
- return NULL ;
205
- }
206
- if (c_filter->fs != istream->fs ) {
207
- LOG_FMT (LL_ERROR, " %s: error: sample rate mismatch: fs=%d filter_fs=%d" , argv[0 ], istream->fs , c_filter->fs );
208
- destroy_codec (c_filter);
209
- return NULL ;
210
- }
211
- if (c_filter->frames < 1 ) {
212
- LOG_FMT (LL_ERROR, " %s: error: filter length must be >= 1" , argv[0 ]);
213
- destroy_codec (c_filter);
214
- return NULL ;
215
- }
216
- cproc = new Convproc;
183
+ Convproc *cproc = new Convproc;
217
184
#if ZITA_CONVOLVER_MAJOR_VERSION >= 4
218
- if (cproc->configure (n_channels, n_channels, c_filter-> frames , min_part_len, min_part_len, max_part_len, 0 .0f )) {
185
+ if (cproc->configure (n_channels, n_channels, filter_frames , min_part_len, min_part_len, max_part_len, 0 .0f )) {
219
186
#else
220
- if (cproc->configure (n_channels, n_channels, c_filter-> frames , min_part_len, min_part_len, max_part_len)) {
187
+ if (cproc->configure (n_channels, n_channels, filter_frames , min_part_len, min_part_len, max_part_len)) {
221
188
#endif
222
- LOG_FMT (LL_ERROR, " %s: error: failed to configure convolution engine" , argv[0 ]);
223
- destroy_codec (c_filter);
189
+ LOG_FMT (LL_ERROR, " %s: error: failed to configure convolution engine" , ei->name );
224
190
delete cproc;
225
191
return NULL ;
226
192
}
227
- LOG_FMT (LL_VERBOSE, " %s: info: filter_frames=%zd min_part_len=%d max_part_len=%d" , argv[ 0 ], c_filter-> frames , min_part_len, max_part_len);
193
+ LOG_FMT (LL_VERBOSE, " %s: info: filter_frames=%zd min_part_len=%d max_part_len=%d" , ei-> name , filter_frames , min_part_len, max_part_len);
228
194
229
195
e = (struct effect *) calloc (1 , sizeof (struct effect ));
230
196
e->name = ei->name ;
@@ -240,33 +206,63 @@ struct effect * zita_convolver_effect_init(const struct effect_info *ei, const s
240
206
e->destroy = zita_convolver_effect_destroy;
241
207
242
208
state = (struct zita_convolver_state *) calloc (1 , sizeof (struct zita_convolver_state ));
243
- state->filter_frames = c_filter-> frames ;
209
+ state->filter_frames = filter_frames ;
244
210
state->len = min_part_len;
245
211
state->cproc = cproc;
246
212
state->output = (sample_t **) calloc (istream->channels , sizeof (sample_t *));
247
- for (i = 0 ; i < istream->channels ; ++i)
213
+ for (int i = 0 ; i < istream->channels ; ++i)
248
214
state->output [i] = (sample_t *) calloc (state->len , sizeof (sample_t ));
249
215
e->data = (void *) state;
250
216
251
- buf_interleaved = (sample_t *) calloc (c_filter->frames * c_filter->channels , sizeof (sample_t ));
252
- if (c_filter->read (c_filter, buf_interleaved, c_filter->frames ) != c_filter->frames )
253
- LOG_FMT (LL_ERROR, " %s: warning: short read" , argv[0 ]);
254
- buf_planar = (float **) calloc (c_filter->channels , sizeof (float *));
255
- for (i = 0 ; i < c_filter->channels ; ++i)
256
- buf_planar[i] = (float *) calloc (c_filter->frames , sizeof (float ));
257
- write_buf_floatp (buf_interleaved, buf_planar, c_filter->channels , c_filter->frames );
258
- free (buf_interleaved);
259
- for (i = k = 0 ; i < istream->channels ; ++i) {
217
+ float **buf_planar = (float **) calloc (filter_channels, sizeof (float *));
218
+ for (int i = 0 ; i < filter_channels; ++i)
219
+ buf_planar[i] = (float *) calloc (filter_frames, sizeof (float ));
220
+ write_buf_floatp (filter_data, buf_planar, filter_channels, filter_frames);
221
+ for (int i = 0 , k = 0 ; i < istream->channels ; ++i) {
260
222
if (GET_BIT (channel_selector, i)) {
261
- cproc->impdata_create (k, k, 1 , buf_planar[(c_filter->channels == 1 ) ? 0 : k], 0 , c_filter->frames );
223
+ if (filter_channels == 1 && k > 0 ) cproc->impdata_link (0 , 0 , k, k);
224
+ else cproc->impdata_create (k, k, 1 , buf_planar[k], 0 , filter_frames);
262
225
++k;
263
226
}
264
227
}
265
- for (i = 0 ; i < c_filter-> channels ; ++i)
228
+ for (int i = 0 ; i < filter_channels ; ++i)
266
229
free (buf_planar[i]);
267
230
free (buf_planar);
268
- destroy_codec (c_filter);
231
+
269
232
cproc->start_process (0 , 0 );
233
+ return e;
234
+ }
235
+
236
+ struct effect * zita_convolver_effect_init (const struct effect_info *ei, const struct stream_info *istream, const char *channel_selector, const char *dir, int argc, const char *const *argv)
237
+ {
238
+ int filter_channels, min_part_len = 0 , max_part_len = 0 ;
239
+ ssize_t filter_frames;
240
+ struct effect *e;
241
+ sample_t *filter_data;
242
+ struct codec_params c_params;
243
+ struct dsp_getopt_state g = DSP_GETOPT_STATE_INITIALIZER;
244
+ char *endptr;
270
245
246
+ int err = fir_parse_opts (ei, istream, &c_params, &g, argc, argv, NULL , NULL );
247
+ if (err || g.ind < argc-3 || g.ind > argc-1 ) {
248
+ LOG_FMT (LL_ERROR, " %s: usage: %s" , argv[0 ], ei->usage );
249
+ return NULL ;
250
+ }
251
+ if (g.ind <= argc-2 ) {
252
+ min_part_len = strtol (argv[g.ind ], &endptr, 10 );
253
+ CHECK_ENDPTR (argv[g.ind ], endptr, " min_part_len" , return NULL );
254
+ ++g.ind ;
255
+ }
256
+ if (g.ind <= argc-2 ) {
257
+ max_part_len = strtol (argv[g.ind ], &endptr, 10 );
258
+ CHECK_ENDPTR (argv[g.ind ], endptr, " max_part_len" , return NULL );
259
+ ++g.ind ;
260
+ }
261
+ c_params.path = argv[g.ind ];
262
+ filter_data = fir_read_filter (ei, istream, dir, &c_params, &filter_channels, &filter_frames);
263
+ if (filter_data == NULL )
264
+ return NULL ;
265
+ e = zita_convolver_effect_init_with_filter (ei, istream, channel_selector, filter_data, filter_channels, filter_frames, min_part_len, max_part_len);
266
+ free (filter_data);
271
267
return e;
272
268
}
0 commit comments