C++ 如何使用QAudioOutput和QaudioCoder播放mp3文件?

C++ 如何使用QAudioOutput和QaudioCoder播放mp3文件?,c++,audio,mp3,qt5.6,C++,Audio,Mp3,Qt5.6,我想使用QAudioOutput将音频文件播放到指定的设备。可以使用.wav文件。但是播放.mp3文件时会有嗡嗡声(.mp3文件是我所知道的压缩文件,所以QAudioOutput不能直接播放)。 在使用QAudioOutput播放之前,我正在尝试解码.mp3文件,但我不知道如何解码。 您能给我一个示例代码,以便我们可以使用QAudioOutput和QaudioCoder播放mp3文件吗?有一个解决方案: 音频文件流.h #pragma once #include <QIODevice&g

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

有一个解决方案:

音频文件流.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);
};
#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;
}