Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwavedecoder.cpp
Go to the documentation of this file.
1
// Copyright (C) 2021 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
// Qt-Security score:critical reason:data-parser
4
5
#
include
"qwavedecoder.h"
6
7
#
include
<
QtCore
/
qdebug
.
h
>
8
#
include
<
QtCore
/
qendian
.
h
>
9
#
include
<
QtCore
/
qtimer
.
h
>
10
11
#
include
<
limits
.
h
>
12
13
QT_BEGIN_NAMESPACE
14
15
#
if
QT_DEPRECATED_SINCE
(
6
,
11
)
16
17
QWaveDecoder
::
QWaveDecoder
(
QIODevice
*
device
,
QObject
*
parent
)
18
:
QIODevice
(
parent
),
19
device
(
device
)
20
{
21
}
22
23
QWaveDecoder
::
QWaveDecoder
(
QIODevice
*
device
,
const
QAudioFormat
&
format
,
QObject
*
parent
)
24
:
QIODevice
(
parent
),
25
device
(
device
),
26
format
(
format
)
27
{
28
}
29
30
QWaveDecoder
::~
QWaveDecoder
() =
default
;
31
32
bool
QWaveDecoder
::
open
(
QIODevice
::
OpenMode
mode
)
33
{
34
bool
canOpen
=
false
;
35
if
(
mode
&
QIODevice
::
ReadOnly
&&
mode
& ~
QIODevice
::
WriteOnly
) {
36
canOpen
=
QIODevice
::
open
(
mode
|
QIODevice
::
Unbuffered
);
37
if
(
canOpen
&&
enoughDataAvailable
())
38
handleData
();
39
else
40
connect
(
device
, &
QIODevice
::
readyRead
,
this
, &
QWaveDecoder
::
handleData
);
41
return
canOpen
;
42
}
43
44
if
(
mode
&
QIODevice
::
WriteOnly
) {
45
if
(
format
.
sampleFormat
() !=
QAudioFormat
::
Int16
)
46
return
false
;
// data format is not supported
47
canOpen
=
QIODevice
::
open
(
mode
);
48
if
(
canOpen
&&
writeHeader
())
49
haveHeader
=
true
;
50
return
canOpen
;
51
}
52
return
QIODevice
::
open
(
mode
);
53
}
54
55
void
QWaveDecoder
::
close
()
56
{
57
if
(
isOpen
() && (
openMode
() &
QIODevice
::
WriteOnly
)) {
58
Q_ASSERT
(
dataSize
<
INT_MAX
);
59
if
(!
device
->
isOpen
() || !
writeDataLength
())
60
qWarning
() <<
"Failed to finalize wav file"
;
61
}
62
QIODevice
::
close
();
63
}
64
65
bool
QWaveDecoder
::
seek
(
qint64
pos
)
66
{
67
return
device
->
seek
(
pos
);
68
}
69
70
qint64
QWaveDecoder
::
pos
()
const
71
{
72
return
device
->
pos
();
73
}
74
75
void
QWaveDecoder
::
setIODevice
(
QIODevice
*
/* device */
)
76
{
77
}
78
79
QAudioFormat
QWaveDecoder
::
audioFormat
()
const
80
{
81
return
format
;
82
}
83
84
QIODevice
*
QWaveDecoder
::
getDevice
()
85
{
86
return
device
;
87
}
88
89
int
QWaveDecoder
::
duration
()
const
90
{
91
if
(
openMode
() &
QIODevice
::
WriteOnly
)
92
return
0;
93
int
bytesPerSec
=
format
.
bytesPerFrame
() *
format
.
sampleRate
();
94
return
bytesPerSec
?
size
() * 1000 /
bytesPerSec
: 0;
95
}
96
97
qint64
QWaveDecoder
::
size
()
const
98
{
99
if
(
openMode
() &
QIODevice
::
ReadOnly
) {
100
if
(!
haveFormat
)
101
return
0;
102
if
(
bps
== 24)
103
return
dataSize
*2/3;
104
return
dataSize
;
105
}
else
{
106
return
device
->
size
();
107
}
108
}
109
110
bool
QWaveDecoder
::
isSequential
()
const
111
{
112
return
device
->
isSequential
();
113
}
114
115
qint64
QWaveDecoder
::
bytesAvailable
()
const
116
{
117
return
haveFormat
?
device
->
bytesAvailable
() : 0;
118
}
119
120
qint64
QWaveDecoder
::
headerLength
()
121
{
122
return
HeaderLength
;
123
}
124
125
qint64
QWaveDecoder
::
readData
(
char
*
data
,
qint64
maxlen
)
126
{
127
const
int
bytesPerSample
=
format
.
bytesPerSample
();
128
if
(!
haveFormat
||
bytesPerSample
== 0)
129
return
0;
130
131
if
(
bps
== 24) {
132
// 24 bit WAV, read in as 16 bit
133
qint64
l
= 0;
134
while
(
l
<
maxlen
- 1) {
135
char
tmp
[3];
136
device
->
read
(
tmp
, 3);
137
if
(
byteSwap
)
138
qSwap
(
tmp
[0],
tmp
[2]);
139
#
if
Q_BYTE_ORDER
==
Q_BIG_ENDIAN
140
data
[0] =
tmp
[0];
141
data
[1] =
tmp
[1];
142
#
else
143
data
[0] =
tmp
[1];
144
data
[1] =
tmp
[2];
145
#
endif
146
data
+= 2;
147
l
+= 2;
148
}
149
return
l
;
150
}
151
152
qint64
nSamples
=
maxlen
/
bytesPerSample
;
153
maxlen
=
nSamples
*
bytesPerSample
;
154
int
read
=
device
->
read
(
data
,
maxlen
);
155
156
if
(!
byteSwap
||
format
.
bytesPerFrame
() == 1)
157
return
read
;
158
159
nSamples
=
read
/
bytesPerSample
;
160
switch
(
bytesPerSample
) {
161
case
2:
162
qbswap
<2>(
data
,
nSamples
,
data
);
163
break
;
164
case
4:
165
qbswap
<4>(
data
,
nSamples
,
data
);
166
break
;
167
default
:
168
Q_UNREACHABLE
();
169
}
170
return
read
;
171
172
}
173
174
qint64
QWaveDecoder
::
writeData
(
const
char
*
data
,
qint64
len
)
175
{
176
if
(!
haveHeader
)
177
return
0;
178
qint64
written
=
device
->
write
(
data
,
len
);
179
dataSize
+=
written
;
180
return
written
;
181
}
182
183
bool
QWaveDecoder
::
writeHeader
()
184
{
185
if
(
device
->
size
() != 0)
186
return
false
;
187
188
#
ifndef
Q_LITTLE_ENDIAN
189
// only implemented for LITTLE ENDIAN
190
return
false
;
191
#
endif
192
193
CombinedHeader
header
;
194
195
memset
(&
header
, 0,
HeaderLength
);
196
197
// RIFF header
198
memcpy
(
header
.
riff
.
descriptor
.
id
,
"RIFF"
,4);
199
qToLittleEndian
<
quint32
>(
quint32
(
dataSize
+
HeaderLength
- 8),
200
reinterpret_cast
<
unsigned
char
*>(&
header
.
riff
.
descriptor
.
size
));
201
memcpy
(
header
.
riff
.
type
,
"WAVE"
,4);
202
203
// WAVE header
204
memcpy
(
header
.
wave
.
descriptor
.
id
,
"fmt "
,4);
205
qToLittleEndian
<
quint32
>(
quint32
(16),
206
reinterpret_cast
<
unsigned
char
*>(&
header
.
wave
.
descriptor
.
size
));
207
qToLittleEndian
<
quint16
>(
quint16
(1),
208
reinterpret_cast
<
unsigned
char
*>(&
header
.
wave
.
audioFormat
));
209
qToLittleEndian
<
quint16
>(
quint16
(
format
.
channelCount
()),
210
reinterpret_cast
<
unsigned
char
*>(&
header
.
wave
.
numChannels
));
211
qToLittleEndian
<
quint32
>(
quint32
(
format
.
sampleRate
()),
212
reinterpret_cast
<
unsigned
char
*>(&
header
.
wave
.
sampleRate
));
213
qToLittleEndian
<
quint32
>(
quint32
(
format
.
sampleRate
() *
format
.
bytesPerFrame
()),
214
reinterpret_cast
<
unsigned
char
*>(&
header
.
wave
.
byteRate
));
215
qToLittleEndian
<
quint16
>(
quint16
(
format
.
channelCount
() *
format
.
bytesPerSample
()),
216
reinterpret_cast
<
unsigned
char
*>(&
header
.
wave
.
blockAlign
));
217
qToLittleEndian
<
quint16
>(
quint16
(
format
.
bytesPerSample
() * 8),
218
reinterpret_cast
<
unsigned
char
*>(&
header
.
wave
.
bitsPerSample
));
219
220
// DATA header
221
memcpy
(
header
.
data
.
descriptor
.
id
,
"data"
,4);
222
qToLittleEndian
<
quint32
>(
quint32
(
dataSize
),
223
reinterpret_cast
<
unsigned
char
*>(&
header
.
data
.
descriptor
.
size
));
224
225
return
device
->
write
(
reinterpret_cast
<
const
char
*>(&
header
),
HeaderLength
);
226
}
227
228
bool
QWaveDecoder
::
writeDataLength
()
229
{
230
#
ifndef
Q_LITTLE_ENDIAN
231
// only implemented for LITTLE ENDIAN
232
return
false
;
233
#
endif
234
235
if
(
isSequential
())
236
return
false
;
237
238
// seek to RIFF header size, see header.riff.descriptor.size above
239
if
(!
device
->
seek
(4)) {
240
qDebug
() <<
"can't seek"
;
241
return
false
;
242
}
243
244
quint32
length
=
dataSize
+
HeaderLength
- 8;
245
if
(
device
->
write
(
reinterpret_cast
<
const
char
*>(&
length
), 4) != 4)
246
return
false
;
247
248
// seek to DATA header size, see header.data.descriptor.size above
249
if
(!
device
->
seek
(40))
250
return
false
;
251
252
return
device
->
write
(
reinterpret_cast
<
const
char
*>(&
dataSize
), 4);
253
}
254
255
void
QWaveDecoder
::
parsingFailed
()
256
{
257
Q_ASSERT
(
device
);
258
disconnect
(
device
, &
QIODevice
::
readyRead
,
this
, &
QWaveDecoder
::
handleData
);
259
emit
parsingError
();
260
}
261
262
void
QWaveDecoder
::
handleData
()
263
{
264
if
(
openMode
() ==
QIODevice
::
WriteOnly
)
265
return
;
266
267
// As a special "state", if we have junk to skip, we do
268
if
(
junkToSkip
> 0) {
269
discardBytes
(
junkToSkip
);
// this also updates junkToSkip
270
271
// If we couldn't skip all the junk, return
272
if
(
junkToSkip
> 0) {
273
// We might have run out
274
if
(
device
->
atEnd
())
275
parsingFailed
();
276
return
;
277
}
278
}
279
280
if
(
state
==
QWaveDecoder
::
InitialState
) {
281
if
(
device
->
bytesAvailable
() <
qint64
(
sizeof
(
RIFFHeader
)))
282
return
;
283
284
RIFFHeader
riff
;
285
device
->
read
(
reinterpret_cast
<
char
*>(&
riff
),
sizeof
(
RIFFHeader
));
286
287
// RIFF = little endian RIFF, RIFX = big endian RIFF
288
if
(((
qstrncmp
(
riff
.
descriptor
.
id
,
"RIFF"
, 4) != 0) && (
qstrncmp
(
riff
.
descriptor
.
id
,
"RIFX"
, 4) != 0))
289
||
qstrncmp
(
riff
.
type
,
"WAVE"
, 4) != 0) {
290
parsingFailed
();
291
return
;
292
}
293
294
state
=
QWaveDecoder
::
WaitingForFormatState
;
295
bigEndian
= (
qstrncmp
(
riff
.
descriptor
.
id
,
"RIFX"
, 4) == 0);
296
byteSwap
= (
bigEndian
!= (
QSysInfo
::
ByteOrder
==
QSysInfo
::
BigEndian
));
297
}
298
299
if
(
state
==
QWaveDecoder
::
WaitingForFormatState
) {
300
if
(
findChunk
(
"fmt "
)) {
301
chunk
descriptor
;
302
const
bool
peekSuccess
=
peekChunk
(&
descriptor
);
303
Q_ASSERT
(
peekSuccess
);
304
305
quint32
rawChunkSize
=
descriptor
.
size
+
sizeof
(
chunk
);
306
if
(
device
->
bytesAvailable
() <
qint64
(
rawChunkSize
))
307
return
;
308
309
WAVEHeader
wave
;
310
device
->
read
(
reinterpret_cast
<
char
*>(&
wave
),
sizeof
(
WAVEHeader
));
311
312
if
(
rawChunkSize
>
sizeof
(
WAVEHeader
))
313
discardBytes
(
rawChunkSize
-
sizeof
(
WAVEHeader
));
314
315
// Swizzle this
316
if
(
bigEndian
) {
317
wave
.
audioFormat
=
qFromBigEndian
<
quint16
>(
wave
.
audioFormat
);
318
}
else
{
319
wave
.
audioFormat
=
qFromLittleEndian
<
quint16
>(
wave
.
audioFormat
);
320
}
321
322
if
(
wave
.
audioFormat
!= 0 &&
wave
.
audioFormat
!= 1) {
323
// 32bit wave files have format == 0xFFFE (WAVE_FORMAT_EXTENSIBLE).
324
// but don't support them at the moment.
325
parsingFailed
();
326
return
;
327
}
328
329
int
rate
;
330
int
channels
;
331
if
(
bigEndian
) {
332
bps
=
qFromBigEndian
<
quint16
>(
wave
.
bitsPerSample
);
333
rate
=
qFromBigEndian
<
quint32
>(
wave
.
sampleRate
);
334
channels
=
qFromBigEndian
<
quint16
>(
wave
.
numChannels
);
335
}
else
{
336
bps
=
qFromLittleEndian
<
quint16
>(
wave
.
bitsPerSample
);
337
rate
=
qFromLittleEndian
<
quint32
>(
wave
.
sampleRate
);
338
channels
=
qFromLittleEndian
<
quint16
>(
wave
.
numChannels
);
339
}
340
341
QAudioFormat
::
SampleFormat
fmt
=
QAudioFormat
::
Unknown
;
342
switch
(
bps
) {
343
case
8:
344
fmt
=
QAudioFormat
::
UInt8
;
345
break
;
346
case
16:
347
fmt
=
QAudioFormat
::
Int16
;
348
break
;
349
case
24:
350
fmt
=
QAudioFormat
::
Int16
;
351
break
;
352
case
32:
353
fmt
=
QAudioFormat
::
Int32
;
354
break
;
355
}
356
if
(
fmt
==
QAudioFormat
::
Unknown
||
rate
== 0 ||
channels
== 0) {
357
parsingFailed
();
358
return
;
359
}
360
361
format
.
setSampleFormat
(
fmt
);
362
format
.
setSampleRate
(
rate
);
363
format
.
setChannelCount
(
channels
);
364
365
state
=
QWaveDecoder
::
WaitingForDataState
;
366
}
367
}
368
369
if
(
state
==
QWaveDecoder
::
WaitingForDataState
) {
370
if
(
findChunk
(
"data"
)) {
371
disconnect
(
device
, &
QIODevice
::
readyRead
,
this
, &
QWaveDecoder
::
handleData
);
372
373
chunk
descriptor
;
374
device
->
read
(
reinterpret_cast
<
char
*>(&
descriptor
),
sizeof
(
chunk
));
375
if
(
bigEndian
)
376
descriptor
.
size
=
qFromBigEndian
<
quint32
>(
descriptor
.
size
);
377
else
378
descriptor
.
size
=
qFromLittleEndian
<
quint32
>(
descriptor
.
size
);
379
380
dataSize
=
descriptor
.
size
;
//means the data size from the data header, not the actual file size
381
if
(!
dataSize
)
382
dataSize
=
device
->
size
() -
headerLength
();
383
384
haveFormat
=
true
;
385
connect
(
device
, &
QIODevice
::
readyRead
,
this
, &
QIODevice
::
readyRead
);
386
emit
formatKnown
();
387
388
return
;
389
}
390
}
391
392
// If we hit the end without finding data, it's a parsing error
393
if
(
device
->
atEnd
()) {
394
parsingFailed
();
395
}
396
}
397
398
bool
QWaveDecoder
::
enoughDataAvailable
()
399
{
400
chunk
descriptor
;
401
if
(!
peekChunk
(&
descriptor
,
false
))
402
return
false
;
403
404
// This is only called for the RIFF/RIFX header, before bigEndian is set,
405
// so we have to manually swizzle
406
if
(
qstrncmp
(
descriptor
.
id
,
"RIFX"
, 4) == 0)
407
descriptor
.
size
=
qFromBigEndian
<
quint32
>(
descriptor
.
size
);
408
if
(
qstrncmp
(
descriptor
.
id
,
"RIFF"
, 4) == 0)
409
descriptor
.
size
=
qFromLittleEndian
<
quint32
>(
descriptor
.
size
);
410
411
if
(
device
->
bytesAvailable
() <
qint64
(
sizeof
(
chunk
)) +
descriptor
.
size
)
412
return
false
;
413
414
return
true
;
415
}
416
417
bool
QWaveDecoder
::
findChunk
(
const
char
*
chunkId
)
418
{
419
chunk
descriptor
;
420
421
do
{
422
if
(!
peekChunk
(&
descriptor
))
423
return
false
;
424
425
if
(
qstrncmp
(
descriptor
.
id
,
chunkId
, 4) == 0)
426
return
true
;
427
428
// A program reading a RIFF file can skip over any chunk whose chunk
429
// ID it doesn't recognize; it simply skips the number of bytes specified
430
// by ckSize plus the pad byte, if present. See Multimedia Programming
431
// Interface and Data Specifications 1.0. IBM / Microsoft. August 1991. pp. 10-11.
432
const
quint32
sizeWithPad
=
descriptor
.
size
+ (
descriptor
.
size
& 1);
433
434
// It's possible that bytes->available() is less than the chunk size
435
// if it's corrupt.
436
junkToSkip
=
qint64
(
sizeof
(
chunk
) +
sizeWithPad
);
437
438
// Skip the current amount
439
if
(
junkToSkip
> 0)
440
discardBytes
(
junkToSkip
);
441
442
// If we still have stuff left, just exit and try again later
443
// since we can't call peekChunk
444
if
(
junkToSkip
> 0)
445
return
false
;
446
447
}
while
(
device
->
bytesAvailable
() > 0);
448
449
return
false
;
450
}
451
452
bool
QWaveDecoder
::
peekChunk
(
chunk
*
pChunk
,
bool
handleEndianness
)
453
{
454
if
(
device
->
bytesAvailable
() <
qint64
(
sizeof
(
chunk
)))
455
return
false
;
456
457
if
(!
device
->
peek
(
reinterpret_cast
<
char
*>(
pChunk
),
sizeof
(
chunk
)))
458
return
false
;
459
460
if
(
handleEndianness
) {
461
if
(
bigEndian
)
462
pChunk
->
size
=
qFromBigEndian
<
quint32
>(
pChunk
->
size
);
463
else
464
pChunk
->
size
=
qFromLittleEndian
<
quint32
>(
pChunk
->
size
);
465
}
466
return
true
;
467
}
468
469
void
QWaveDecoder
::
discardBytes
(
qint64
numBytes
)
470
{
471
// Discards a number of bytes
472
// If the iodevice doesn't have this many bytes in it,
473
// remember how much more junk we have to skip.
474
if
(
device
->
isSequential
()) {
475
QByteArray
r
=
device
->
read
(
qMin
(
numBytes
,
qint64
(16384)));
// uggh, wasted memory, limit to a max of 16k
476
if
(
r
.
size
() <
numBytes
)
477
junkToSkip
=
numBytes
-
r
.
size
();
478
else
479
junkToSkip
= 0;
480
}
else
{
481
quint64
origPos
=
device
->
pos
();
482
device
->
seek
(
device
->
pos
() +
numBytes
);
483
junkToSkip
=
origPos
+
numBytes
-
device
->
pos
();
484
}
485
}
486
487
#
endif
// QT_DEPRECATED_SINCE(6, 11)
488
489
QT_END_NAMESPACE
490
491
#
include
"moc_qwavedecoder.cpp"
QSqlRelationalDelegate
\inmodule QtSql
qtmultimedia
src
multimedia
audio
qwavedecoder.cpp
Generated on
for Qt by
1.16.1