【问题标题】:How to play mp3 file using QAudioOutput and QAudioDecoder?如何使用 QAudioOutput 和 QAudioDecoder 播放 mp3 文件?
【发布时间】:2017-05-03 00:40:45
【问题描述】:

我想使用 QAudioOutput 将音频文件播放到指定设备。 .wav 文件没问题。但是播放.mp3文件时只是嗡嗡声(.mp3文件我知道是压缩文件,所以QAudioOutput不能直接播放)。
我正在尝试在使用 QAudioOutput 之前解码 .mp3 文件,但我不知道如何。
你能给我一个示例代码,以便我们可以使用 QAudioOutput 和 QAudioDecoder 播放 mp3 文件吗?

【问题讨论】:

    标签: c++ audio mp3 qt5.6


    【解决方案1】:

    有解决办法:

    AudioFileStream.h

    #pragma once
    
    #include <QIODevice>
    #include <QBuffer>
    #include <QAudioDecoder>
    #include <QAudioFormat>
    #include <QFile>
    
    // Class for decode audio files like MP3 and push decoded audio data to QOutputDevice (like speaker) and also signal newData().
    // For decoding it uses QAudioDecoder which uses QAudioFormat for decode audio file for desire format, then put decoded data to buffer.
    // based on: https://github.com/Znurre/QtMixer
    class AudioFileStream : public QIODevice
    {
        Q_OBJECT
    
    public:
        AudioFileStream();
        bool init(const QAudioFormat& format);
    
        enum State { Playing, Stopped };
    
        void play(const QString &filePath);
        void stop();
    
        bool atEnd() const override;
    
    protected:
        qint64 readData(char* data, qint64 maxlen) override;
        qint64 writeData(const char* data, qint64 len) override;
    
    private:
        QFile m_file;
        QBuffer m_input;
        QBuffer m_output;
        QByteArray m_data;
        QAudioDecoder m_decoder;
        QAudioFormat m_format;
    
        State m_state;
    
        bool isInited;
        bool isDecodingFinished;
    
        void clear();
    
    private slots:
        void bufferReady();
        void finished();
    
    signals:
        void stateChanged(AudioFileStream::State state);
        void newData(const QByteArray& data);
    };
    

    AudioFileStream.cpp

    #include "AudioFileStream.h"
    
    AudioFileStream::AudioFileStream() :
        m_input(&m_data),
        m_output(&m_data),
        m_state(State::Stopped)
    {
        setOpenMode(QIODevice::ReadOnly);
    
        isInited = false;
        isDecodingFinished = false;
    }
    
    // format - it is audio format to which we whant decode audio data
    bool AudioFileStream::init(const QAudioFormat& format)
    {
        m_format = format;
        m_decoder.setAudioFormat(m_format);
    
        connect(&m_decoder, SIGNAL(bufferReady()), this, SLOT(bufferReady()));
        connect(&m_decoder, SIGNAL(finished()), this, SLOT(finished()));
    
        // Initialize buffers
        if (!m_output.open(QIODevice::ReadOnly) || !m_input.open(QIODevice::WriteOnly))
        {
            return false;
        }
    
        isInited = true;
    
        return true;
    }
    
    // AudioOutput device (like speaker) call this function for get new audio data
    qint64 AudioFileStream::readData(char* data, qint64 maxlen)
    {
        memset(data, 0, maxlen);
    
        if (m_state == State::Playing)
        {
            m_output.read(data, maxlen);
    
            // There is we send readed audio data via signal, for ability get audio signal for the who listen this signal.
            // Other word this emulate QAudioProbe behaviour for retrieve audio data which of sent to output device (speaker).
            if (maxlen > 0)
            {
                QByteArray buff(data, maxlen);
                emit newData(buff);
            }
    
            // Is finish of file
            if (atEnd())
            {
                stop();
            }
        }
    
        return maxlen;
    }
    
    qint64 AudioFileStream::writeData(const char* data, qint64 len)
    {
        Q_UNUSED(data);
        Q_UNUSED(len);
    
        return 0;
    }
    
    // Start play audio file
    void AudioFileStream::play(const QString &filePath)
    {
        clear();
    
        m_file.setFileName(filePath);
    
        if (!m_file.open(QIODevice::ReadOnly))
        {
            return;
        }
    
        m_decoder.setSourceDevice(&m_file);
        m_decoder.start();
    
        m_state = State::Playing;
        emit stateChanged(m_state);
    }
    
    // Stop play audio file
    void AudioFileStream::stop()
    {
        clear();
        m_state = State::Stopped;
        emit stateChanged(m_state);
    }
    
    
    void AudioFileStream::clear()
    {
        m_decoder.stop();
        m_data.clear();
        isDecodingFinished = false;
    }
    
    // Is finish of file
    bool AudioFileStream::atEnd() const
    {
        return m_output.size()
            && m_output.atEnd()
            && isDecodingFinished;
    }
    
    
    
    /////////////////////////////////////////////////////////////////////
    // QAudioDecoder logic this methods responsible for decode audio file and put audio data to stream buffer
    
    // Run when decode decoded some audio data
    void AudioFileStream::bufferReady() // SLOT
    {
        const QAudioBuffer &buffer = m_decoder.read();
    
        const int length = buffer.byteCount();
        const char *data = buffer.constData<char>();
    
        m_input.write(data, length);
    }
    
    // Run when decode finished decoding
    void AudioFileStream::finished() // SLOT
    {
        isDecodingFinished = true;
    }
    
    
    /////////////////////////////////////////////////////////////////////
    

    使用方法:

    void init()
    {
        QAudioDeviceInfo device = QAudioDeviceInfo::defaultOutputDevice();
        QAudioFormat desire_audio_romat = device.preferredFormat();
    
        m_audioFileStream = new AudioFileStream;
        if (!m_audioFileStream->init(desire_audio_romat))
        {
            return false;
        }
    
        QAudioOutput* m_audioOutput = new QAudioOutput(desire_audio_romat);
        m_audioOutput->start(m_audioFileStream);
    }
    
    void play()
    {
        m_audioFileStream->play("C:/file.mp3");
    }
    
    void stop()
    {
        m_audioFileStream->stop;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-30
      • 2011-01-30
      • 2012-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多