+ struct resample_context *ctx = para_calloc(sizeof(*ctx));
+ struct btr_node *btrn = fn->btrn;
+ struct wav_params wp;
+
+ fn->private_data = ctx;
+ fn->min_iqs = 2;
+ LLS_COPY_WAV_PARMS(&wp, LSG_FILTER_CMD_RESAMPLE, fn->lpr);
+ ctx->cwc = check_wav_init(btr_parent(btrn), btrn, &wp, NULL);
+ btr_log_tree(btr_parent(btr_parent(btrn)), LL_INFO);
+}
+
+static void resample_pre_select(struct sched *s, void *context)
+{
+ struct filter_node *fn = context;
+ struct resample_context *ctx = fn->private_data;
+ int ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL);
+
+ if (ret != 0)
+ return sched_min_delay(s);
+ check_wav_pre_select(s, ctx->cwc);
+}
+
+static int get_btr_val(const char *what, struct btr_node *btrn)
+{
+ char *buf;
+ int32_t val;
+ int ret = btr_exec_up(btr_parent(btrn), what, &buf);
+
+ if (ret < 0) {
+ PARA_NOTICE_LOG("btr exec for \"%s\" failed\n", what);
+ return ret;
+ }
+ ret = para_atoi32(buf, &val);
+ free(buf);
+ return ret < 0? ret : val;
+}
+
+static int resample_set_params(struct filter_node *fn)
+{
+ int ret;
+ struct resample_context *ctx = fn->private_data;
+ struct btr_node *btrn = fn->btrn;
+ struct lls_parse_result *lpr = fn->lpr;
+
+ ctx->channels = U32_OPTVAL(CHANNELS, lpr);
+ if (!OPT_GIVEN(CHANNELS, lpr)) {
+ ret = get_btr_val("channels", btrn);
+ if (ret >= 0)
+ ctx->channels = ret;
+ }
+ ctx->source_sample_rate = U32_OPTVAL(SAMPLE_RATE, lpr);
+ if (!OPT_GIVEN(SAMPLE_RATE, lpr)) {
+ ret = get_btr_val("sample_rate", btrn);
+ if (ret >= 0)
+ ctx->source_sample_rate = ret;
+ }
+ /* reject all sample formats except 16 bit signed, little endian */
+ ret = get_btr_val("sample_format", btrn);
+ if (ret >= 0 && ret != SF_S16_LE) {
+ const char * const sample_formats[] = {SAMPLE_FORMATS};
+ PARA_ERROR_LOG("unsupported sample format: %s\n",
+ sample_formats[ret]);
+ return -ERRNO_TO_PARA_ERROR(EINVAL);
+ }
+ ctx->ratio = U32_OPTVAL(DEST_SAMPLE_RATE, lpr)
+ / (float)ctx->source_sample_rate;
+ return 1;