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(struct btr_node
*btrn
, const char *cmd
, char **result
)
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
);
39 static void resample_close(struct filter_node
*fn
)
41 struct resample_context
*ctx
= fn
->private_data
;
45 check_wav_shutdown(ctx
->cwc
);
47 src_delete(ctx
->src_state
);
49 fn
->private_data
= NULL
;
52 static void resample_open(struct filter_node
*fn
)
54 struct resample_context
*ctx
= para_calloc(sizeof(*ctx
));
55 struct btr_node
*btrn
= fn
->btrn
;
58 fn
->private_data
= ctx
;
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
);
65 static void resample_pre_select(struct sched
*s
, void *context
)
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
);
72 return sched_min_delay(s
);
73 check_wav_pre_select(s
, ctx
->cwc
);
76 static int get_btr_val(const char *what
, struct btr_node
*btrn
)
80 int ret
= btr_exec_up(btr_parent(btrn
), what
, &buf
);
83 PARA_NOTICE_LOG("btr exec for \"%s\" failed\n", what
);
86 ret
= para_atoi32(buf
, &val
);
88 return ret
< 0? ret
: val
;
91 static int resample_set_params(struct filter_node
*fn
)
94 struct resample_context
*ctx
= fn
->private_data
;
95 struct btr_node
*btrn
= fn
->btrn
;
96 struct lls_parse_result
*lpr
= fn
->lpr
;
98 ctx
->channels
= U32_OPTVAL(CHANNELS
, lpr
);
99 if (!OPT_GIVEN(CHANNELS
, lpr
)) {
100 ret
= get_btr_val("channels", btrn
);
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
);
108 ctx
->source_sample_rate
= ret
;
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
);
118 ctx
->ratio
= U32_OPTVAL(DEST_SAMPLE_RATE
, lpr
)
119 / (float)ctx
->source_sample_rate
;
123 static int resample_init(struct filter_node
*fn
)
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
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
);
137 PARA_INFO_LOG("converter type: %s\n",
138 lls_enum_string_val(converter
, o_c
));
139 ret
= resample_set_params(fn
);
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
;
148 fn
->min_iqs
= 2 * ctx
->channels
;
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
)
157 int ret
, num_samples
, out_samples
;
162 data
.src_ratio
= ctx
->ratio
;
163 data
.end_of_input
= !have_more
;
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
;
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
);
177 PARA_ERROR_LOG("%s\n", src_strerror(ret
));
179 return -E_LIBSAMPLERATE
;
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
);
186 *result_frames
= data
.output_frames_gen
;
187 return data
.input_frames_used
;
190 static int resample_post_select(__a_unused
struct sched
*s
, void *context
)
193 struct filter_node
*fn
= context
;
194 struct resample_context
*ctx
= fn
->private_data
;
195 struct btr_node
*btrn
= fn
->btrn
;
197 size_t in_bytes
, num_frames
;
200 ret
= check_wav_post_select(ctx
->cwc
);
203 ret
= btr_node_status(btrn
, fn
->min_iqs
, BTR_NT_INTERNAL
);
206 if (!ctx
->src_state
) {
207 ret
= resample_init(fn
);
211 if (ctx
->source_sample_rate
== U32_OPTVAL(DEST_SAMPLE_RATE
, fn
->lpr
)) {
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
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
;
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
);
232 btr_consume(btrn
, ret
* 2 * ctx
->channels
);
233 btr_add_output((char *)out
, num_frames
* 2 * ctx
->channels
, btrn
);
237 btr_remove_node(&fn
->btrn
);
238 /* This releases the check_wav btr node */
239 check_wav_post_select(ctx
->cwc
);
244 static void *resample_setup(const struct lls_parse_result
*lpr
)
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");
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");
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");
271 static void resample_teardown(__a_unused
const struct lls_parse_result
*lpr
,
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