// 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; }
void reinit_audio_chain(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; init_demux_stream(mpctx, STREAM_AUDIO); if (!mpctx->sh_audio) { uninit_player(mpctx, INITIALIZED_AO); goto no_audio; } if (!(mpctx->initialized_flags & INITIALIZED_ACODEC)) { if (!init_best_audio_codec(mpctx->sh_audio, opts->audio_decoders)) goto init_error; mpctx->initialized_flags |= INITIALIZED_ACODEC; } int ao_srate = opts->force_srate; int ao_format = opts->audio_output_format; struct mp_chmap ao_channels = {0}; if (mpctx->initialized_flags & INITIALIZED_AO) { ao_srate = mpctx->ao->samplerate; ao_format = mpctx->ao->format; ao_channels = mpctx->ao->channels; } else { // Automatic downmix if (mp_chmap_is_stereo(&opts->audio_output_channels) && !mp_chmap_is_stereo(&mpctx->sh_audio->channels)) { mp_chmap_from_channels(&ao_channels, 2); } } // Determine what the filter chain outputs. build_afilter_chain() also // needs this for testing whether playback speed is changed by resampling // or using a special filter. if (!init_audio_filters(mpctx->sh_audio, // preliminary init // input: mpctx->sh_audio->samplerate, // output: &ao_srate, &ao_channels, &ao_format)) { MP_ERR(mpctx, "Error at audio filter chain pre-init!\n"); goto init_error; } if (!(mpctx->initialized_flags & INITIALIZED_AO)) { mpctx->initialized_flags |= INITIALIZED_AO; mp_chmap_remove_useless_channels(&ao_channels, &opts->audio_output_channels); mpctx->ao = ao_init_best(mpctx->global, mpctx->input, mpctx->encode_lavc_ctx, ao_srate, ao_format, ao_channels); struct ao *ao = mpctx->ao; if (!ao) { MP_ERR(mpctx, "Could not open/initialize audio device -> no sound.\n"); goto init_error; } ao->buffer.start = talloc_new(ao); char *s = mp_audio_fmt_to_str(ao->samplerate, &ao->channels, ao->format); MP_INFO(mpctx, "AO: [%s] %s\n", ao->driver->name, s); talloc_free(s); MP_VERBOSE(mpctx, "AO: Description: %s\n", ao->driver->description); update_window_title(mpctx, true); } if (recreate_audio_filters(mpctx) < 0) goto init_error; mpctx->syncing_audio = true; return; init_error: uninit_player(mpctx, INITIALIZED_ACODEC | INITIALIZED_AO); cleanup_demux_stream(mpctx, STREAM_AUDIO); no_audio: mpctx->current_track[STREAM_AUDIO] = NULL; MP_INFO(mpctx, "Audio: no audio\n"); }