Merge branch 'maint'
[paraslash.git] / resample_filter.c
1 /* Copyright (C) 2012 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
2
3 /** \file resample_filter.c A sample rate converter based on libsamplerate. */
4
5 #include <regex.h>
6 #include <samplerate.h>
7 #include <lopsub.h>
8
9 #include "filter_cmd.lsg.h"
10 #include "para.h"
11 #include "error.h"
12 #include "list.h"
13 #include "sched.h"
14 #include "buffer_tree.h"
15 #include "filter.h"
16 #include "string.h"
17 #include "check_wav.h"
18
19 #define U32_OPTVAL(_opt, _lpr) (FILTER_CMD_OPT_UINT32_VAL(RESAMPLE, _opt, _lpr))
20 #define OPT_GIVEN(_opt, _lpr) (FILTER_CMD_OPT_GIVEN(RESAMPLE, _opt, _lpr))
21
22 /* effective values, may differ from config arg */
23 struct resample_context {
24         uint32_t channels;
25         int source_sample_rate;
26         float ratio;
27         SRC_STATE *src_state;
28         struct check_wav_context *cwc;
29 };
30
31 static int resample_execute(struct btr_node *btrn, const char *cmd, char **result)
32 {
33         struct filter_node *fn = btr_context(btrn);
34         struct resample_context *ctx = fn->private_data;
35         uint32_t dsr = U32_OPTVAL(DEST_SAMPLE_RATE, fn->lpr);
36         return decoder_execute(cmd, dsr, ctx->channels, result);
37 }
38
39 static void resample_close(struct filter_node *fn)
40 {
41         struct resample_context *ctx = fn->private_data;
42
43         if (!ctx)
44                 return;
45         check_wav_shutdown(ctx->cwc);
46         if (ctx->src_state)
47                 src_delete(ctx->src_state);
48         free(ctx);
49         fn->private_data = NULL;
50 }
51
52 static void resample_open(struct filter_node *fn)
53 {
54         struct resample_context *ctx = para_calloc(sizeof(*ctx));
55         struct btr_node *btrn = fn->btrn;
56         struct wav_params wp;
57
58         fn->private_data = ctx;
59         fn->min_iqs = 2;
60         LLS_COPY_WAV_PARMS(&wp, LSG_FILTER_CMD_RESAMPLE, fn->lpr);
61         ctx->cwc = check_wav_init(btr_parent(btrn), btrn, &wp, NULL);
62         btr_log_tree(btr_parent(btr_parent(btrn)), LL_INFO);
63 }
64
65 static void resample_pre_select(struct sched *s, void *context)
66 {
67         struct filter_node *fn = context;
68         struct resample_context *ctx = fn->private_data;
69         int ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL);
70
71         if (ret != 0)
72                 return sched_min_delay(s);
73         check_wav_pre_select(s, ctx->cwc);
74 }
75
76 static int get_btr_val(const char *what, struct btr_node *btrn)
77 {
78         char *buf;
79         int32_t val;
80         int ret = btr_exec_up(btr_parent(btrn), what, &buf);
81
82         if (ret < 0) {
83                 PARA_NOTICE_LOG("btr exec for \"%s\" failed\n", what);
84                 return ret;
85         }
86         ret = para_atoi32(buf, &val);
87         free(buf);
88         return ret < 0? ret : val;
89 }
90
91 static int resample_set_params(struct filter_node *fn)
92 {
93         int ret;
94         struct resample_context *ctx = fn->private_data;
95         struct btr_node *btrn = fn->btrn;
96         struct lls_parse_result *lpr = fn->lpr;
97
98         ctx->channels = U32_OPTVAL(CHANNELS, lpr);
99         if (!OPT_GIVEN(CHANNELS, lpr)) {
100                 ret = get_btr_val("channels", btrn);
101                 if (ret >= 0)
102                         ctx->channels = ret;
103         }
104         ctx->source_sample_rate = U32_OPTVAL(SAMPLE_RATE, lpr);
105         if (!OPT_GIVEN(SAMPLE_RATE, lpr)) {
106                 ret = get_btr_val("sample_rate", btrn);
107                 if (ret >= 0)
108                         ctx->source_sample_rate = ret;
109         }
110         /* reject all sample formats except 16 bit signed, little endian */
111         ret = get_btr_val("sample_format", btrn);
112         if (ret >= 0 && ret != SF_S16_LE) {
113                 const char * const sample_formats[] = {SAMPLE_FORMATS};
114                 PARA_ERROR_LOG("unsupported sample format: %s\n",
115                         sample_formats[ret]);
116                 return -ERRNO_TO_PARA_ERROR(EINVAL);
117         }
118         ctx->ratio = U32_OPTVAL(DEST_SAMPLE_RATE, lpr)
119                 / (float)ctx->source_sample_rate;
120         return 1;
121 }
122
123 static int resample_init(struct filter_node *fn)
124 {
125         int ret;
126         const uint32_t trafo[] = {
127                 [RCT_BEST] = SRC_SINC_BEST_QUALITY,
128                 [RCT_MEDIUM] = SRC_SINC_MEDIUM_QUALITY,
129                 [RCT_FASTEST] = SRC_SINC_FASTEST,
130                 [RCT_ZERO_ORDER_HOLD] = SRC_ZERO_ORDER_HOLD,
131                 [RCT_LINEAR] = SRC_LINEAR
132         };
133         struct resample_context *ctx = fn->private_data;
134         const struct lls_option *o_c = FILTER_CMD_OPT(RESAMPLE, CONVERTER);
135         uint32_t converter = U32_OPTVAL(CONVERTER, fn->lpr);
136
137         PARA_INFO_LOG("converter type: %s\n",
138                 lls_enum_string_val(converter, o_c));
139         ret = resample_set_params(fn);
140         if (ret < 0)
141                 return ret;
142         ctx->src_state = src_new(trafo[converter],
143                 U32_OPTVAL(CHANNELS, fn->lpr), &ret);
144         if (!ctx->src_state) {
145                 PARA_ERROR_LOG("%s\n", src_strerror(ret));
146                 return -E_LIBSAMPLERATE;
147         }
148         fn->min_iqs = 2 * ctx->channels;
149         return 1;
150 }
151
152 /* returns number of input frames used */
153 static int resample_frames(int16_t *in, size_t num_frames, bool have_more,
154                 struct resample_context *ctx, int16_t **result,
155                 size_t *result_frames)
156 {
157         int ret, num_samples, out_samples;
158         float *in_float;
159         int16_t *out;
160         SRC_DATA data;
161
162         data.src_ratio = ctx->ratio;
163         data.end_of_input = !have_more;
164
165         data.input_frames = num_frames;
166         num_samples = num_frames * ctx->channels;
167         data.output_frames = num_frames * ctx->ratio + 1;
168         out_samples = data.output_frames * ctx->channels;
169
170         in_float = para_malloc(num_samples * sizeof(float));
171         src_short_to_float_array(in, in_float, num_samples);
172         data.data_in = in_float;
173         data.data_out = para_malloc(out_samples * sizeof(float));
174         ret = src_process(ctx->src_state, &data);
175         free(in_float);
176         if (ret != 0) {
177                 PARA_ERROR_LOG("%s\n", src_strerror(ret));
178                 free(data.data_out);
179                 return -E_LIBSAMPLERATE;
180         }
181         out_samples = data.output_frames_gen * ctx->channels;
182         out = para_malloc(out_samples * sizeof(short));
183         src_float_to_short_array(data.data_out, out, out_samples);
184         free(data.data_out);
185         *result = out;
186         *result_frames = data.output_frames_gen;
187         return data.input_frames_used;
188 }
189
190 static int resample_post_select(__a_unused struct sched *s, void *context)
191 {
192         int ret;
193         struct filter_node *fn = context;
194         struct resample_context *ctx = fn->private_data;
195         struct btr_node *btrn = fn->btrn;
196         int16_t *in, *out;
197         size_t in_bytes, num_frames;
198         bool have_more;
199
200         ret = check_wav_post_select(ctx->cwc);
201         if (ret < 0)
202                 goto out;
203         ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
204         if (ret <= 0)
205                 goto out;
206         if (!ctx->src_state) {
207                 ret = resample_init(fn);
208                 if (ret <= 0)
209                         goto out;
210         }
211         if (ctx->source_sample_rate == U32_OPTVAL(DEST_SAMPLE_RATE, fn->lpr)) {
212                 /*
213                  * No resampling necessary. We do not splice ourselves out
214                  * though, since our children might want to ask us through the
215                  * btr exec mechanism for the destination samplerate and the
216                  * channel count.
217                  */
218                 btr_pushdown(btrn);
219                 return 0;
220         }
221         btr_merge(btrn, fn->min_iqs);
222         in_bytes = btr_next_buffer(btrn, (char **)&in);
223         ret = -E_RESAMPLE_EOF;
224         num_frames = in_bytes / 2 / ctx->channels;
225         if (num_frames == 0)
226                 goto out;
227         have_more = !btr_no_parent(btrn) ||
228                 btr_next_buffer_omit(btrn, in_bytes, NULL) > 0;
229         ret = resample_frames(in, num_frames, have_more, ctx, &out, &num_frames);
230         if (ret < 0)
231                 goto out;
232         btr_consume(btrn, ret * 2 * ctx->channels);
233         btr_add_output((char *)out, num_frames * 2 * ctx->channels, btrn);
234         return 0;
235 out:
236         if (ret < 0) {
237                 btr_remove_node(&fn->btrn);
238                 /* This releases the check_wav btr node */
239                 check_wav_post_select(ctx->cwc);
240         }
241         return ret;
242 }
243
244 static void *resample_setup(const struct lls_parse_result *lpr)
245 {
246         int given;
247         uint32_t u32;
248
249         /* sanity checks */
250         u32 = U32_OPTVAL(CHANNELS, lpr);
251         given = OPT_GIVEN(CHANNELS, lpr);
252         if (u32 == 0 && given) {
253                 PARA_EMERG_LOG("fatal: zero channels?!\n");
254                 exit(EXIT_FAILURE);
255         }
256         u32 = U32_OPTVAL(SAMPLE_RATE, lpr);
257         given = OPT_GIVEN(SAMPLE_RATE, lpr);
258         if (u32 == 0 && given) {
259                 PARA_EMERG_LOG("fatal: input sample rate can not be 0\n");
260                 exit(EXIT_FAILURE);
261         }
262         u32 = U32_OPTVAL(DEST_SAMPLE_RATE, lpr);
263         given = OPT_GIVEN(DEST_SAMPLE_RATE, lpr);
264         if (u32 == 0 && given) {
265                 PARA_EMERG_LOG("fatal: destination sample rate can not be 0\n");
266                 exit(EXIT_FAILURE);
267         }
268         return NULL;
269 }
270
271 static void resample_teardown(__a_unused const struct lls_parse_result *lpr,
272                 void *conf)
273 {
274         free(conf);
275 }
276
277 const struct filter lsg_filter_cmd_com_resample_user_data = {
278         .setup = resample_setup,
279         .open = resample_open,
280         .pre_select = resample_pre_select,
281         .post_select = resample_post_select,
282         .close = resample_close,
283         .teardown = resample_teardown,
284         .execute = resample_execute
285 };