// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_drc_t* s = (af_drc_t*)af->setup; switch(cmd){ case AF_CONTROL_REINIT: // Sanity check if(!arg) return AF_ERROR; mp_audio_copy_config(af->data, (struct mp_audio*)arg); if(((struct mp_audio*)arg)->format != (AF_FORMAT_S16_NE)){ mp_audio_set_format(af->data, AF_FORMAT_FLOAT_NE); } return af_test_output(af,(struct mp_audio*)arg); case AF_CONTROL_COMMAND_LINE:{ int i = 0; float target = DEFAULT_TARGET; sscanf((char*)arg,"%d:%f", &i, &target); if (i != 1 && i != 2) return AF_ERROR; s->method = i-1; s->mid_s16 = ((float)SHRT_MAX) * target; s->mid_float = target; return AF_OK; } } return AF_UNKNOWN; }
static int control(struct af_instance *af, int cmd, void *arg) { struct priv *priv = af->priv; switch (cmd) { case AF_CONTROL_REINIT: { struct mp_audio *in = arg; struct mp_audio orig_in = *in; struct mp_audio *out = af->data; force_in_params(af, in); mp_audio_copy_config(out, in); force_out_params(af, out); if (in->nch != out->nch || in->bps != out->bps) { MP_ERR(af, "Forced input/output formats are incompatible.\n"); return AF_ERROR; } if (priv->fail) { MP_ERR(af, "Failing on purpose.\n"); return AF_ERROR; } return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { switch(cmd){ case AF_CONTROL_REINIT:{ // Sanity check if(!arg) return AF_ERROR; mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_num_channels(af->data, 1); #if 0 if (((struct mp_audio*)arg)->format == AF_FORMAT_FLOAT) { af->data->format = AF_FORMAT_FLOAT; af->data->bps = 4; af->play = play_float; }// else #endif { mp_audio_set_format(af->data, AF_FORMAT_S16); af->filter = play_s16; } return af_test_output(af,(struct mp_audio*)arg); } } return AF_UNKNOWN; }
static int control(struct af_instance *af, int cmd, void *arg) { struct priv *s = af->priv; switch (cmd) { case AF_CONTROL_REINIT: { struct mp_audio *in = arg; mp_audio_copy_config(af->data, in); mp_audio_force_interleaved_format(af->data); if (s->fast && af_fmt_from_planar(in->format) != AF_FORMAT_FLOAT) { mp_audio_set_format(af->data, AF_FORMAT_S16); } else { mp_audio_set_format(af->data, AF_FORMAT_FLOAT); } if (af_fmt_is_planar(in->format)) mp_audio_set_format(af->data, af_fmt_to_planar(af->data->format)); return af_test_output(af, in); } case AF_CONTROL_SET_VOLUME: s->level = *(float *)arg; return AF_OK; case AF_CONTROL_GET_VOLUME: *(float *)arg = s->level; return AF_OK; } return AF_UNKNOWN; }
static int filter(struct af_instance *af, struct mp_audio *data) { if (data) mp_audio_copy_config(data, af->data); af_add_output_frame(af, data); return 0; }
static int control(struct af_instance *af, int cmd, void *arg) { struct priv *p = af->priv; switch (cmd) { case AF_CONTROL_REINIT: { struct mp_audio *in = arg; struct mp_audio orig_in = *in; struct mp_audio *out = af->data; in->format = AF_FORMAT_FLOATP; mp_audio_copy_config(out, in); if (p->rubber) rubberband_delete(p->rubber); int opts = p->opt_transients | p->opt_detector | p->opt_phase | p->opt_window | p->opt_smoothing | p->opt_formant | p->opt_pitch | p-> opt_channels | RubberBandOptionProcessRealTime; p->rubber = rubberband_new(in->rate, in->channels.num, opts, 1.0, 1.0); if (!p->rubber) { MP_FATAL(af, "librubberband initialization failed.\n"); return AF_ERROR; } update_speed(af, p->speed); update_pitch(af, p->pitch); control(af, AF_CONTROL_RESET, NULL); return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE; } case AF_CONTROL_SET_PLAYBACK_SPEED: { update_speed(af, *(double *)arg); return AF_OK; } case AF_CONTROL_RESET: if (p->rubber) rubberband_reset(p->rubber); talloc_free(p->pending); p->pending = NULL; p->rubber_delay = 0; return AF_OK; case AF_CONTROL_COMMAND: { char **args = arg; if (!strcmp(args[0], "set-pitch")) { char *endptr; double pitch = strtod(args[1], &endptr); if (*endptr || pitch < 0.01 || pitch > 100.0) return CONTROL_ERROR; update_pitch(af, pitch); return CONTROL_OK; } else { return CONTROL_ERROR; } } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_extrastereo_t* s = (af_extrastereo_t*)af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ // Sanity check if(!arg) return AF_ERROR; mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_num_channels(af->data, 2); if (af->data->format == AF_FORMAT_FLOAT_NE) { af->play = play_float; }// else { mp_audio_set_format(af->data, AF_FORMAT_S16_NE); af->play = play_s16; } return af_test_output(af,(struct mp_audio*)arg); } case AF_CONTROL_COMMAND_LINE:{ float f; sscanf((char*)arg,"%f", &f); s->mul = f; return AF_OK; } } return AF_UNKNOWN; }
static int filter_out(struct af_instance *af) { struct priv *p = af->priv; while (rubberband_available(p->rubber) <= 0) { const float *dummy[MP_NUM_CHANNELS] = {0}; const float **in_data = dummy; size_t in_samples = 0; if (p->pending) { if (!p->pending->samples) break; // recover from previous EOF if (p->needs_reset) { rubberband_reset(p->rubber); p->rubber_delay = 0; } p->needs_reset = false; size_t needs = rubberband_get_samples_required(p->rubber); in_data = (void *)&p->pending->planes; in_samples = MPMIN(p->pending->samples, needs); } if (p->needs_reset) break; // previous EOF p->needs_reset = !p->pending; // EOF rubberband_process(p->rubber, in_data, in_samples, p->needs_reset); p->rubber_delay += in_samples; if (!p->pending) break; mp_audio_skip_samples(p->pending, in_samples); } int out_samples = rubberband_available(p->rubber); if (out_samples > 0) { struct mp_audio *out = mp_audio_pool_get(af->out_pool, af->data, out_samples); if (!out) return -1; if (p->pending) mp_audio_copy_config(out, p->pending); float **out_data = (void *)&out->planes; out->samples = rubberband_retrieve(p->rubber, out_data, out->samples); p->rubber_delay -= out->samples * p->speed; af_add_output_frame(af, out); } int delay_samples = p->rubber_delay; if (p->pending) delay_samples += p->pending->samples; af->delay = delay_samples / (af->data->rate * p->speed); return 0; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_surround_t *s = af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ float fc; mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_channels_old(af->data, ((struct mp_audio*)arg)->nch*2); mp_audio_set_format(af->data, AF_FORMAT_FLOAT_NE); if (af->data->nch != 4){ mp_msg(MSGT_AFILTER, MSGL_ERR, "[surround] Only stereo input is supported.\n"); return AF_DETACH; } // Surround filer coefficients fc = 2.0 * 7000.0/(float)af->data->rate; if (-1 == af_filter_design_fir(L, s->w, &fc, LP|HAMMING, 0)){ mp_msg(MSGT_AFILTER, MSGL_ERR, "[surround] Unable to design low-pass filter.\n"); return AF_ERROR; } // Free previous delay queues free(s->dl); free(s->dr); // Allocate new delay queues s->dl = calloc(LD,af->data->bps); s->dr = calloc(LD,af->data->bps); if((NULL == s->dl) || (NULL == s->dr)) mp_msg(MSGT_AFILTER, MSGL_FATAL, "[delay] Out of memory\n"); // Initialize delay queue index if(AF_OK != af_from_ms(1, &s->d, &s->wi, af->data->rate, 0.0, 1000.0)) return AF_ERROR; // printf("%i\n",s->wi); s->ri = 0; if((af->data->format != ((struct mp_audio*)arg)->format) || (af->data->bps != ((struct mp_audio*)arg)->bps)){ mp_audio_set_format((struct mp_audio*)arg, af->data->format); return AF_FALSE; } return AF_OK; } case AF_CONTROL_COMMAND_LINE:{ float d = 0; sscanf((char*)arg,"%f",&d); if ((d < 0) || (d > 1000)){ mp_msg(MSGT_AFILTER, MSGL_ERR, "[surround] Invalid delay time, valid time values" " are 0ms to 1000ms current value is %0.3f ms\n",d); return AF_ERROR; } s->d = d; return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_equalizer_t* s = (af_equalizer_t*)af->priv; switch(cmd){ case AF_CONTROL_REINIT:{ int k =0, i =0; float F[KM] = CF; s->gain_factor=0.0; // Sanity check if(!arg) return AF_ERROR; mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_format(af->data, AF_FORMAT_FLOAT); // Calculate number of active filters s->K=KM; while(F[s->K-1] > (float)af->data->rate/2.2) s->K--; if(s->K != KM) MP_INFO(af, "Limiting the number of filters to" " %i due to low sample rate.\n",s->K); // Generate filter taps for(k=0;k<s->K;k++) bp2(s->a[k],s->b[k],F[k]/((float)af->data->rate),Q); // Calculate how much this plugin adds to the overall time delay af->delay = 2.0 / (double)af->data->rate; // Calculate gain factor to prevent clipping at output for(k=0;k<AF_NCH;k++) { for(i=0;i<KM;i++) { if(s->gain_factor < s->g[k][i]) s->gain_factor=s->g[k][i]; } } s->gain_factor=log10(s->gain_factor + 1.0) * 20.0; if(s->gain_factor > 0.0) { s->gain_factor=0.1+(s->gain_factor/12.0); }else{ s->gain_factor=1; } return af_test_output(af,arg); } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { switch(cmd){ case AF_CONTROL_REINIT: mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_format(af->data, AF_FORMAT_FLOAT_NE); return af_test_output(af,(struct mp_audio*)arg); } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_delay_t* s = af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ int i; // Free prevous delay queues for(i=0;i<af->data->nch;i++) free(s->q[i]); mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_force_interleaved_format(af->data); // Allocate new delay queues for(i=0;i<af->data->nch;i++){ s->q[i] = calloc(L,af->data->bps); if(NULL == s->q[i]) mp_msg(MSGT_AFILTER, MSGL_FATAL, "[delay] Out of memory\n"); } if(AF_OK != af_from_ms(AF_NCH, s->d, s->wi, af->data->rate, 0.0, 1000.0)) return AF_ERROR; s->ri = 0; for(i=0;i<AF_NCH;i++){ mp_msg(MSGT_AFILTER, MSGL_DBG2, "[delay] Channel %i delayed by %0.3fms\n", i,MPCLAMP(s->d[i],0.0,1000.0)); mp_msg(MSGT_AFILTER, MSGL_DBG3, "[delay] Channel %i delayed by %i samples\n", i,s->wi[i]); } return AF_OK; } case AF_CONTROL_COMMAND_LINE:{ int n = 1; int i = 0; char* cl = arg; while(n && i < AF_NCH ){ sscanf(cl,"%f:%n",&s->d[i],&n); if(n==0 || cl[n-1] == '\0') break; cl=&cl[n]; i++; } return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { switch(cmd){ case AF_CONTROL_REINIT: // Sanity check if(!arg) return AF_ERROR; mp_audio_force_interleaved_format((struct mp_audio*)arg); mp_audio_copy_config(af->data, (struct mp_audio*)arg); if(((struct mp_audio*)arg)->format != (AF_FORMAT_S16)){ mp_audio_set_format(af->data, AF_FORMAT_FLOAT); } return af_test_output(af,(struct mp_audio*)arg); } return AF_UNKNOWN; }
static int filter_out(struct af_instance *af) { struct priv *p = af->priv; if (!p->graph) goto error; AVFrame *frame = av_frame_alloc(); if (!frame) goto error; int err = av_buffersink_get_frame(p->out, frame); if (err == AVERROR(EAGAIN) || err == AVERROR_EOF) { // Not an error situation - no more output buffers in queue. // AVERROR_EOF means we shouldn't even give the filter more // input, but we don't handle that completely correctly. av_frame_free(&frame); p->eof |= err == AVERROR_EOF; return 0; } struct mp_audio *out = mp_audio_from_avframe(frame); if (!out) goto error; mp_audio_copy_config(out, af->data); if (frame->pts != AV_NOPTS_VALUE) { double in_time = p->samples_in / (double)af->fmt_in.rate; double out_time = frame->pts * av_q2d(p->timebase_out); // Need pts past the last output sample. out_time += out->samples / (double)out->rate; af->delay = in_time - out_time; } get_metadata_from_av_frame(af, frame); af_add_output_frame(af, out); av_frame_free(&frame); return 0; error: av_frame_free(&frame); return -1; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_surround_t *s = af->priv; switch(cmd){ case AF_CONTROL_REINIT:{ struct mp_audio *in = arg; float fc; if (!mp_chmap_is_stereo(&in->channels)) { MP_ERR(af, "Only stereo input is supported.\n"); return AF_DETACH; } mp_audio_set_format(in, AF_FORMAT_FLOAT); mp_audio_copy_config(af->data, in); mp_audio_set_channels_old(af->data, in->nch * 2); // Surround filer coefficients fc = 2.0 * 7000.0/(float)af->data->rate; if (-1 == af_filter_design_fir(L, s->w, &fc, LP|HAMMING, 0)){ MP_ERR(af, "Unable to design low-pass filter.\n"); return AF_ERROR; } // Free previous delay queues free(s->dl); free(s->dr); // Allocate new delay queues s->dl = calloc(LD,af->data->bps); s->dr = calloc(LD,af->data->bps); if((NULL == s->dl) || (NULL == s->dr)) MP_FATAL(af, "Out of memory\n"); // Initialize delay queue index if(AF_OK != af_from_ms(1, &s->d, &s->wi, af->data->rate, 0.0, 1000.0)) return AF_ERROR; // printf("%i\n",s->wi); s->ri = 0; return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_delay_t* s = af->priv; switch(cmd){ case AF_CONTROL_REINIT:{ int i; struct mp_audio *in = arg; if (in->bps != 1 && in->bps != 2 && in->bps != 4) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[delay] Sample format not supported\n"); return AF_ERROR; } // Free prevous delay queues for(i=0;i<af->data->nch;i++) free(s->q[i]); mp_audio_force_interleaved_format(in); mp_audio_copy_config(af->data, in); // Allocate new delay queues for(i=0;i<af->data->nch;i++){ s->q[i] = calloc(L,af->data->bps); if(NULL == s->q[i]) mp_msg(MSGT_AFILTER, MSGL_FATAL, "[delay] Out of memory\n"); } if(AF_OK != af_from_ms(AF_NCH, s->d, s->wi, af->data->rate, 0.0, 1000.0)) return AF_ERROR; s->ri = 0; for(i=0;i<AF_NCH;i++){ mp_msg(MSGT_AFILTER, MSGL_DBG2, "[delay] Channel %i delayed by %0.3fms\n", i,MPCLAMP(s->d[i],0.0,1000.0)); mp_msg(MSGT_AFILTER, MSGL_DBG3, "[delay] Channel %i delayed by %i samples\n", i,s->wi[i]); } return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_sinesuppress_t* s = (af_sinesuppress_t*)af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ // Sanity check if(!arg) return AF_ERROR; mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_num_channels(af->data, 1); #if 0 if (((struct mp_audio*)arg)->format == AF_FORMAT_FLOAT_NE) { af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; af->play = play_float; }// else #endif { mp_audio_set_format(af->data, AF_FORMAT_S16_NE); af->play = play_s16; } return af_test_output(af,(struct mp_audio*)arg); } case AF_CONTROL_COMMAND_LINE:{ float f1,f2; sscanf((char*)arg,"%f:%f", &f1,&f2); s->freq = f1; s->decay = f2; return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_scaletempo_t* s = af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ struct mp_audio* data = (struct mp_audio*)arg; float srate = data->rate / 1000; int nch = data->nch; int bps; int use_int = 0; int frames_stride, frames_overlap; int i, j; mp_msg(MSGT_AFILTER, MSGL_V, "[scaletempo] %.3f speed * %.3f scale_nominal = %.3f\n", s->speed, s->scale_nominal, s->scale); mp_audio_copy_config(af->data, data); if (s->scale == 1.0) { if (s->speed_tempo && s->speed_pitch) return AF_DETACH; af->delay = 0; af->mul = 1; return af_test_output(af, data); } if (data->format == AF_FORMAT_S16_NE) { use_int = 1; } else { mp_audio_set_format(af->data, AF_FORMAT_FLOAT_NE); } bps = af->data->bps; frames_stride = srate * s->ms_stride; s->bytes_stride = frames_stride * bps * nch; s->bytes_stride_scaled = s->scale * s->bytes_stride; s->frames_stride_scaled = s->scale * frames_stride; s->frames_stride_error = 0; af->mul = (double)s->bytes_stride / s->bytes_stride_scaled; af->delay = 0; frames_overlap = frames_stride * s->percent_overlap; if (frames_overlap <= 0) { s->bytes_standing = s->bytes_stride; s->samples_standing = s->bytes_standing / bps; s->output_overlap = NULL; s->bytes_overlap = 0; } else { s->samples_overlap = frames_overlap * nch; s->bytes_overlap = frames_overlap * nch * bps; s->bytes_standing = s->bytes_stride - s->bytes_overlap; s->samples_standing = s->bytes_standing / bps; s->buf_overlap = realloc(s->buf_overlap, s->bytes_overlap); s->table_blend = realloc(s->table_blend, s->bytes_overlap * 4); if(!s->buf_overlap || !s->table_blend) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[scaletempo] Out of memory\n"); return AF_ERROR; } memset(s->buf_overlap, 0, s->bytes_overlap); if (use_int) { int32_t* pb = s->table_blend; int64_t blend = 0; for (i=0; i<frames_overlap; i++) { int32_t v = blend / frames_overlap; for (j=0; j<nch; j++) { *pb++ = v; } blend += 65536; // 2^16 } s->output_overlap = output_overlap_s16; } else { float* pb = s->table_blend; for (i=0; i<frames_overlap; i++) { float v = i / (float)frames_overlap; for (j=0; j<nch; j++) { *pb++ = v; } } s->output_overlap = output_overlap_float; } } s->frames_search = (frames_overlap > 1) ? srate * s->ms_search : 0; if (s->frames_search <= 0) { s->best_overlap_offset = NULL; } else { if (use_int) { int64_t t = frames_overlap; int32_t n = 8589934588LL / (t * t); // 4 * (2^31 - 1) / t^2 int32_t* pw; s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap * 2 + UNROLL_PADDING); s->table_window = realloc(s->table_window, s->bytes_overlap * 2 - nch * bps * 2); if(!s->buf_pre_corr || !s->table_window) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[scaletempo] Out of memory\n"); return AF_ERROR; } memset((char *)s->buf_pre_corr + s->bytes_overlap * 2, 0, UNROLL_PADDING); pw = s->table_window; for (i=1; i<frames_overlap; i++) { int32_t v = ( i * (t - i) * n ) >> 15; for (j=0; j<nch; j++) { *pw++ = v; } } s->best_overlap_offset = best_overlap_offset_s16; } else { float* pw; s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap); s->table_window = realloc(s->table_window, s->bytes_overlap - nch * bps); if(!s->buf_pre_corr || !s->table_window) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[scaletempo] Out of memory\n"); return AF_ERROR; } pw = s->table_window; for (i=1; i<frames_overlap; i++) { float v = i * (frames_overlap - i); for (j=0; j<nch; j++) { *pw++ = v; } } s->best_overlap_offset = best_overlap_offset_float; } } s->bytes_per_frame = bps * nch; s->num_channels = nch; s->bytes_queue = (s->frames_search + frames_stride + frames_overlap) * bps * nch; s->buf_queue = realloc(s->buf_queue, s->bytes_queue + UNROLL_PADDING); if(!s->buf_queue) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[scaletempo] Out of memory\n"); return AF_ERROR; } s->bytes_queued = 0; s->bytes_to_slide = 0; mp_msg (MSGT_AFILTER, MSGL_DBG2, "[scaletempo] " "%.2f stride_in, %i stride_out, %i standing, " "%i overlap, %i search, %i queue, %s mode\n", s->frames_stride_scaled, (int)(s->bytes_stride / nch / bps), (int)(s->bytes_standing / nch / bps), (int)(s->bytes_overlap / nch / bps), s->frames_search, (int)(s->bytes_queue / nch / bps), (use_int?"s16":"float")); return af_test_output(af, (struct mp_audio*)arg); } case AF_CONTROL_PLAYBACK_SPEED | AF_CONTROL_SET:{ if (s->speed_tempo) { if (s->speed_pitch) { break; } s->speed = *(float*)arg; s->scale = s->speed * s->scale_nominal; } else { if (s->speed_pitch) { s->speed = 1 / *(float*)arg; s->scale = s->speed * s->scale_nominal; break; } } return AF_OK; } case AF_CONTROL_SCALETEMPO_AMOUNT | AF_CONTROL_SET:{ s->scale = *(float*)arg; s->scale = s->speed * s->scale_nominal; return AF_OK; } case AF_CONTROL_SCALETEMPO_AMOUNT | AF_CONTROL_GET: *(float*)arg = s->scale; return AF_OK; case AF_CONTROL_COMMAND_LINE:{ strarg_t speed = {}; opt_t subopts[] = { {"scale", OPT_ARG_FLOAT, &s->scale_nominal, NULL}, {"stride", OPT_ARG_FLOAT, &s->ms_stride, NULL}, {"overlap", OPT_ARG_FLOAT, &s->percent_overlap, NULL}, {"search", OPT_ARG_FLOAT, &s->ms_search, NULL}, {"speed", OPT_ARG_STR, &speed, NULL}, {NULL}, }; if (subopt_parse(arg, subopts) != 0) { return AF_ERROR; } if (s->scale_nominal <= 0) { mp_msg(MSGT_AFILTER, MSGL_ERR, "[scaletempo] %s: %s: scale > 0\n", mp_gtext("error parsing command line"), mp_gtext("value out of range")); return AF_ERROR; } if (s->ms_stride <= 0) { mp_msg(MSGT_AFILTER, MSGL_ERR, "[scaletempo] %s: %s: stride > 0\n", mp_gtext("error parsing command line"), mp_gtext("value out of range")); return AF_ERROR; } if (s->percent_overlap < 0 || s->percent_overlap > 1) { mp_msg(MSGT_AFILTER, MSGL_ERR, "[scaletempo] %s: %s: 0 <= overlap <= 1\n", mp_gtext("error parsing command line"), mp_gtext("value out of range")); return AF_ERROR; } if (s->ms_search < 0) { mp_msg(MSGT_AFILTER, MSGL_ERR, "[scaletempo] %s: %s: search >= 0\n", mp_gtext("error parsing command line"), mp_gtext("value out of range")); return AF_ERROR; } if (speed.len > 0) { if (strcmp(speed.str, "pitch") == 0) { s->speed_tempo = 0; s->speed_pitch = 1; } else if (strcmp(speed.str, "tempo") == 0) { s->speed_tempo = 1; s->speed_pitch = 0; } else if (strcmp(speed.str, "none") == 0) { s->speed_tempo = 0; s->speed_pitch = 0; } else if (strcmp(speed.str, "both") == 0) { s->speed_tempo = 1; s->speed_pitch = 1; } else { mp_msg(MSGT_AFILTER, MSGL_ERR, "[scaletempo] %s: %s: speed=[pitch|tempo|none|both]\n", mp_gtext("error parsing command line"), mp_gtext("value out of range")); return AF_ERROR; } } s->scale = s->speed * s->scale_nominal; mp_msg(MSGT_AFILTER, MSGL_DBG2, "[scaletempo] %6.3f scale, %6.2f stride, %6.2f overlap, %6.2f search, speed = %s\n", s->scale_nominal, s->ms_stride, s->percent_overlap, s->ms_search, (s->speed_tempo?(s->speed_pitch?"tempo and speed":"tempo"):(s->speed_pitch?"pitch":"none"))); return AF_OK; } }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_equalizer_t* s = (af_equalizer_t*)af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ int k =0, i =0; float F[KM] = CF; s->gain_factor=0.0; // Sanity check if(!arg) return AF_ERROR; mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_format(af->data, AF_FORMAT_FLOAT_NE); // Calculate number of active filters s->K=KM; while(F[s->K-1] > (float)af->data->rate/2.2) s->K--; if(s->K != KM) mp_msg(MSGT_AFILTER, MSGL_INFO, "[equalizer] Limiting the number of filters to" " %i due to low sample rate.\n",s->K); // Generate filter taps for(k=0;k<s->K;k++) bp2(s->a[k],s->b[k],F[k]/((float)af->data->rate),Q); // Calculate how much this plugin adds to the overall time delay af->delay = 2 * af->data->nch * af->data->bps; // Calculate gain factor to prevent clipping at output for(k=0;k<AF_NCH;k++) { for(i=0;i<KM;i++) { if(s->gain_factor < s->g[k][i]) s->gain_factor=s->g[k][i]; } } s->gain_factor=log10(s->gain_factor + 1.0) * 20.0; if(s->gain_factor > 0.0) { s->gain_factor=0.1+(s->gain_factor/12.0); }else{ s->gain_factor=1; } return af_test_output(af,arg); } case AF_CONTROL_COMMAND_LINE:{ float g[10]={0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}; int i,j; sscanf((char*)arg,"%f:%f:%f:%f:%f:%f:%f:%f:%f:%f", &g[0], &g[1], &g[2], &g[3], &g[4], &g[5], &g[6], &g[7], &g[8] ,&g[9]); for(i=0;i<AF_NCH;i++){ for(j=0;j<KM;j++){ ((af_equalizer_t*)af->setup)->g[i][j] = pow(10.0,clamp(g[j],G_MIN,G_MAX)/20.0)-1.0; } } return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance *af, int cmd, void *arg) { af_scaletempo_t *s = af->priv; switch (cmd) { case AF_CONTROL_REINIT: { struct mp_audio *data = (struct mp_audio *)arg; float srate = data->rate / 1000; int nch = data->nch; int use_int = 0; mp_msg(MSGT_AFILTER, MSGL_V, "[scaletempo] %.3f speed * %.3f scale_nominal = %.3f\n", s->speed, s->scale_nominal, s->scale); mp_audio_force_interleaved_format(data); mp_audio_copy_config(af->data, data); if (s->scale == 1.0) { if (s->speed_tempo && s->speed_pitch) return AF_DETACH; af->delay = 0; af->mul = 1; return af_test_output(af, data); } if (data->format == AF_FORMAT_S16) { use_int = 1; } else { mp_audio_set_format(af->data, AF_FORMAT_FLOAT); } int bps = af->data->bps; s->frames_stride = srate * s->ms_stride; s->bytes_stride = s->frames_stride * bps * nch; s->frames_stride_scaled = s->scale * s->frames_stride; s->frames_stride_error = 0; af->mul = 1.0 / s->scale; af->delay = 0; int frames_overlap = s->frames_stride * s->percent_overlap; if (frames_overlap <= 0) { s->bytes_standing = s->bytes_stride; s->samples_standing = s->bytes_standing / bps; s->output_overlap = NULL; s->bytes_overlap = 0; } else { s->samples_overlap = frames_overlap * nch; s->bytes_overlap = frames_overlap * nch * bps; s->bytes_standing = s->bytes_stride - s->bytes_overlap; s->samples_standing = s->bytes_standing / bps; s->buf_overlap = realloc(s->buf_overlap, s->bytes_overlap); s->table_blend = realloc(s->table_blend, s->bytes_overlap * 4); if (!s->buf_overlap || !s->table_blend) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[scaletempo] Out of memory\n"); return AF_ERROR; } memset(s->buf_overlap, 0, s->bytes_overlap); if (use_int) { int32_t *pb = s->table_blend; int64_t blend = 0; for (int i = 0; i < frames_overlap; i++) { int32_t v = blend / frames_overlap; for (int j = 0; j < nch; j++) *pb++ = v; blend += 65536; // 2^16 } s->output_overlap = output_overlap_s16; } else { float *pb = s->table_blend; for (int i = 0; i < frames_overlap; i++) { float v = i / (float)frames_overlap; for (int j = 0; j < nch; j++) *pb++ = v; } s->output_overlap = output_overlap_float; } } s->frames_search = (frames_overlap > 1) ? srate * s->ms_search : 0; if (s->frames_search <= 0) s->best_overlap_offset = NULL; else { if (use_int) { int64_t t = frames_overlap; int32_t n = 8589934588LL / (t * t); // 4 * (2^31 - 1) / t^2 s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap * 2 + UNROLL_PADDING); s->table_window = realloc(s->table_window, s->bytes_overlap * 2 - nch * bps * 2); if (!s->buf_pre_corr || !s->table_window) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[scaletempo] Out of memory\n"); return AF_ERROR; } memset((char *)s->buf_pre_corr + s->bytes_overlap * 2, 0, UNROLL_PADDING); int32_t *pw = s->table_window; for (int i = 1; i < frames_overlap; i++) { int32_t v = (i * (t - i) * n) >> 15; for (int j = 0; j < nch; j++) *pw++ = v; } s->best_overlap_offset = best_overlap_offset_s16; } else { s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap); s->table_window = realloc(s->table_window, s->bytes_overlap - nch * bps); if (!s->buf_pre_corr || !s->table_window) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[scaletempo] Out of memory\n"); return AF_ERROR; } float *pw = s->table_window; for (int i = 1; i < frames_overlap; i++) { float v = i * (frames_overlap - i); for (int j = 0; j < nch; j++) *pw++ = v; } s->best_overlap_offset = best_overlap_offset_float; } } s->bytes_per_frame = bps * nch; s->num_channels = nch; s->bytes_queue = (s->frames_search + s->frames_stride + frames_overlap) * bps * nch; s->buf_queue = realloc(s->buf_queue, s->bytes_queue + UNROLL_PADDING); if (!s->buf_queue) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[scaletempo] Out of memory\n"); return AF_ERROR; } s->bytes_queued = 0; s->bytes_to_slide = 0; mp_msg(MSGT_AFILTER, MSGL_DBG2, "[scaletempo] " "%.2f stride_in, %i stride_out, %i standing, " "%i overlap, %i search, %i queue, %s mode\n", s->frames_stride_scaled, (int)(s->bytes_stride / nch / bps), (int)(s->bytes_standing / nch / bps), (int)(s->bytes_overlap / nch / bps), s->frames_search, (int)(s->bytes_queue / nch / bps), (use_int ? "s16" : "float")); return af_test_output(af, (struct mp_audio *)arg); } case AF_CONTROL_SET_PLAYBACK_SPEED: { if (s->speed_tempo) { if (s->speed_pitch) break; s->speed = *(double *)arg; s->scale = s->speed * s->scale_nominal; } else { if (s->speed_pitch) { s->speed = 1 / *(double *)arg; s->scale = s->speed * s->scale_nominal; break; } } return AF_OK; } case AF_CONTROL_RESET: s->bytes_queued = 0; s->bytes_to_slide = 0; s->frames_stride_error = 0; memset(s->buf_overlap, 0, s->bytes_overlap); }
// Initialization and runtime control static int control(struct af_instance *af, int cmd, void *arg) { af_ac3enc_t *s = af->priv; static const int default_bit_rate[AC3_MAX_CHANNELS+1] = \ {0, 96000, 192000, 256000, 384000, 448000, 448000}; switch (cmd){ case AF_CONTROL_REINIT: { struct mp_audio *in = arg; struct mp_audio orig_in = *in; if (AF_FORMAT_IS_SPECIAL(in->format) || in->nch < s->cfg_min_channel_num) return AF_DETACH; mp_audio_set_format(in, s->in_sampleformat); if (in->rate != 48000 && in->rate != 44100 && in->rate != 32000) in->rate = 48000; af->data->rate = in->rate; mp_chmap_reorder_to_lavc(&in->channels); if (in->nch > AC3_MAX_CHANNELS) mp_audio_set_num_channels(in, AC3_MAX_CHANNELS); mp_audio_set_format(af->data, AF_FORMAT_S_AC3); mp_audio_set_num_channels(af->data, 2); if (!mp_audio_config_equals(in, &orig_in)) return AF_FALSE; s->in_samples = AC3_FRAME_SIZE; if (s->cfg_add_iec61937_header) { s->out_samples = AC3_FRAME_SIZE; } else { s->out_samples = AC3_MAX_CODED_FRAME_SIZE / af->data->sstride; } mp_audio_copy_config(s->input, in); mp_audio_realloc(s->input, s->in_samples); s->input->samples = 0; talloc_free(s->pending); s->pending = NULL; MP_DBG(af, "af_lavcac3enc reinit: %d, %d, %d.\n", in->nch, in->rate, s->in_samples); int bit_rate = s->bit_rate ? s->bit_rate : default_bit_rate[in->nch]; if (s->lavc_actx->channels != in->nch || s->lavc_actx->sample_rate != in->rate || s->lavc_actx->bit_rate != bit_rate) { avcodec_close(s->lavc_actx); // Put sample parameters s->lavc_actx->channels = in->nch; s->lavc_actx->channel_layout = mp_chmap_to_lavc(&in->channels); s->lavc_actx->sample_rate = in->rate; s->lavc_actx->bit_rate = bit_rate; if (avcodec_open2(s->lavc_actx, s->lavc_acodec, NULL) < 0) { MP_ERR(af, "Couldn't open codec %s, br=%d.\n", "ac3", bit_rate); return AF_ERROR; } } if (s->lavc_actx->frame_size != AC3_FRAME_SIZE) { MP_ERR(af, "lavcac3enc: unexpected ac3 " "encoder frame size %d\n", s->lavc_actx->frame_size); return AF_ERROR; } return AF_OK; } } return AF_UNKNOWN; }
/* Initialization and runtime control af audio filter instance cmd control command arg argument */ static int control(struct af_instance* af, int cmd, void* arg) { af_export_t* s = af->priv; switch (cmd){ case AF_CONTROL_REINIT:{ int i=0; int mapsize; // Free previous buffers free(s->buf[0]); // unmap previous area if(s->mmap_area) munmap(s->mmap_area, SIZE_HEADER + (af->data->bps*s->sz*af->data->nch)); // close previous file descriptor if(s->fd) close(s->fd); // Accept only int16_t as input format (which sucks) mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_format(af->data, AF_FORMAT_S16); // Allocate new buffers (as one continuous block) s->buf[0] = calloc(s->sz*af->data->nch, af->data->bps); if(NULL == s->buf[0]) { MP_FATAL(af, "Out of memory\n"); return AF_ERROR; } for(i = 1; i < af->data->nch; i++) s->buf[i] = (uint8_t *)s->buf[0] + i*s->sz*af->data->bps; if (!s->filename) { MP_FATAL(af, "No filename set.\n"); return AF_ERROR; } // Init memory mapping s->fd = open(s->filename, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0640); MP_INFO(af, "Exporting to file: %s\n", s->filename); if(s->fd < 0) { MP_FATAL(af, "Could not open/create file: %s\n", s->filename); return AF_ERROR; } // header + buffer mapsize = (SIZE_HEADER + (af->data->bps * s->sz * af->data->nch)); // grow file to needed size for(i = 0; i < mapsize; i++){ char null = 0; write(s->fd, (void*) &null, 1); } // mmap size s->mmap_area = mmap(0, mapsize, PROT_READ|PROT_WRITE,MAP_SHARED, s->fd, 0); if(s->mmap_area == NULL) MP_FATAL(af, "Could not mmap file %s\n", s->filename); MP_INFO(af, "Memory mapped to file: %s (%p)\n", s->filename, s->mmap_area); // Initialize header *((int*)s->mmap_area) = af->data->nch; *((int*)s->mmap_area + 1) = s->sz * af->data->bps * af->data->nch; msync(s->mmap_area, mapsize, MS_ASYNC); // Use test_output to return FALSE if necessary return af_test_output(af, (struct mp_audio*)arg); } } return AF_UNKNOWN; }
/* Initialization and runtime control af audio filter instance cmd control command arg argument */ static int control(struct af_instance* af, int cmd, void* arg) { af_export_t* s = af->setup; switch (cmd){ case AF_CONTROL_REINIT:{ int i=0; int mapsize; // Free previous buffers if (s->buf) free(s->buf[0]); // unmap previous area if(s->mmap_area) munmap(s->mmap_area, SIZE_HEADER + (af->data->bps*s->sz*af->data->nch)); // close previous file descriptor if(s->fd) close(s->fd); // Accept only int16_t as input format (which sucks) mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_format(af->data, AF_FORMAT_S16); // If buffer length isn't set, set it to the default value if(s->sz == 0) s->sz = DEF_SZ; // Allocate new buffers (as one continuous block) s->buf[0] = calloc(s->sz*af->data->nch, af->data->bps); if(NULL == s->buf[0]) mp_msg(MSGT_AFILTER, MSGL_FATAL, "[export] Out of memory\n"); for(i = 1; i < af->data->nch; i++) s->buf[i] = (uint8_t *)s->buf[0] + i*s->sz*af->data->bps; if (!s->filename) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[export] No filename set.\n"); return AF_ERROR; } // Init memory mapping s->fd = open(s->filename, O_RDWR | O_CREAT | O_TRUNC, 0640); mp_msg(MSGT_AFILTER, MSGL_INFO, "[export] Exporting to file: %s\n", s->filename); if(s->fd < 0) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[export] Could not open/create file: %s\n", s->filename); return AF_ERROR; } // header + buffer mapsize = (SIZE_HEADER + (af->data->bps * s->sz * af->data->nch)); // grow file to needed size for(i = 0; i < mapsize; i++){ char null = 0; write(s->fd, (void*) &null, 1); } // mmap size s->mmap_area = mmap(0, mapsize, PROT_READ|PROT_WRITE,MAP_SHARED, s->fd, 0); if(s->mmap_area == NULL) mp_msg(MSGT_AFILTER, MSGL_FATAL, "[export] Could not mmap file %s\n", s->filename); mp_msg(MSGT_AFILTER, MSGL_INFO, "[export] Memory mapped to file: %s (%p)\n", s->filename, s->mmap_area); // Initialize header *((int*)s->mmap_area) = af->data->nch; *((int*)s->mmap_area + 1) = s->sz * af->data->bps * af->data->nch; msync(s->mmap_area, mapsize, MS_ASYNC); // Use test_output to return FALSE if necessary return af_test_output(af, (struct mp_audio*)arg); } case AF_CONTROL_COMMAND_LINE:{ int i=0; char *str = arg; if (!str){ talloc_free(s->filename); s->filename = mp_find_user_config_file(SHARED_FILE); return AF_OK; } while((str[i]) && (str[i] != ':')) i++; talloc_free(s->filename); s->filename = talloc_array_size(NULL, 1, i + 1); memcpy(s->filename, str, i); s->filename[i] = 0; sscanf(str + i + 1, "%d", &(s->sz)); if((s->sz <= 0) || (s->sz > 2048)) mp_msg(MSGT_AFILTER, MSGL_ERR, "[export] Buffer size must be between" " 1 and 2048\n" ); return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance *af, int cmd, void *arg) { af_ac3enc_t *s = af->priv; static const int default_bit_rate[AC3_MAX_CHANNELS+1] = \ {0, 96000, 192000, 256000, 384000, 448000, 448000}; switch (cmd){ case AF_CONTROL_REINIT: { struct mp_audio *in = arg; struct mp_audio orig_in = *in; if (!af_fmt_is_pcm(in->format) || in->nch < s->cfg_min_channel_num) return AF_DETACH; // At least currently, the AC3 encoder doesn't export sample rates. in->rate = 48000; select_encode_format(s->lavc_actx, in); af->data->rate = in->rate; mp_audio_set_format(af->data, AF_FORMAT_S_AC3); mp_audio_set_num_channels(af->data, 2); if (!mp_audio_config_equals(in, &orig_in)) return AF_FALSE; if (s->cfg_add_iec61937_header) { s->out_samples = AC3_FRAME_SIZE; } else { s->out_samples = AC3_MAX_CODED_FRAME_SIZE / af->data->sstride; } mp_audio_copy_config(s->input, in); talloc_free(s->pending); s->pending = NULL; MP_DBG(af, "reinit: %d, %d, %d.\n", in->nch, in->rate, s->in_samples); int bit_rate = s->bit_rate ? s->bit_rate : default_bit_rate[in->nch]; if (s->lavc_actx->channels != in->nch || s->lavc_actx->sample_rate != in->rate || s->lavc_actx->bit_rate != bit_rate) { avcodec_close(s->lavc_actx); // Put sample parameters s->lavc_actx->sample_fmt = af_to_avformat(in->format); s->lavc_actx->channels = in->nch; s->lavc_actx->channel_layout = mp_chmap_to_lavc(&in->channels); s->lavc_actx->sample_rate = in->rate; s->lavc_actx->bit_rate = bit_rate; if (avcodec_open2(s->lavc_actx, s->lavc_acodec, NULL) < 0) { MP_ERR(af, "Couldn't open codec %s, br=%d.\n", "ac3", bit_rate); return AF_ERROR; } if (s->lavc_actx->frame_size < 1) { MP_ERR(af, "encoder didn't specify input frame size\n"); return AF_ERROR; } } s->in_samples = s->lavc_actx->frame_size; mp_audio_realloc(s->input, s->in_samples); s->input->samples = 0; s->encoder_buffered = 0; return AF_OK; } case AF_CONTROL_RESET: if (avcodec_is_open(s->lavc_actx)) avcodec_flush_buffers(s->lavc_actx); talloc_free(s->pending); s->pending = NULL; s->input->samples = 0; s->encoder_buffered = 0; return AF_OK; } return AF_UNKNOWN; }