File: AudioDecoder.cpp

package info (click to toggle)
js8call 2.2.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 22,416 kB
  • sloc: cpp: 563,285; f90: 9,265; ansic: 937; python: 132; sh: 93; makefile: 6
file content (119 lines) | stat: -rw-r--r-- 2,804 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "AudioDecoder.h"

AudioDecoder::AudioDecoder(QObject *parent) :
    QIODevice(parent),
    m_state { AudioDecoder::Stopped },
    m_input { &m_data, this },
    m_output { &m_data, this },
    m_init { false },
    m_isDecodingFinished { false }
{
    setOpenMode(QIODevice::ReadOnly);

    m_decoder = new QAudioDecoder(this);
    connect(m_decoder, &QAudioDecoder::bufferReady, this, &AudioDecoder::bufferReady);
    connect(m_decoder, static_cast<void(QAudioDecoder::*)(QAudioDecoder::Error)>(&QAudioDecoder::error), this, &AudioDecoder::errored);
    connect(m_decoder, &QAudioDecoder::finished, this, &AudioDecoder::finished);
}

AudioDecoder::~AudioDecoder(){
    stop();
}

// initialize an audio device
void AudioDecoder::init(const QAudioFormat &format) {
    m_decoder->setAudioFormat(format);

    if (!m_output.open(QIODevice::ReadOnly) || !m_input.open(QIODevice::WriteOnly)){
        m_init = false;
        return;
    }

    m_init = true;
    emit initialized();
}

// play an audio file
void AudioDecoder::start(const QString &filePath){
    if(!m_init){
        return;
    }

    if(m_state == AudioDecoder::Decoding){
        return;
    }

    m_state = AudioDecoder::Decoding;
    m_decoder->setSourceFilename(filePath);
    m_decoder->start();
}

// Stop playing audio
void AudioDecoder::stop() {
    m_state = AudioDecoder::Stopped;
    m_decoder->stop();
    m_data.clear();
    m_isDecodingFinished = false;
}


// io device, read into buffer.
qint64 AudioDecoder::readData(char* data, qint64 maxlen) {
    memset(data, 0, maxlen);

    if (m_state == AudioDecoder::Decoding){
        m_output.read(data, maxlen);

        // Emulate QAudioProbe behaviour for audio data that is sent to output device
        if (maxlen > 0){
            QByteArray buff(data, maxlen);
            emit newData(buff);
        }

        // Is finish of file
        if (atEnd()){
            stop();
        }
    }

    return maxlen;
}

// io device, unused.
qint64 AudioDecoder::writeData(const char* data, qint64 len) {
    Q_UNUSED(data);
    Q_UNUSED(len);

    return 0;
}

// io device, at end of device
bool AudioDecoder::atEnd() const {
    bool value = m_output.size()
        && m_output.atEnd()
        && m_isDecodingFinished;
    return value;
}

// handle buffered data ready
void AudioDecoder::bufferReady() {
    const QAudioBuffer &buffer = m_decoder->read();
    if(!buffer.isValid()){
        return;
    }

    const int length = buffer.byteCount();
    const char *data = buffer.constData<char>();

    m_input.write(data, length);
}

// handle buffered data decoding is finished
void AudioDecoder::finished() {
    m_isDecodingFinished = true;
}

// handle buffered data decoding error
void AudioDecoder::errored(QAudioDecoder::Error /*error*/) {
    stop();
}