// 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; }
// 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; }
// 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; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_volnorm_t* s = (af_volnorm_t*)af->setup; switch(cmd){ case AF_CONTROL_REINIT: // Sanity check if(!arg) return AF_ERROR; af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = ((af_data_t*)arg)->nch; if(((af_data_t*)arg)->format == (AF_FORMAT_S16_NE)){ af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; }else{ af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; } return af_test_output(af,(af_data_t*)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 = ((float)INT_MAX) * target; return AF_OK; } } 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; }
/* Initialization and runtime control */ static int control(struct af_instance *af, int cmd, void* arg) { af_hrtf_t *s = af->priv; int test_output_res; switch(cmd) { case AF_CONTROL_REINIT: reset(s); af->data->rate = 48000; mp_audio_set_channels_old(af->data, ((struct mp_audio*)arg)->nch); if(af->data->nch == 2) { /* 2 channel input */ if(s->decode_mode != HRTF_MIX_MATRIX2CH) { /* Default behavior is stereo mixing. */ s->decode_mode = HRTF_MIX_STEREO; } } else if (af->data->nch < 5) { mp_audio_set_channels_old(af->data, 5); } mp_audio_set_format(af->data, AF_FORMAT_S16); test_output_res = af_test_output(af, (struct mp_audio*)arg); // after testing input set the real output format mp_audio_set_num_channels(af->data, 2); s->print_flag = 1; return test_output_res; case AF_CONTROL_RESET: reset(s); return AF_OK; } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_sub_t* s = af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ // Sanity check if(!arg) return AF_ERROR; af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = max(s->ch+1,((af_data_t*)arg)->nch); af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; // Design low-pass filter s->k = 1.0; if((-1 == af_filter_szxform(sp[0].a, sp[0].b, Q, s->fc, (float)af->data->rate, &s->k, s->w[0])) || (-1 == af_filter_szxform(sp[1].a, sp[1].b, Q, s->fc, (float)af->data->rate, &s->k, s->w[1]))) return AF_ERROR; return af_test_output(af,(af_data_t*)arg); } case AF_CONTROL_COMMAND_LINE:{ int ch=5; float fc=60.0; sscanf(arg,"%f:%i", &fc , &ch); if(AF_OK != control(af,AF_CONTROL_SUB_CH | AF_CONTROL_SET, &ch)) return AF_ERROR; return control(af,AF_CONTROL_SUB_FC | AF_CONTROL_SET, &fc); } case AF_CONTROL_SUB_CH | AF_CONTROL_SET: // Requires reinit // Sanity check if((*(int*)arg >= AF_NCH) || (*(int*)arg < 0)){ af_msg(AF_MSG_ERROR,"[sub] Subwoofer channel number must be between " " 0 and %i current value is %i\n", AF_NCH-1, *(int*)arg); return AF_ERROR; } s->ch = *(int*)arg; return AF_OK; case AF_CONTROL_SUB_CH | AF_CONTROL_GET: *(int*)arg = s->ch; return AF_OK; case AF_CONTROL_SUB_FC | AF_CONTROL_SET: // Requires reinit // Sanity check if((*(float*)arg > 300) || (*(float*)arg < 20)){ af_msg(AF_MSG_ERROR,"[sub] Cutoff frequency must be between 20Hz and" " 300Hz current value is %0.2f",*(float*)arg); return AF_ERROR; } // Set cutoff frequency s->fc = *(float*)arg; return AF_OK; case AF_CONTROL_SUB_FC | AF_CONTROL_GET: *(float*)arg = s->fc; return AF_OK; } return AF_UNKNOWN; }
/* Initialization and runtime control */ static int control(struct af_instance *af, int cmd, void* arg) { af_hrtf_t *s = af->setup; int test_output_res; char mode; switch(cmd) { case AF_CONTROL_REINIT: af->data->rate = ((struct mp_audio*)arg)->rate; if(af->data->rate != 48000) { // automatic samplerate adjustment in the filter chain // is not yet supported. mp_msg(MSGT_AFILTER, MSGL_ERR, "[hrtf] ERROR: Sampling rate is not 48000 Hz (%d)!\n", af->data->rate); return AF_ERROR; } mp_audio_set_channels_old(af->data, ((struct mp_audio*)arg)->nch); if(af->data->nch == 2) { /* 2 channel input */ if(s->decode_mode != HRTF_MIX_MATRIX2CH) { /* Default behavior is stereo mixing. */ s->decode_mode = HRTF_MIX_STEREO; } } else if (af->data->nch < 5) mp_audio_set_channels_old(af->data, 5); mp_audio_set_format(af->data, AF_FORMAT_S16); test_output_res = af_test_output(af, (struct mp_audio*)arg); // after testing input set the real output format mp_audio_set_num_channels(af->data, 2); s->print_flag = 1; return test_output_res; case AF_CONTROL_COMMAND_LINE: sscanf((char*)arg, "%c", &mode); switch(mode) { case 'm': /* Use matrix rear decoding. */ s->matrix_mode = 1; break; case 's': /* Input needs matrix decoding. */ s->decode_mode = HRTF_MIX_MATRIX2CH; break; case '0': s->matrix_mode = 0; break; default: mp_msg(MSGT_AFILTER, MSGL_ERR, "[hrtf] Mode is neither 'm', 's', nor '0' (%c).\n", mode); return AF_ERROR; } s->print_flag = 1; return AF_OK; } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_resample_t* s = (af_resample_t*)af->setup; af_data_t *data= (af_data_t*)arg; int out_rate, test_output_res; // helpers for checking input format switch(cmd){ case AF_CONTROL_REINIT: if((af->data->rate == data->rate) || (af->data->rate == 0)) return AF_DETACH; af->data->nch = data->nch; if (af->data->nch > AF_NCH) af->data->nch = AF_NCH; af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; af->mul = (double)af->data->rate / data->rate; af->delay = af->data->nch * s->filter_length / FFMIN(af->mul, 1); // *bps*.5 if (s->ctx_out_rate != af->data->rate || s->ctx_in_rate != data->rate || s->ctx_filter_size != s->filter_length || s->ctx_phase_shift != s->phase_shift || s->ctx_linear != s->linear || s->ctx_cutoff != s->cutoff) { swr_free(&s->swrctx); if((s->swrctx=swr_alloc()) == NULL) return AF_ERROR; av_opt_set_int(s->swrctx, "out_sample_rate", af->data->rate, 0); av_opt_set_int(s->swrctx, "in_sample_rate", data->rate, 0); av_opt_set_int(s->swrctx, "filter_size", s->filter_length, 0); av_opt_set_int(s->swrctx, "phase_shift", s->phase_shift, 0); av_opt_set_int(s->swrctx, "linear_interp", s->linear, 0); av_opt_set_double(s->swrctx, "cutoff", s->cutoff, 0); av_opt_set_sample_fmt(s->swrctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_sample_fmt(s->swrctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int(s->swrctx, "in_channel_count", af->data->nch, 0); av_opt_set_int(s->swrctx, "out_channel_count", af->data->nch, 0); if(swr_init(s->swrctx) < 0) return AF_ERROR; s->ctx_out_rate = af->data->rate; s->ctx_in_rate = data->rate; s->ctx_filter_size = s->filter_length; s->ctx_phase_shift = s->phase_shift; s->ctx_linear = s->linear; s->ctx_cutoff = s->cutoff; } // hack to make af_test_output ignore the samplerate change out_rate = af->data->rate; af->data->rate = data->rate; test_output_res = af_test_output(af, (af_data_t*)arg); af->data->rate = out_rate; return test_output_res; case AF_CONTROL_COMMAND_LINE:{ s->cutoff= 0.0; sscanf((char*)arg,"%d:%d:%d:%d:%lf", &af->data->rate, &s->filter_length, &s->linear, &s->phase_shift, &s->cutoff); if(s->cutoff <= 0.0) s->cutoff= FFMAX(1.0 - 6.5/(s->filter_length+8), 0.80); return AF_OK; } case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET: af->data->rate = *(int*)arg; return AF_OK; } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_gate_t* s = (af_gate_t*)af->setup; switch(cmd){ case AF_CONTROL_REINIT: // Sanity check if(!arg) return AF_ERROR; af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = ((af_data_t*)arg)->nch; af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; // Time constant set to 0.1s // s->alpha = (1.0/0.2)/(2.0*M_PI*(float)((af_data_t*)arg)->rate); return af_test_output(af,(af_data_t*)arg); case AF_CONTROL_COMMAND_LINE:{ /* float v=-10.0; */ /* float vol[AF_NCH]; */ /* float s=0.0; */ /* float clipp[AF_NCH]; */ /* int i; */ /* sscanf((char*)arg,"%f:%f", &v, &s); */ /* for(i=0;i<AF_NCH;i++){ */ /* vol[i]=v; */ /* clipp[i]=s; */ /* } */ /* if(AF_OK != control(af,AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_SET, clipp)) */ /* return AF_ERROR; */ /* return control(af,AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, vol); */ } case AF_CONTROL_GATE_ON_OFF | AF_CONTROL_SET: memcpy(s->enable,(int*)arg,AF_NCH*sizeof(int)); return AF_OK; case AF_CONTROL_GATE_ON_OFF | AF_CONTROL_GET: memcpy((int*)arg,s->enable,AF_NCH*sizeof(int)); return AF_OK; case AF_CONTROL_GATE_THRESH | AF_CONTROL_SET: return af_from_dB(AF_NCH,(float*)arg,s->tresh,20.0,-60.0,-1.0); case AF_CONTROL_GATE_THRESH | AF_CONTROL_GET: return af_to_dB(AF_NCH,s->tresh,(float*)arg,10.0); case AF_CONTROL_GATE_ATTACK | AF_CONTROL_SET: return af_from_ms(AF_NCH,(float*)arg,s->attack,af->data->rate,500.0,0.1); case AF_CONTROL_GATE_ATTACK | AF_CONTROL_GET: return af_to_ms(AF_NCH,s->attack,(float*)arg,af->data->rate); case AF_CONTROL_GATE_RELEASE | AF_CONTROL_SET: return af_from_ms(AF_NCH,(float*)arg,s->release,af->data->rate,3000.0,10.0); case AF_CONTROL_GATE_RELEASE | AF_CONTROL_GET: return af_to_ms(AF_NCH,s->release,(float*)arg,af->data->rate); case AF_CONTROL_GATE_RANGE | AF_CONTROL_SET: return af_from_dB(AF_NCH,(float*)arg,s->range,20.0,100.0,0.0); case AF_CONTROL_GATE_RANGE | AF_CONTROL_GET: return af_to_dB(AF_NCH,s->range,(float*)arg,10.0); } 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_s* af, int cmd, void* arg) { switch(cmd){ case AF_CONTROL_REINIT: af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = ((af_data_t*)arg)->nch; af->data->format= AF_FORMAT_FLOAT_NE; af->data->bps = 4; return af_test_output(af,(af_data_t*)arg); } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance_s* 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; af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = 1; #if 0 if (((af_data_t*)arg)->format == AF_FORMAT_FLOAT_NE) { af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; af->play = play_float; }// else #endif { af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; af->play = play_s16; } return af_test_output(af,(af_data_t*)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; } case AF_CONTROL_SS_FREQ | AF_CONTROL_SET: s->freq = *(float*)arg; return AF_OK; case AF_CONTROL_SS_FREQ | AF_CONTROL_GET: *(float*)arg = s->freq; return AF_OK; case AF_CONTROL_SS_DECAY | AF_CONTROL_SET: s->decay = *(float*)arg; return AF_OK; case AF_CONTROL_SS_DECAY | AF_CONTROL_GET: *(float*)arg = s->decay; return AF_OK; } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_resample_t* s = (af_resample_t*)af->setup; af_data_t *data= (af_data_t*)arg; int out_rate, test_output_res; // helpers for checking input format switch(cmd){ case AF_CONTROL_REINIT: if((af->data->rate == data->rate) || (af->data->rate == 0)) return AF_DETACH; af->data->nch = data->nch; if (af->data->nch > AF_NCH) af->data->nch = AF_NCH; af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; af->mul = (double)af->data->rate / data->rate; af->delay = af->data->nch * s->filter_length / min(af->mul, 1); // *bps*.5 if (s->ctx_out_rate != af->data->rate || s->ctx_in_rate != data->rate || s->ctx_filter_size != s->filter_length || s->ctx_phase_shift != s->phase_shift || s->ctx_linear != s->linear || s->ctx_cutoff != s->cutoff) { if(s->avrctx) av_resample_close(s->avrctx); s->avrctx= av_resample_init(af->data->rate, /*in_rate*/data->rate, s->filter_length, s->phase_shift, s->linear, s->cutoff); s->ctx_out_rate = af->data->rate; s->ctx_in_rate = data->rate; s->ctx_filter_size = s->filter_length; s->ctx_phase_shift = s->phase_shift; s->ctx_linear = s->linear; s->ctx_cutoff = s->cutoff; } // hack to make af_test_output ignore the samplerate change out_rate = af->data->rate; af->data->rate = data->rate; test_output_res = af_test_output(af, (af_data_t*)arg); af->data->rate = out_rate; return test_output_res; case AF_CONTROL_COMMAND_LINE:{ s->cutoff= 0.0; sscanf((char*)arg,"%d:%d:%d:%d:%lf", &af->data->rate, &s->filter_length, &s->linear, &s->phase_shift, &s->cutoff); if(s->cutoff <= 0.0) s->cutoff= max(1.0 - 6.5/(s->filter_length+8), 0.80); return AF_OK; } case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET: af->data->rate = *(int*)arg; return AF_OK; } return AF_UNKNOWN; }
static int stats_init(af_instance_t *af, struct af_stats *s, af_data_t *data) { int i; if (!data) return AF_ERROR; *(af->data) = *data; af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; s->n_samples = 0; s->tsquare = 0; s->max = 0; for (i = 0; i < 65536; i++) s->histogram[i] = 0; return af_test_output(af, data); }
// 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; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_center_t* s = af->priv; switch(cmd){ case AF_CONTROL_REINIT:{ // Sanity check if(!arg) return AF_ERROR; af->data->rate = ((struct mp_audio*)arg)->rate; mp_audio_set_channels_old(af->data, MPMAX(s->ch+1,((struct mp_audio*)arg)->nch)); mp_audio_set_format(af->data, AF_FORMAT_FLOAT); 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_sub_t* s = af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ // Sanity check if(!arg) return AF_ERROR; af->data->rate = ((struct mp_audio*)arg)->rate; mp_audio_set_channels_old(af->data, MPMAX(s->ch+1,((struct mp_audio*)arg)->nch)); mp_audio_set_format(af->data, AF_FORMAT_FLOAT); // Design low-pass filter s->k = 1.0; if((-1 == af_filter_szxform(sp[0].a, sp[0].b, Q, s->fc, (float)af->data->rate, &s->k, s->w[0])) || (-1 == af_filter_szxform(sp[1].a, sp[1].b, Q, s->fc, (float)af->data->rate, &s->k, s->w[1]))) return AF_ERROR; return af_test_output(af,(struct mp_audio*)arg); } case AF_CONTROL_COMMAND_LINE:{ int ch=5; float fc=60.0; sscanf(arg,"%f:%i", &fc , &ch); // Sanity check if(ch >= AF_NCH || ch < 0){ mp_msg(MSGT_AFILTER, MSGL_ERR, "[sub] Subwoofer channel number must be between " " 0 and %i current value is %i\n", AF_NCH-1, ch); return AF_ERROR; } s->ch = ch; if(fc > 300 || fc < 20){ mp_msg(MSGT_AFILTER, MSGL_ERR, "[sub] Cutoff frequency must be between 20Hz and" " 300Hz current value is %0.2f",fc); return AF_ERROR; } s->fc = fc; return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance_s* 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; af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = 2; if (((af_data_t*)arg)->format == AF_FORMAT_FLOAT_NE) { af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; af->play = play_float; }// else { af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; af->play = play_s16; } return af_test_output(af,(af_data_t*)arg); } case AF_CONTROL_COMMAND_LINE:{ float f; sscanf((char*)arg,"%f", &f); s->mul = f; return AF_OK; } case AF_CONTROL_ES_MUL | AF_CONTROL_SET: s->mul = *(float*)arg; return AF_OK; case AF_CONTROL_ES_MUL | AF_CONTROL_GET: *(float*)arg = s->mul; return AF_OK; } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_center_t* s = af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ // Sanity check if(!arg) return AF_ERROR; af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = FFMAX(s->ch+1,((af_data_t*)arg)->nch); af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; return af_test_output(af,(af_data_t*)arg); } case AF_CONTROL_COMMAND_LINE:{ int ch=1; sscanf(arg,"%i", &ch); return control(af,AF_CONTROL_CENTER_CH | AF_CONTROL_SET, &ch); } case AF_CONTROL_CENTER_CH | AF_CONTROL_SET: // Requires reinit // Sanity check if((*(int*)arg >= AF_NCH) || (*(int*)arg < 0)){ mp_msg(MSGT_AFILTER, MSGL_ERR, "[sub] Center channel number must be between " " 0 and %i current value is %i\n", AF_NCH-1, *(int*)arg); return AF_ERROR; } s->ch = *(int*)arg; return AF_OK; case AF_CONTROL_CENTER_CH | AF_CONTROL_GET: *(int*)arg = s->ch; 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; }
static int control(struct af_instance_s *af, int cmd, void *arg) { af_ladspa_t *setup = (af_ladspa_t*) af->setup; int i, r; float val; switch(cmd) { case AF_CONTROL_REINIT: mp_msg(MSGT_AFILTER, MSGL_V, "%s: (re)init\n", setup->myname); if (!arg) return AF_ERROR; /* accept FLOAT, let af_format do conversion */ af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = ((af_data_t*)arg)->nch; af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; /* arg->len is not set here yet, so init of buffers and connecting the * filter, has to be done in play() :-/ */ return af_test_output(af, (af_data_t*)arg); case AF_CONTROL_COMMAND_LINE: { char *buf; mp_msg(MSGT_AFILTER, MSGL_V, "%s: parse suboptions\n", setup->myname); /* suboption parser here! * format is (ladspa=)file:label:controls.... */ if (!arg) { mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNoSuboptions); return AF_ERROR; } buf = malloc(strlen(arg)+1); if (!buf) return af_ladspa_malloc_failed(setup->myname); /* file... */ buf[0] = '\0'; sscanf(arg, "%[^:]", buf); if (buf[0] == '\0') { mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNoLibFile); free(buf); return AF_ERROR; } arg += strlen(buf); setup->file = strdup(buf); if (!setup->file) return af_ladspa_malloc_failed(setup->myname); mp_msg(MSGT_AFILTER, MSGL_V, "%s: file --> %s\n", setup->myname, setup->file); if (*(char*)arg != '\0') arg++; /* read ':' */ /* label... */ buf[0] = '\0'; sscanf(arg, "%[^:]", buf); if (buf[0] == '\0') { mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNoLabel); free(buf); return AF_ERROR; } arg += strlen(buf); setup->label = strdup(buf); if (!setup->label) return af_ladspa_malloc_failed(setup->myname); mp_msg(MSGT_AFILTER, MSGL_V, "%s: label --> %s\n", setup->myname, setup->label); /* if (*(char*)arg != '0') arg++; */ /* read ':' */ free(buf); /* no longer needed */ /* set new setup->myname */ free(setup->myname); setup->myname = calloc(strlen(af_info_ladspa.name)+strlen(setup->file)+ strlen(setup->label)+6, 1); snprintf(setup->myname, strlen(af_info_ladspa.name)+ strlen(setup->file)+strlen(setup->label)+6, "%s: (%s:%s)", af_info_ladspa.name, setup->file, setup->label); /* load plugin :) */ if ( af_ladspa_load_plugin(setup) != AF_OK ) return AF_ERROR; /* see what inputs, outputs and controls this plugin has */ if ( af_ladspa_parse_plugin(setup) != AF_OK ) return AF_ERROR; /* ninputcontrols is set by now, read control values from arg */ for(i=0; i<setup->ninputcontrols; i++) { if (!arg || (*(char*)arg != ':') ) { mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNotEnoughControls); return AF_ERROR; } arg++; r = sscanf(arg, "%f", &val); if (r!=1) { mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNotEnoughControls); return AF_ERROR; } setup->inputcontrols[setup->inputcontrolsmap[i]] = val; arg = strchr(arg, ':'); } mp_msg(MSGT_AFILTER, MSGL_V, "%s: input controls: ", setup->myname); for(i=0; i<setup->ninputcontrols; i++) { mp_msg(MSGT_AFILTER, MSGL_V, "%0.4f ", setup->inputcontrols[setup->inputcontrolsmap[i]]); } mp_msg(MSGT_AFILTER, MSGL_V, "\n"); /* check boundaries of inputcontrols */ mp_msg(MSGT_AFILTER, MSGL_V, "%s: checking boundaries of input controls\n", setup->myname); for(i=0; i<setup->ninputcontrols; i++) { int p = setup->inputcontrolsmap[i]; LADSPA_PortRangeHint hint = setup->plugin_descriptor->PortRangeHints[p]; val = setup->inputcontrols[p]; if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) && val < hint.LowerBound) { mp_msg(MSGT_AFILTER, MSGL_ERR, MSGTR_AF_LADSPA_ErrControlBelow, setup->myname, i, hint.LowerBound); return AF_ERROR; } if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) && val > hint.UpperBound) { mp_msg(MSGT_AFILTER, MSGL_ERR, MSGTR_AF_LADSPA_ErrControlAbove, setup->myname, i, hint.UpperBound); return AF_ERROR; } } mp_msg(MSGT_AFILTER, MSGL_V, "%s: all controls have sane values\n", setup->myname); /* All is well! */ setup->status = AF_OK; 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_s* 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 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) af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = ((af_data_t*)arg)->nch; af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; // 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; // 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, (af_data_t*)arg); } case AF_CONTROL_COMMAND_LINE:{ int i=0; char *str = arg; if (!str){ free(s->filename); s->filename = get_path(SHARED_FILE); return AF_OK; } while((str[i]) && (str[i] != ':')) i++; free(s->filename); s->filename = calloc(i + 1, 1); memcpy(s->filename, str, i); s->filename[i] = 0; sscanf(str + i + 1, "%d", &(s->sz)); return af->control(af, AF_CONTROL_EXPORT_SZ | AF_CONTROL_SET, &s->sz); } case AF_CONTROL_EXPORT_SZ | AF_CONTROL_SET: s->sz = * (int *) arg; 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; case AF_CONTROL_EXPORT_SZ | AF_CONTROL_GET: *(int*) arg = s->sz; 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 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_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; af->data->rate = ((struct mp_audio*)arg)->rate; af->data->nch = ((struct mp_audio*)arg)->nch; af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; // 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; } case AF_CONTROL_EQUALIZER_GAIN | AF_CONTROL_SET:{ float* gain = ((af_control_ext_t*)arg)->arg; int ch = ((af_control_ext_t*)arg)->ch; int k; if(ch >= AF_NCH || ch < 0) return AF_ERROR; for(k = 0 ; k<KM ; k++) s->g[ch][k] = pow(10.0,clamp(gain[k],G_MIN,G_MAX)/20.0)-1.0; return AF_OK; } case AF_CONTROL_EQUALIZER_GAIN | AF_CONTROL_GET:{ float* gain = ((af_control_ext_t*)arg)->arg; int ch = ((af_control_ext_t*)arg)->ch; int k; if(ch >= AF_NCH || ch < 0) return AF_ERROR; for(k = 0 ; k<KM ; k++) gain[k] = log10(s->g[ch][k]+1.0) * 20.0; return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_volume_t* s = (af_volume_t*)af->setup; switch(cmd){ case AF_CONTROL_REINIT: // Sanity check if(!arg) return AF_ERROR; af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = ((af_data_t*)arg)->nch; if(s->fast && (((af_data_t*)arg)->format != (AF_FORMAT_FLOAT_NE))){ af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; } else{ // Cutoff set to 10Hz for forgetting factor float x = 2.0*M_PI*15.0/(float)af->data->rate; float t = 2.0-cos(x); s->time = 1.0 - (t - sqrt(t*t - 1)); mp_msg(MSGT_AFILTER, MSGL_DBG2, "[volume] Forgetting factor = %0.5f\n",s->time); af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; } return af_test_output(af,(af_data_t*)arg); case AF_CONTROL_COMMAND_LINE:{ float v=0.0; float vol[AF_NCH]; int i; sscanf((char*)arg,"%f:%i", &v, &s->soft); for(i=0;i<AF_NCH;i++) vol[i]=v; return control(af,AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, vol); } case AF_CONTROL_POST_CREATE: s->fast = ((((af_cfg_t*)arg)->force & AF_INIT_FORMAT_MASK) == AF_INIT_FLOAT) ? 0 : 1; return AF_OK; case AF_CONTROL_VOLUME_ON_OFF | AF_CONTROL_SET: memcpy(s->enable,(int*)arg,AF_NCH*sizeof(int)); return AF_OK; case AF_CONTROL_VOLUME_ON_OFF | AF_CONTROL_GET: memcpy((int*)arg,s->enable,AF_NCH*sizeof(int)); return AF_OK; case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_SET: s->soft = *(int*)arg; return AF_OK; case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_GET: *(int*)arg = s->soft; return AF_OK; case AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET: return af_from_dB(AF_NCH,(float*)arg,s->level,20.0,-200.0,60.0); case AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET: return af_to_dB(AF_NCH,s->level,(float*)arg,20.0); case AF_CONTROL_VOLUME_PROBE | AF_CONTROL_GET: return af_to_dB(AF_NCH,s->pow,(float*)arg,10.0); case AF_CONTROL_VOLUME_PROBE_MAX | AF_CONTROL_GET: return af_to_dB(AF_NCH,s->max,(float*)arg,10.0); case AF_CONTROL_PRE_DESTROY:{ float m = 0.0; int i; if(!s->fast){ for(i=0;i<AF_NCH;i++) m=max(m,s->max[i]); af_to_dB(1, &m, &m, 10.0); mp_msg(MSGT_AFILTER, MSGL_INFO, "[volume] The maximum volume was %0.2fdB \n", m); } return AF_OK; } } return AF_UNKNOWN; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_scaletempo_t* s = af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ af_data_t* data = (af_data_t*)arg; float srate = data->rate / 1000.0f; 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); if (s->scale == 1.0) { if (s->speed_tempo && s->speed_pitch) return AF_DETACH; memcpy(af->data, data, sizeof(af_data_t)); return af_test_output(af, data); } af->data->rate = data->rate; af->data->nch = data->nch; if ( data->format == AF_FORMAT_S16_LE || data->format == AF_FORMAT_S16_BE ) { use_int = 1; af->data->format = AF_FORMAT_S16_NE; af->data->bps = bps = 2; } else { af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = bps = 4; } 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; 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; } else { int old_overlap = s->bytes_overlap; 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; } // not necessarily correct, but keeping old data if possible // avoids clicks when changing speed. if (s->bytes_overlap != old_overlap) 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; } 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, (af_data_t*)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; 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] " MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange ": scale > 0\n"); return AF_ERROR; } if (s->ms_stride <= 0) { mp_msg(MSGT_AFILTER, MSGL_ERR, "[scaletempo] " MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange ": stride > 0\n"); return AF_ERROR; } if (s->percent_overlap < 0 || s->percent_overlap > 1) { mp_msg(MSGT_AFILTER, MSGL_ERR, "[scaletempo] " MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange ": 0 <= overlap <= 1\n"); return AF_ERROR; } if (s->ms_search < 0) { mp_msg(MSGT_AFILTER, MSGL_ERR, "[scaletempo] " MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange ": search >= 0\n"); 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] " MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange ": speed=[pitch|tempo|none|both]\n"); 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_s *af, int cmd, void *arg) { af_ac3enc_t *s = (af_ac3enc_t *)af->setup; af_data_t *data = (af_data_t *)arg; int i, bit_rate, test_output_res; static const int default_bit_rate[AC3_MAX_CHANNELS+1] = \ {0, 96000, 192000, 256000, 384000, 448000, 448000}; switch (cmd){ case AF_CONTROL_REINIT: if (AF_FORMAT_IS_AC3(data->format) || data->nch < s->min_channel_num) return AF_DETACH; s->pending_len = 0; s->expect_len = AC3_FRAME_SIZE * data->nch * data->bps; if (s->add_iec61937_header) af->mul = (double)AC3_FRAME_SIZE * 2 * 2 / s->expect_len; else af->mul = (double)AC3_MAX_CODED_FRAME_SIZE / s->expect_len; mp_msg(MSGT_AFILTER, MSGL_DBG2, "af_lavcac3enc reinit: %d, %d, %f, %d.\n", data->nch, data->rate, af->mul, s->expect_len); af->data->format = AF_FORMAT_S16_NE; if (data->rate == 48000 || data->rate == 44100 || data->rate == 32000) af->data->rate = data->rate; else af->data->rate = 48000; if (data->nch > AC3_MAX_CHANNELS) af->data->nch = AC3_MAX_CHANNELS; else af->data->nch = data->nch; af->data->bps = 2; test_output_res = af_test_output(af, data); bit_rate = s->bit_rate ? s->bit_rate : default_bit_rate[af->data->nch]; if (s->lavc_actx->channels != af->data->nch || s->lavc_actx->sample_rate != af->data->rate || s->lavc_actx->bit_rate != bit_rate) { if (s->lavc_actx->codec) avcodec_close(s->lavc_actx); // Put sample parameters s->lavc_actx->channels = af->data->nch; s->lavc_actx->sample_rate = af->data->rate; s->lavc_actx->bit_rate = bit_rate; if(avcodec_open(s->lavc_actx, s->lavc_acodec) < 0) { mp_msg(MSGT_AFILTER, MSGL_ERR, MSGTR_CouldntOpenCodec, "ac3", bit_rate); return AF_ERROR; } } af->data->format = AF_FORMAT_AC3_BE; af->data->nch = 2; return test_output_res; case AF_CONTROL_COMMAND_LINE: mp_msg(MSGT_AFILTER, MSGL_DBG2, "af_lavcac3enc cmdline: %s.\n", (char*)arg); s->bit_rate = 0; s->min_channel_num = 0; s->add_iec61937_header = 0; sscanf((char*)arg,"%d:%d:%d", &s->add_iec61937_header, &s->bit_rate, &s->min_channel_num); if (s->bit_rate < 1000) s->bit_rate *= 1000; if (s->bit_rate) { for (i = 0; i < 19; ++i) if (ff_ac3_bitrate_tab[i] * 1000 == s->bit_rate) break; if (i >= 19) { mp_msg(MSGT_AFILTER, MSGL_WARN, "af_lavcac3enc unable set unsupported " "bitrate %d, use default bitrate (check manpage to see " "supported bitrates).\n", s->bit_rate); s->bit_rate = 0; } } if (s->min_channel_num == 0) s->min_channel_num = 5; mp_msg(MSGT_AFILTER, MSGL_V, "af_lavcac3enc config spdif:%d, bitrate:%d, " "minchnum:%d.\n", s->add_iec61937_header, s->bit_rate, s->min_channel_num); return AF_OK; } return AF_UNKNOWN; }