From fcd963afe3fd87c1bcd959e4c34185f6757f8713 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Fri, 6 Dec 2013 14:34:15 -0500 Subject: [PATCH] src/io/source_avcodec.c: add _multi, building AVAudioResampleContext the first time _do or _do_multi is run --- src/io/source_avcodec.c | 110 ++++++++++++++++++++++++++++++++++++------------ src/io/source_avcodec.h | 2 +- 2 files changed, 84 insertions(+), 28 deletions(-) diff --git a/src/io/source_avcodec.c b/src/io/source_avcodec.c index a53d7208..847f7cdc 100644 --- a/src/io/source_avcodec.c +++ b/src/io/source_avcodec.c @@ -57,8 +57,13 @@ struct _aubio_source_avcodec_t { uint_t read_index; sint_t selected_stream; uint_t eof; + uint_t multi; }; +/* convenience function to recreate the AVAudioResampleContext the first time _do + * or _do_multi is called */ +void aubio_source_avcodec_set_multi(aubio_source_avcodec_t * s, uint_t multi); + aubio_source_avcodec_t * new_aubio_source_avcodec(char_t * path, uint_t samplerate, uint_t hop_size) { aubio_source_avcodec_t * s = AUBIO_NEW(aubio_source_avcodec_t); int err; @@ -157,25 +162,6 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(char_t * path, uint_t samplera } s->samplerate = samplerate; - int64_t input_layout = av_get_default_channel_layout(s->input_channels); - int64_t mono_layout = av_get_default_channel_layout(1); - - AVAudioResampleContext *avr = s->avr; - avr = avresample_alloc_context(); - av_opt_set_int(avr, "in_channel_layout", input_layout, 0); - av_opt_set_int(avr, "out_channel_layout", mono_layout, 0); - av_opt_set_int(avr, "in_sample_rate", s->input_samplerate, 0); - av_opt_set_int(avr, "out_sample_rate", s->samplerate, 0); - av_opt_set_int(avr, "in_sample_fmt", avCodecCtx->sample_fmt, 0); - av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); - if ( ( err = avresample_open(avr) ) < 0) { - char errorstr[256]; - av_strerror (err, errorstr, sizeof(errorstr)); - AUBIO_ERR("Could not open AVAudioResampleContext for %s (%s)\n", - s->path, errorstr); - goto beach; - } - AVFrame *avFrame = s->avFrame; avFrame = avcodec_alloc_frame(); if (!avFrame) { @@ -191,17 +177,20 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(char_t * path, uint_t samplera s->avFormatCtx = avFormatCtx; s->avCodecCtx = avCodecCtx; s->avFrame = avFrame; - s->avr = avr; + + // default to mono output + aubio_source_avcodec_set_multi(s, 0); s->eof = 0; + s->multi = 0; //av_log_set_level(AV_LOG_QUIET); return s; beach: - AUBIO_ERR("can not read %s at samplerate %dHz with a hop_size of %d\n", - s->path, s->samplerate, s->hop_size); + //AUBIO_ERR("can not read %s at samplerate %dHz with a hop_size of %d\n", + // s->path, s->samplerate, s->hop_size); del_aubio_source_avcodec(s); return NULL; } @@ -246,9 +235,6 @@ void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s, uint_t * read_sam int in_linesize = 0; av_samples_get_buffer_size(&in_linesize, avCodecCtx->channels, avFrame->nb_samples, avCodecCtx->sample_fmt, 1); - //AUBIO_WRN("Got data_size %d in_linesize %d frame for (%s)\n", - // data_size, in_linesize, s->path); - int in_samples = avFrame->nb_samples; int out_linesize = 0; int max_out_samples = AUBIO_AVCODEC_MAX_BUFFER_SIZE; @@ -272,7 +258,44 @@ beach: av_free_packet(&avPacket); } +void aubio_source_avcodec_set_multi(aubio_source_avcodec_t * s, uint_t multi) { + if ( (multi != s->multi) || (s->avr == NULL) ) { + int64_t input_layout = av_get_default_channel_layout(s->input_channels); + int64_t mono_layout = av_get_default_channel_layout(1); + if (s->avr != NULL) { + avresample_close( s->avr ); + av_free ( s->avr ); + s->avr = NULL; + } + AVAudioResampleContext *avr = s->avr; + avr = avresample_alloc_context(); + + av_opt_set_int(avr, "in_channel_layout", input_layout, 0); + if (multi) { + av_opt_set_int(avr, "out_channel_layout", input_layout, 0); + } else { + av_opt_set_int(avr, "out_channel_layout", mono_layout, 0); + } + av_opt_set_int(avr, "in_sample_rate", s->input_samplerate, 0); + av_opt_set_int(avr, "out_sample_rate", s->samplerate, 0); + av_opt_set_int(avr, "in_sample_fmt", s->avCodecCtx->sample_fmt, 0); + av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); + int err; + if ( ( err = avresample_open(avr) ) < 0) { + char errorstr[256]; + av_strerror (err, errorstr, sizeof(errorstr)); + AUBIO_ERR("Could not open AVAudioResampleContext for %s (%s)\n", + s->path, errorstr); + //goto beach; + return; + } + s->avr = avr; + s->multi = multi; + } +} + void aubio_source_avcodec_do(aubio_source_avcodec_t * s, fvec_t * read_data, uint_t * read){ + if (s->multi == 1) aubio_source_avcodec_set_multi(s, 0); uint_t i; uint_t end = 0; uint_t total_wrote = 0; @@ -303,7 +326,39 @@ void aubio_source_avcodec_do(aubio_source_avcodec_t * s, fvec_t * read_data, uin } void aubio_source_avcodec_do_multi(aubio_source_avcodec_t * s, fmat_t * read_data, uint_t * read){ - //uint_t i,j, input_channels = s->input_channels; + if (s->multi == 0) aubio_source_avcodec_set_multi(s, 1); + uint_t i,j; + uint_t end = 0; + uint_t total_wrote = 0; + while (total_wrote < s->hop_size) { + end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote); + for (j = 0; j < read_data->height; j++) { + for (i = 0; i < end; i++) { + read_data->data[j][i + total_wrote] = + s->output[(i + s->read_index) * s->input_channels + j]; + } + } + total_wrote += end; + if (total_wrote < s->hop_size) { + uint_t avcodec_read = 0; + aubio_source_avcodec_readframe(s, &avcodec_read); + s->read_samples = avcodec_read; + s->read_index = 0; + if (s->eof) { + break; + } + } else { + s->read_index += end; + } + } + if (total_wrote < s->hop_size) { + for (j = 0; j < read_data->height; j++) { + for (i = end; i < s->hop_size; i++) { + read_data->data[j][i] = 0.; + } + } + } + *read = total_wrote; } uint_t aubio_source_avcodec_get_samplerate(aubio_source_avcodec_t * s) { @@ -316,7 +371,8 @@ uint_t aubio_source_avcodec_get_channels(aubio_source_avcodec_t * s) { uint_t aubio_source_avcodec_seek (aubio_source_avcodec_t * s, uint_t pos) { //uint_t resampled_pos = (uint_t)ROUND(pos * s->input_samplerate * 1. / s->samplerate); - return 0; //sf_seek (s->handle, resampled_pos, SEEK_SET); + AUBIO_ERR("Not implemented, _seek(%d) file %s", pos, s->path); + return -1; //sf_seek (s->handle, resampled_pos, SEEK_SET); } void del_aubio_source_avcodec(aubio_source_avcodec_t * s){ diff --git a/src/io/source_avcodec.h b/src/io/source_avcodec.h index d3344159..4374078f 100644 --- a/src/io/source_avcodec.h +++ b/src/io/source_avcodec.h @@ -64,7 +64,7 @@ aubio_source_avcodec_t * new_aubio_source_avcodec(char_t * uri, uint_t samplerat \param s source object, created with ::new_aubio_source_avcodec \param read_to ::fvec_t of data to read to - \param read upon returns, equals to number of frames actually read + \param[out] read upon returns, equals to number of frames actually read Upon returns, `read` contains the number of frames actually read from the source. `hop_size` if enough frames could be read, less otherwise. -- 2.11.0