diff --git a/src/AudioUtils.c b/src/AudioUtils.c deleted file mode 100644 index 2f14d85cec052e90e98667f7f3831e3c2d7393e3..0000000000000000000000000000000000000000 --- a/src/AudioUtils.c +++ /dev/null @@ -1,131 +0,0 @@ -#include "AudioUtils.hh" - -#include <assert.h> -#include <libavutil/opt.h> -#include <libavcodec/avcodec.h> -#include <libavformat/avformat.h> -#include <libswresample/swresample.h> -#include <libavcodec/avfft.h> - -#define MAXPIXVALUE 7 /* Some magix AV magic stuff */ - -int -decodeAudioFile(const char *path, const int sample_rate, double **const data, size_t *const size) -{ - AVPacket packet; - AVFormatContext *format = avformat_alloc_context(); - struct SwrContext *swr = swr_alloc(); - AVFrame *frame = av_frame_alloc(); - int ret_code = -1; - ssize_t stream_index = -1; - AVStream *stream = NULL; - AVCodecContext *codec_ctx = NULL; - AVCodecParameters *codec_par = NULL; - AVCodec *codec = NULL; - - if (!frame) { - fprintf(stderr, "Error allocating the frame\n"); - goto exit_error; - } - - /* Get format from audio file */ - if (avformat_open_input(&format, path, NULL, NULL) != 0) { - fprintf(stderr, "Could not open file '%s'\n", path); - goto exit_error; - } - if (avformat_find_stream_info(format, NULL) < 0) { - fprintf(stderr, "Could not retrieve stream info from file '%s'\n", path); - return -1; - } - - /* Find the index of the first audio stream */ - for (unsigned int i = 0; i < format->nb_streams; i++) { - codec = avcodec_find_encoder(format->streams[i]->codecpar->codec_id); - if (codec->type == AVMEDIA_TYPE_AUDIO) { - stream_index = i; - break; - } - } - if (stream_index == -1) { - fprintf(stderr, "Could not retrieve audio stream from file '%s'\n", path); - goto exit_error; - } - stream = format->streams[stream_index]; - - /* Find & open codec */ - codec_ctx = stream->codec; - codec_par = stream->codecpar; - codec = avcodec_find_decoder(codec_par->codec_id); - - if (codec == NULL) { - fprintf(stderr, "Failed to find decoder for stream #%zu in file '%s'\n", stream_index, - path); - goto exit_error; - } - - if (avcodec_open2(codec_ctx, codec, NULL) < 0) { - fprintf(stderr, "Failed to open decoder for stream #%zu in file '%s'\n", stream_index, - path); - goto exit_error; - } - - /* Prepare resampler */ - av_opt_set_int(swr, "in_channel_count", codec_ctx->channels, 0); - av_opt_set_int(swr, "out_channel_count", 1, 0); - av_opt_set_int(swr, "in_channel_layout", (int64_t)codec_ctx->channel_layout, 0); - av_opt_set_int(swr, "out_channel_layout", AV_CH_LAYOUT_MONO, 0); - av_opt_set_int(swr, "in_sample_rate", codec_ctx->sample_rate, 0); - av_opt_set_int(swr, "out_sample_rate", sample_rate, 0); - av_opt_set_sample_fmt(swr, "in_sample_fmt", codec_ctx->sample_fmt, 0); - av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_DBL, 0); - swr_init(swr); - if (!swr_is_initialized(swr)) { - fprintf(stderr, "Resampler has not been properly initialized\n"); - goto exit_error; - } - - /* Prepare to read data */ - av_init_packet(&packet); - - /* Iterate through frames */ - *data = NULL; - *size = 0; - while (av_read_frame(format, &packet) >= 0) { - /* Decode one frame */ - int gotFrame; - if (avcodec_decode_audio4(codec_ctx, frame, &gotFrame, &packet) < 0) { - break; - } - if (!gotFrame) { - continue; - } - - /* Resample frames */ - double *buffer; - av_samples_alloc((uint8_t **)&buffer, NULL, 1, frame->nb_samples, AV_SAMPLE_FMT_DBL, 0); - const int frame_count_int = swr_convert(swr, (uint8_t **)&buffer, frame->nb_samples, - (const uint8_t **)frame->data, frame->nb_samples); - assert(frame_count_int >= 0); - const size_t frame_count = (size_t)frame_count_int; - - /* Append resampled frames to data */ - *data = (double *)realloc(*data, (*size + (size_t)frame->nb_samples) * sizeof(double)); - memcpy(*data + *size, buffer, frame_count * sizeof(double)); - av_free(buffer); - *size += frame_count; - } - - /* Clean up */ - ret_code = 0; -exit_error: - if (frame != NULL) - av_frame_free(&frame); - if (swr != NULL) - swr_free(&swr); - if (codec_ctx != NULL) - avcodec_close(codec_ctx); - if (format != NULL) - avformat_free_context(format); - - return ret_code; -} diff --git a/src/AudioUtils.cc b/src/AudioUtils.cc index 187983c7eaa60f854b2fd28afddfa15c371f2272..fb65325d5b5c030c90d02b7ce1cfe550cb2634a2 100644 --- a/src/AudioUtils.cc +++ b/src/AudioUtils.cc @@ -40,10 +40,20 @@ DecoderOption::getDecalage() const noexcept RawImageData RawImageData::fromAudioFile(const DecoderOption &opt, const QString &path) { + auto avFrameDeleter = [](AVFrame *ptr) noexcept -> void { + if (ptr) + av_frame_free(&ptr); + }; + + auto swrContenxtDeleter = [](SwrContext *swr) noexcept -> void { + if (swr) + swr_free(&swr); + }; + AVPacket packet; - AVFormatContext *format = avformat_alloc_context(); - struct SwrContext *swr = swr_alloc(); - AVFrame *frame = av_frame_alloc(); + AVFormatContext *format = avformat_alloc_context(); + std::unique_ptr<SwrContext, decltype(swrContenxtDeleter)> swr(swr_alloc(), swrContenxtDeleter); + std::unique_ptr<AVFrame, decltype(avFrameDeleter)> frame(av_frame_alloc(), avFrameDeleter); ssize_t stream_index = -1; AVStream *stream = nullptr; AVCodecContext *codec_ctx = nullptr; @@ -98,16 +108,17 @@ RawImageData::fromAudioFile(const DecoderOption &opt, const QString &path) } /* Prepare resampler */ - av_opt_set_int(swr, "in_channel_count", codec_ctx->channels, 0); - av_opt_set_int(swr, "out_channel_count", 1, 0); - av_opt_set_int(swr, "in_channel_layout", static_cast<int64_t>(codec_ctx->channel_layout), 0); - av_opt_set_int(swr, "out_channel_layout", AV_CH_LAYOUT_MONO, 0); - av_opt_set_int(swr, "in_sample_rate", codec_ctx->sample_rate, 0); - av_opt_set_int(swr, "out_sample_rate", opt.getSampleRate(), 0); - av_opt_set_sample_fmt(swr, "in_sample_fmt", codec_ctx->sample_fmt, 0); - av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_DBL, 0); - swr_init(swr); - if (!swr_is_initialized(swr)) { + av_opt_set_int(swr.get(), "in_channel_count", codec_ctx->channels, 0); + av_opt_set_int(swr.get(), "out_channel_count", 1, 0); + av_opt_set_int(swr.get(), "in_channel_layout", static_cast<int64_t>(codec_ctx->channel_layout), + 0); + av_opt_set_int(swr.get(), "out_channel_layout", AV_CH_LAYOUT_MONO, 0); + av_opt_set_int(swr.get(), "in_sample_rate", codec_ctx->sample_rate, 0); + av_opt_set_int(swr.get(), "out_sample_rate", opt.getSampleRate(), 0); + av_opt_set_sample_fmt(swr.get(), "in_sample_fmt", codec_ctx->sample_fmt, 0); + av_opt_set_sample_fmt(swr.get(), "out_sample_fmt", AV_SAMPLE_FMT_DBL, 0); + swr_init(swr.get()); + if (!swr_is_initialized(swr.get())) { fprintf(stderr, "Resampler has not been properly initialized\n"); throw std::runtime_error("failed to initialize resampler"); } @@ -119,7 +130,7 @@ RawImageData::fromAudioFile(const DecoderOption &opt, const QString &path) while (av_read_frame(format, &packet) >= 0) { /* Decode one frame */ int gotFrame; - if (avcodec_decode_audio4(codec_ctx, frame, &gotFrame, &packet) < 0) { + if (avcodec_decode_audio4(codec_ctx, frame.get(), &gotFrame, &packet) < 0) { break; } if (!gotFrame) { @@ -129,7 +140,7 @@ RawImageData::fromAudioFile(const DecoderOption &opt, const QString &path) /* Resample frames */ double *buffer; av_samples_alloc((uint8_t **)&buffer, NULL, 1, frame->nb_samples, AV_SAMPLE_FMT_DBL, 0); - const int frame_count_int = swr_convert(swr, (uint8_t **)&buffer, frame->nb_samples, + const int frame_count_int = swr_convert(swr.get(), (uint8_t **)&buffer, frame->nb_samples, (const uint8_t **)frame->data, frame->nb_samples); assert(frame_count_int >= 0); const size_t frame_count = (size_t)frame_count_int; @@ -141,12 +152,6 @@ RawImageData::fromAudioFile(const DecoderOption &opt, const QString &path) size += frame_count; } - /* Clean up */ -exit_error: - if (frame != NULL) - av_frame_free(&frame); - if (swr != NULL) - swr_free(&swr); if (codec_ctx != NULL) avcodec_close(codec_ctx); if (format != NULL) diff --git a/src/AudioUtils.hh b/src/AudioUtils.hh index a8022c5675d2d86f0b588290935c290c03e0a79d..7953909bea91eb85b1eeec3c64033307458490a1 100644 --- a/src/AudioUtils.hh +++ b/src/AudioUtils.hh @@ -1,25 +1,17 @@ #ifndef VIVY_AUDIOUTILS_H #define VIVY_AUDIOUTILS_H -#ifdef __cplusplus -extern "C" { +#ifndef __cplusplus +#error "This is a C++ header" #endif +extern "C" { #include <libavutil/opt.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswresample/swresample.h> #include <libavcodec/avfft.h> - -int decodeAudioFile(const char *path, const int sample_rate, double **const data, - size_t *const size); - -#ifdef __cplusplus } -#endif - -/* C++ only code */ -#ifdef __cplusplus #include <QtGlobal> #include <memory.h> @@ -78,6 +70,4 @@ public: }; } -#endif - #endif // VIVY_AUDIOUTILS_H diff --git a/src/UI/AudioVisualizer.cc b/src/UI/AudioVisualizer.cc index 41b21aa973042babda524b3aeab2f7817add0189..ec0e03ffca181d91bbfb09388ac11df517c74207 100644 --- a/src/UI/AudioVisualizer.cc +++ b/src/UI/AudioVisualizer.cc @@ -31,23 +31,8 @@ AudioVisualizer::fromFile(const QString &filename) if (filename.isEmpty()) return nullptr; - const int sample_rate = 44100; - double *data = nullptr; - size_t size = 0; - int rc = decodeAudioFile(filename.toStdString().c_str(), sample_rate, &data, &size); - auto data_deleter = [](double *ptr) -> void { - if (ptr != nullptr) { - av_free(ptr); - } - }; - std::unique_ptr<double, decltype(data_deleter)> data_holder(data, data_deleter); - - if (rc != 0) { - printf("ERROR\n"); - return nullptr; - } - - Utils::RawImageData rawImage(Utils::DecoderOption{}, data, size); + Utils::RawImageData rawImage = + Utils::RawImageData::fromAudioFile(Utils::DecoderOption{}, filename); QImage img = QImage(rawImage.releasePixels(), rawImage.getWidth(), rawImage.getHeight(), rawImage.getWidth(), QImage::Format_Grayscale8, Utils::RawImageData::pixelsDeleter, rawImage.releasePixels())