Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
1 résultat Searching

ProfilController.php

Blame
  • Audio.hh 4,84 Kio
    #pragma once
    
    #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>
    #include <memory.h>
    }
    
    #include "Utils.hh"
    #include <QtGlobal>
    #include <QMap>
    #include <QVector>
    #include <QString>
    
    namespace Vivy
    {
    class AudioContext;
    
    // The memory representation of an audio file. It is created inplace and should
    // not be moved around. It should be used to get the properties of an audio
    // file and its streams. The user can use a stream from the file and get data
    // from it.
    class AudioContext final {
        VIVY_UNMOVABLE_OBJECT(AudioContext)
    
    public:
        // Hold all the data for a stream in an audio file. Should only be owned by
        // the AudioContext class.
        class Stream final {
            VIVY_UNMOVABLE_OBJECT(Stream)
    
            static inline Utils::DeleterFunctionType<double> dataDeleter =
                std::bind_front(Utils::freePtrIfNotNull<double>, av_free);
    
            static inline Utils::DeleterFunctionType<AVCodecContext> codecContexteleter =
                std::bind_front(Utils::freePPtrIfNotNull<AVCodecContext>, avcodec_free_context);
    
            static inline Utils::DeleterFunctionType<AVFrame> avFrameDeleter =
                std::bind_front(Utils::freePPtrIfNotNull<AVFrame>, av_frame_free);
    
            static inline Utils::DeleterFunctionType<SwrContext> swrContenxtDeleter =
                std::bind_front(Utils::freePPtrIfNotNull<SwrContext>, swr_free);
    
            // All the used types
            using AVCodecContextPtr = std::unique_ptr<AVCodecContext, decltype(codecContexteleter)>;
            using DataPtr           = std::shared_ptr<double[]>;
            using AVFramePtr        = std::unique_ptr<AVFrame, decltype(avFrameDeleter)>;
            using SwrContextPtr     = std::unique_ptr<SwrContext, decltype(swrContenxtDeleter)>;
    
        public:
            Stream(AVCodec *, AVFormatContext *, AVStream *, int index);
            ~Stream() noexcept;
    
            // The non-owning view of the stream's data
            using DataWeakPtr = std::weak_ptr<double[]>;
    
            // Decode the stream
            void decodeData();
            void cleanUpData() noexcept;
            bool isDecoded() const noexcept;
            int getDataSampleRate() const noexcept;
            size_t getDecodedDataSize() const noexcept;
            size_t getDecodedChunkSize() const noexcept;
            size_t getDecodedDecalage() const noexcept;
            double *getDecodedData() const noexcept;
    
            // Some getters
            int getChannels() const noexcept;
            int getSampleRate() const noexcept;
            QString getName() const noexcept;
            AVCodecID getCodecId() const noexcept;
            qint64 getBitRate() const noexcept;
    
            // Get the index from the audio context
            int getStreamIndex() const noexcept;
    
            QJsonObject getProperties() const noexcept;
    
        private:
            // Codec related informations
            AVCodecID codecId{ AV_CODEC_ID_NONE };
            AVCodec *codec{ nullptr };
            AVCodecParameters *codecParams{ nullptr };
            AVCodecContextPtr codecContext{ nullptr };
    
            // Stream is held by AudioContext
            AVStream *audioStream{ nullptr };
    
            // Store the index of this stream
            int streamIndexInAudioContext;
    
            // Resampled frame data
            AVFormatContext *dataFormat;
            SwrContextPtr dataSwrContext{ swr_alloc(), swrContenxtDeleter };
            AVFramePtr dataFrame{ av_frame_alloc(), avFrameDeleter };
            double *dataPtr{ nullptr };
            size_t dataSize{ 0 };
    
            // Constants for the resampler
            static constexpr uint resamplerChunkSize  = 512;
            static constexpr uint resamplerOverlap    = 128;
            static constexpr uint resamplerDecalage   = resamplerChunkSize - resamplerOverlap;
            static constexpr uint resamplerSampleRate = 44100;
        };
    
        using StreamPtr     = std::shared_ptr<Stream>;
        using StreamWeakPtr = std::weak_ptr<Stream>;
    
    public:
        AudioContext(const QString &path);
    
        StreamWeakPtr getStream(int) const noexcept;
        StreamWeakPtr getDefaultStream() const noexcept;
    
        QString getElementName() const noexcept;
        QJsonDocument getProperties() const noexcept;
    
    private:
        // Regarding the format
        static inline Utils::DeleterFunctionType<AVFormatContext> avFormatContextDeleter =
            std::bind_front(Utils::freePtrIfNotNull<AVFormatContext>, avformat_free_context);
    
        using AVFormatContextPtr = std::unique_ptr<AVFormatContext, decltype(avFormatContextDeleter)>;
        AVFormatContextPtr format{ avformat_alloc_context(), avFormatContextDeleter };
    
        const QString filePath;               // Usefull information
        QMap<uint, StreamPtr> audioStreams{}; // THe audio streams of the file
    
        int defaultStreamIndex{ -1 };
    
        // Spare always null shared pointer, to be used when the audioStream[i] was
        // not found.
        StreamPtr spareNullSreamPtr{ nullptr };
    };
    }