1 /* Copyright (C) 2012 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
3 /** \file resample_filter.c A sample rate converter based on libsamplerate. */
6 #include <samplerate.h>
9 #include "filter_cmd.lsg.h"
14 #include "buffer_tree.h"
17 #include "check_wav.h"
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))
22 /* effective values, may differ from config arg */
23 struct resample_context {
25 int source_sample_rate;
28 struct check_wav_context *cwc;
31 static int resample_execute(const struct btr_node *btrn, const char *cmd,
34 struct filter_node *fn = btr_context(btrn);
35 struct resample_context *ctx = fn->private_data;
36 uint32_t dsr = U32_OPTVAL(DEST_SAMPLE_RATE, fn->lpr);
37 return decoder_execute(cmd, dsr, ctx->channels, result);
40 static void resample_close(struct filter_node *fn)
42 struct resample_context *ctx = fn->private_data;
46 check_wav_shutdown(ctx->cwc);
48 src_delete(ctx->src_state);
50 fn->private_data = NULL;
53 static void resample_open(struct filter_node *fn)
55 struct resample_context *ctx = zalloc(sizeof(*ctx));
56 struct btr_node *btrn = fn->btrn;
59 fn->private_data = ctx;
61 LLS_COPY_WAV_PARMS(&wp, LSG_FILTER_CMD_RESAMPLE, fn->lpr);
62 ctx->cwc = check_wav_init(btr_parent(btrn), btrn, &wp, NULL);
63 btr_log_tree(btr_parent(btr_parent(btrn)), LL_INFO);
66 static void resample_pre_monitor(struct sched *s, void *context)
68 struct filter_node *fn = context;
69 struct resample_context *ctx = fn->private_data;
70 int ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL);
73 return sched_min_delay(s);
74 check_wav_pre_monitor(s, ctx->cwc);
77 static int get_btr_val(const char *what, struct btr_node *btrn)
81 int ret = btr_exec_up(btr_parent(btrn), what, &buf);
84 PARA_NOTICE_LOG("btr exec for \"%s\" failed\n", what);
87 ret = para_atoi32(buf, &val);
89 return ret < 0? ret : val;
92 static int resample_set_params(struct filter_node *fn)
95 struct resample_context *ctx = fn->private_data;
96 struct btr_node *btrn = fn->btrn;
97 struct lls_parse_result *lpr = fn->lpr;
99 ctx->channels = U32_OPTVAL(CHANNELS, lpr);
100 if (!OPT_GIVEN(CHANNELS, lpr)) {
101 ret = get_btr_val("channels", btrn);
105 ctx->source_sample_rate = U32_OPTVAL(SAMPLE_RATE, lpr);
106 if (!OPT_GIVEN(SAMPLE_RATE, lpr)) {
107 ret = get_btr_val("sample_rate", btrn);
109 ctx->source_sample_rate = ret;
111 /* reject all sample formats except 16 bit signed, little endian */
112 ret = get_btr_val("sample_format", btrn);
113 if (ret >= 0 && ret != SF_S16_LE) {
114 const char * const sample_formats[] = {SAMPLE_FORMATS};
115 PARA_ERROR_LOG("unsupported sample format: %s\n",
116 sample_formats[ret]);
117 return -ERRNO_TO_PARA_ERROR(EINVAL);
119 ctx->ratio = U32_OPTVAL(DEST_SAMPLE_RATE, lpr)
120 / (float)ctx->source_sample_rate;
124 static int resample_init(struct filter_node *fn)
127 const uint32_t trafo[] = {
128 [RCT_BEST] = SRC_SINC_BEST_QUALITY,
129 [RCT_MEDIUM] = SRC_SINC_MEDIUM_QUALITY,
130 [RCT_FASTEST] = SRC_SINC_FASTEST,
131 [RCT_ZERO_ORDER_HOLD] = SRC_ZERO_ORDER_HOLD,
132 [RCT_LINEAR] = SRC_LINEAR
134 struct resample_context *ctx = fn->private_data;
135 const struct lls_option *o_c = FILTER_CMD_OPT(RESAMPLE, CONVERTER);
136 uint32_t converter = U32_OPTVAL(CONVERTER, fn->lpr);
138 PARA_INFO_LOG("converter type: %s\n",
139 lls_enum_string_val(converter, o_c));
140 ret = resample_set_params(fn);
143 ctx->src_state = src_new(trafo[converter],
144 U32_OPTVAL(CHANNELS, fn->lpr), &ret);
145 if (!ctx->src_state) {
146 PARA_ERROR_LOG("%s\n", src_strerror(ret));
147 return -E_LIBSAMPLERATE;
149 fn->min_iqs = 2 * ctx->channels;
153 /* returns number of input frames used */
154 static int resample_frames(int16_t *in, size_t num_frames, bool have_more,
155 struct resample_context *ctx, int16_t **result,
156 size_t *result_frames)
158 int ret, num_samples, out_samples;
163 data.src_ratio = ctx->ratio;
164 data.end_of_input = !have_more;
166 data.input_frames = num_frames;
167 num_samples = num_frames * ctx->channels;
168 data.output_frames = num_frames * ctx->ratio + 1;
169 out_samples = data.output_frames * ctx->channels;
171 in_float = arr_alloc(num_samples, sizeof(float));
172 src_short_to_float_array(in, in_float, num_samples);
173 data.data_in = in_float;
174 data.data_out = arr_alloc(out_samples, sizeof(float));
175 ret = src_process(ctx->src_state, &data);
178 PARA_ERROR_LOG("%s\n", src_strerror(ret));
180 return -E_LIBSAMPLERATE;
182 out_samples = data.output_frames_gen * ctx->channels;
183 out = arr_alloc(out_samples, sizeof(short));
184 src_float_to_short_array(data.data_out, out, out_samples);
187 *result_frames = data.output_frames_gen;
188 return data.input_frames_used;
191 static int resample_post_monitor(__a_unused struct sched *s, void *context)
194 struct filter_node *fn = context;
195 struct resample_context *ctx = fn->private_data;
196 struct btr_node *btrn = fn->btrn;
198 size_t in_bytes, num_frames;
201 ret = check_wav_post_monitor(ctx->cwc);
204 ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
207 if (!ctx->src_state) {
208 ret = resample_init(fn);
212 if (ctx->source_sample_rate == U32_OPTVAL(DEST_SAMPLE_RATE, fn->lpr)) {
214 * No resampling necessary. We do not splice ourselves out
215 * though, since our children might want to ask us through the
216 * btr exec mechanism for the destination samplerate and the
222 btr_merge(btrn, fn->min_iqs);
223 in_bytes = btr_next_buffer(btrn, (char **)&in);
225 num_frames = in_bytes / 2 / ctx->channels;
228 have_more = !btr_no_parent(btrn) ||
229 btr_next_buffer_omit(btrn, in_bytes, NULL) > 0;
230 ret = resample_frames(in, num_frames, have_more, ctx, &out, &num_frames);
233 btr_consume(btrn, ret * 2 * ctx->channels);
234 btr_add_output((char *)out, num_frames * 2 * ctx->channels, btrn);
238 btr_remove_node(&fn->btrn);
239 /* This releases the check_wav btr node */
240 check_wav_post_monitor(ctx->cwc);
245 static void *resample_setup(const struct lls_parse_result *lpr)
251 u32 = U32_OPTVAL(CHANNELS, lpr);
252 given = OPT_GIVEN(CHANNELS, lpr);
253 if (u32 == 0 && given) {
254 PARA_EMERG_LOG("fatal: zero channels?!\n");
257 u32 = U32_OPTVAL(SAMPLE_RATE, lpr);
258 given = OPT_GIVEN(SAMPLE_RATE, lpr);
259 if (u32 == 0 && given) {
260 PARA_EMERG_LOG("fatal: input sample rate can not be 0\n");
263 u32 = U32_OPTVAL(DEST_SAMPLE_RATE, lpr);
264 given = OPT_GIVEN(DEST_SAMPLE_RATE, lpr);
265 if (u32 == 0 && given) {
266 PARA_EMERG_LOG("fatal: destination sample rate can not be 0\n");
272 static void resample_teardown(__a_unused const struct lls_parse_result *lpr,
278 const struct filter lsg_filter_cmd_com_resample_user_data = {
279 .setup = resample_setup,
280 .open = resample_open,
281 .pre_monitor = resample_pre_monitor,
282 .post_monitor = resample_post_monitor,
283 .close = resample_close,
284 .teardown = resample_teardown,
285 .execute = resample_execute