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_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; }
// 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_channels_t* s = af->priv; switch(cmd){ case AF_CONTROL_REINIT: ; struct mp_chmap chmap; mp_chmap_set_unknown(&chmap, s->nch); mp_audio_set_channels(af->data, &chmap); // Set default channel assignment if(!s->router){ int i; // Make sure this filter isn't redundant if(af->data->nch == ((struct mp_audio*)arg)->nch) return AF_DETACH; // If mono: fake stereo if(((struct mp_audio*)arg)->nch == 1){ s->nr = MPMIN(af->data->nch,2); for(i=0;i<s->nr;i++){ s->route[i][FR] = 0; s->route[i][TO] = i; } } else{ s->nr = MPMIN(af->data->nch, ((struct mp_audio*)arg)->nch); for(i=0;i<s->nr;i++){ s->route[i][FR] = i; s->route[i][TO] = i; } } } af->data->rate = ((struct mp_audio*)arg)->rate; mp_audio_force_interleaved_format((struct mp_audio*)arg); mp_audio_set_format(af->data, ((struct mp_audio*)arg)->format); return check_routes(af,((struct mp_audio*)arg)->nch,af->data->nch); } 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); }