1 | // Copyright (C) 2016 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef WAVEDECODER_H |
5 | #define WAVEDECODER_H |
6 | |
7 | #include <QtCore/qiodevice.h> |
8 | #include <QtMultimedia/qaudioformat.h> |
9 | |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | |
14 | |
15 | class Q_MULTIMEDIA_EXPORT QWaveDecoder : public QIODevice |
16 | { |
17 | Q_OBJECT |
18 | |
19 | public: |
20 | explicit QWaveDecoder(QIODevice *device, QObject *parent = nullptr); |
21 | explicit QWaveDecoder(QIODevice *device, const QAudioFormat &format, |
22 | QObject *parent = nullptr); |
23 | ~QWaveDecoder(); |
24 | |
25 | QAudioFormat audioFormat() const; |
26 | QIODevice* getDevice(); |
27 | int duration() const; |
28 | static qint64 headerLength(); |
29 | |
30 | bool open(QIODevice::OpenMode mode) override; |
31 | void close() override; |
32 | bool seek(qint64 pos) override; |
33 | qint64 pos() const override; |
34 | void setIODevice(QIODevice *device); |
35 | qint64 size() const override; |
36 | bool isSequential() const override; |
37 | qint64 bytesAvailable() const override; |
38 | |
39 | Q_SIGNALS: |
40 | void formatKnown(); |
41 | void parsingError(); |
42 | |
43 | private Q_SLOTS: |
44 | void handleData(); |
45 | |
46 | private: |
47 | qint64 readData(char *data, qint64 maxlen) override; |
48 | qint64 writeData(const char *data, qint64 len) override; |
49 | |
50 | bool writeHeader(); |
51 | bool writeDataLength(); |
52 | bool enoughDataAvailable(); |
53 | bool findChunk(const char *chunkId); |
54 | void discardBytes(qint64 numBytes); |
55 | void parsingFailed(); |
56 | |
57 | enum State { |
58 | InitialState, |
59 | WaitingForFormatState, |
60 | WaitingForDataState |
61 | }; |
62 | |
63 | struct chunk |
64 | { |
65 | char id[4]; // A four-character code that identifies the representation of the chunk data |
66 | // padded on the right with blank characters (ASCII 32) |
67 | quint32 size; // Does not include the size of the id or size fields or the pad byte at the end of payload |
68 | }; |
69 | |
70 | bool peekChunk(chunk* pChunk, bool handleEndianness = true); |
71 | |
72 | struct RIFFHeader |
73 | { |
74 | chunk descriptor; |
75 | char type[4]; |
76 | }; |
77 | struct WAVEHeader |
78 | { |
79 | chunk descriptor; |
80 | quint16 audioFormat; |
81 | quint16 numChannels; |
82 | quint32 sampleRate; |
83 | quint32 byteRate; |
84 | quint16 blockAlign; |
85 | quint16 bitsPerSample; |
86 | }; |
87 | |
88 | struct DATAHeader |
89 | { |
90 | chunk descriptor; |
91 | }; |
92 | |
93 | struct CombinedHeader |
94 | { |
95 | RIFFHeader riff; |
96 | WAVEHeader wave; |
97 | DATAHeader data; |
98 | }; |
99 | static const int HeaderLength = sizeof(CombinedHeader); |
100 | |
101 | bool haveFormat = false; |
102 | bool haveHeader = false; |
103 | qint64 dataSize = 0; |
104 | QIODevice *device = nullptr; |
105 | QAudioFormat format; |
106 | State state = InitialState; |
107 | quint32 junkToSkip = 0; |
108 | bool bigEndian = false; |
109 | bool byteSwap = false; |
110 | int bps = 0; |
111 | }; |
112 | |
113 | QT_END_NAMESPACE |
114 | |
115 | #endif // WAVEDECODER_H |
116 |