1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qaudiobuffer.h"
41#include "qaudiobuffer_p.h"
42
43#include <QObject>
44#include <QDebug>
45
46QT_BEGIN_NAMESPACE
47
48
49static void qRegisterAudioBufferMetaTypes()
50{
51 qRegisterMetaType<QAudioBuffer>();
52}
53
54Q_CONSTRUCTOR_FUNCTION(qRegisterAudioBufferMetaTypes)
55
56
57class QAudioBufferPrivate : public QSharedData
58{
59public:
60 QAudioBufferPrivate(QAbstractAudioBuffer *provider)
61 : mProvider(provider)
62 , mCount(1)
63 {
64 }
65
66 ~QAudioBufferPrivate()
67 {
68 if (mProvider)
69 mProvider->release();
70 }
71
72 void ref()
73 {
74 mCount.ref();
75 }
76
77 void deref()
78 {
79 if (!mCount.deref())
80 delete this;
81 }
82
83 QAudioBufferPrivate *clone();
84
85 static QAudioBufferPrivate *acquire(QAudioBufferPrivate *other)
86 {
87 if (!other)
88 return nullptr;
89
90 // Ref the other (if there are extant data() pointers, they will
91 // also point here - it's a feature, not a bug, like QByteArray)
92 other->ref();
93 return other;
94 }
95
96 QAbstractAudioBuffer *mProvider;
97 QAtomicInt mCount;
98};
99
100// Private class to go in .cpp file
101class QMemoryAudioBufferProvider : public QAbstractAudioBuffer {
102public:
103 QMemoryAudioBufferProvider(const void *data, int frameCount, const QAudioFormat &format, qint64 startTime)
104 : mStartTime(startTime)
105 , mFrameCount(frameCount)
106 , mFormat(format)
107 {
108 int numBytes = format.bytesForFrames(frameCount);
109 if (numBytes > 0) {
110 mBuffer = malloc(size: numBytes);
111 if (!mBuffer) {
112 // OOM, if that's likely
113 mStartTime = -1;
114 mFrameCount = 0;
115 mFormat = QAudioFormat();
116 } else {
117 // Allocated, see if we have data to copy
118 if (data) {
119 memcpy(dest: mBuffer, src: data, n: numBytes);
120 } else {
121 // We have to fill with the zero value..
122 switch (format.sampleType()) {
123 case QAudioFormat::SignedInt:
124 // Signed int means 0x80, 0x8000 is zero
125 // XXX this is not right for > 8 bits(0x8080 vs 0x8000)
126 memset(s: mBuffer, c: 0x80, n: numBytes);
127 break;
128 default:
129 memset(s: mBuffer, c: 0x0, n: numBytes);
130 }
131 }
132 }
133 } else
134 mBuffer = nullptr;
135 }
136
137 ~QMemoryAudioBufferProvider()
138 {
139 if (mBuffer)
140 free(ptr: mBuffer);
141 }
142
143 void release() override {delete this;}
144 QAudioFormat format() const override {return mFormat;}
145 qint64 startTime() const override {return mStartTime;}
146 int frameCount() const override {return mFrameCount;}
147
148 void *constData() const override {return mBuffer;}
149
150 void *writableData() override {return mBuffer;}
151 QAbstractAudioBuffer *clone() const override
152 {
153 return new QMemoryAudioBufferProvider(mBuffer, mFrameCount, mFormat, mStartTime);
154 }
155
156 void *mBuffer;
157 qint64 mStartTime;
158 int mFrameCount;
159 QAudioFormat mFormat;
160};
161
162QAudioBufferPrivate *QAudioBufferPrivate::clone()
163{
164 // We want to create a single bufferprivate with a
165 // single qaab
166 // This should only be called when the count is > 1
167 Q_ASSERT(mCount.loadRelaxed() > 1);
168
169 if (mProvider) {
170 QAbstractAudioBuffer *abuf = mProvider->clone();
171
172 if (!abuf) {
173 abuf = new QMemoryAudioBufferProvider(mProvider->constData(), mProvider->frameCount(), mProvider->format(), mProvider->startTime());
174 }
175
176 if (abuf) {
177 return new QAudioBufferPrivate(abuf);
178 }
179 }
180
181 return nullptr;
182}
183
184/*!
185 \class QAbstractAudioBuffer
186 \internal
187*/
188
189/*!
190 \class QAudioBuffer
191 \inmodule QtMultimedia
192 \ingroup multimedia
193 \ingroup multimedia_audio
194 \brief The QAudioBuffer class represents a collection of audio samples with a specific format and sample rate.
195*/
196// ^ Mostly useful with probe or decoder
197
198/*!
199 Create a new, empty, invalid buffer.
200 */
201QAudioBuffer::QAudioBuffer()
202 : d(nullptr)
203{
204}
205
206/*!
207 \internal
208 Create a new audio buffer from the supplied \a provider. This
209 constructor is typically only used when handling certain hardware
210 or media framework specific buffers, and generally isn't useful
211 in application code.
212 */
213QAudioBuffer::QAudioBuffer(QAbstractAudioBuffer *provider)
214 : d(new QAudioBufferPrivate(provider))
215{
216}
217/*!
218 Creates a new audio buffer from \a other. Generally
219 this will have copy-on-write semantics - a copy will
220 only be made when it has to be.
221 */
222QAudioBuffer::QAudioBuffer(const QAudioBuffer &other)
223{
224 d = QAudioBufferPrivate::acquire(other: other.d);
225}
226
227/*!
228 Creates a new audio buffer from the supplied \a data, in the
229 given \a format. The format will determine how the number
230 and sizes of the samples are interpreted from the \a data.
231
232 If the supplied \a data is not an integer multiple of the
233 calculated frame size, the excess data will not be used.
234
235 This audio buffer will copy the contents of \a data.
236
237 \a startTime (in microseconds) indicates when this buffer
238 starts in the stream.
239 If this buffer is not part of a stream, set it to -1.
240 */
241QAudioBuffer::QAudioBuffer(const QByteArray &data, const QAudioFormat &format, qint64 startTime)
242{
243 if (format.isValid()) {
244 int frameCount = format.framesForBytes(byteCount: data.size());
245 d = new QAudioBufferPrivate(new QMemoryAudioBufferProvider(data.constData(), frameCount, format, startTime));
246 } else
247 d = nullptr;
248}
249
250/*!
251 Creates a new audio buffer with space for \a numFrames frames of
252 the given \a format. The individual samples will be initialized
253 to the default for the format.
254
255 \a startTime (in microseconds) indicates when this buffer
256 starts in the stream.
257 If this buffer is not part of a stream, set it to -1.
258 */
259QAudioBuffer::QAudioBuffer(int numFrames, const QAudioFormat &format, qint64 startTime)
260{
261 if (format.isValid())
262 d = new QAudioBufferPrivate(new QMemoryAudioBufferProvider(nullptr, numFrames, format, startTime));
263 else
264 d = nullptr;
265}
266
267/*!
268 Assigns the \a other buffer to this.
269 */
270QAudioBuffer &QAudioBuffer::operator =(const QAudioBuffer &other)
271{
272 if (this->d != other.d) {
273 if (d)
274 d->deref();
275 d = QAudioBufferPrivate::acquire(other: other.d);
276 }
277 return *this;
278}
279
280/*!
281 Destroys this audio buffer.
282 */
283QAudioBuffer::~QAudioBuffer()
284{
285 if (d)
286 d->deref();
287}
288
289/*!
290 Returns true if this is a valid buffer. A valid buffer
291 has more than zero frames in it and a valid format.
292 */
293bool QAudioBuffer::isValid() const
294{
295 if (!d || !d->mProvider)
296 return false;
297 return d->mProvider->format().isValid() && (d->mProvider->frameCount() > 0);
298}
299
300/*!
301 Returns the \l {QAudioFormat}{format} of this buffer.
302
303 Several properties of this format influence how
304 the \l duration() or \l byteCount() are calculated
305 from the \l frameCount().
306 */
307QAudioFormat QAudioBuffer::format() const
308{
309 if (!isValid())
310 return QAudioFormat();
311 return d->mProvider->format();
312}
313
314/*!
315 Returns the number of complete audio frames in this buffer.
316
317 An audio frame is an interleaved set of one sample per channel
318 for the same instant in time.
319*/
320int QAudioBuffer::frameCount() const
321{
322 if (!isValid())
323 return 0;
324 return d->mProvider->frameCount();
325}
326
327/*!
328 Returns the number of samples in this buffer.
329
330 If the format of this buffer has multiple channels,
331 then this count includes all channels. This means
332 that a stereo buffer with 1000 samples in total will
333 have 500 left samples and 500 right samples (interleaved),
334 and this function will return 1000.
335
336 \sa frameCount()
337*/
338int QAudioBuffer::sampleCount() const
339{
340 if (!isValid())
341 return 0;
342
343 return frameCount() * format().channelCount();
344}
345
346/*!
347 Returns the size of this buffer, in bytes.
348 */
349int QAudioBuffer::byteCount() const
350{
351 const QAudioFormat f(format());
352 return format().bytesForFrames(frameCount: frameCount());
353}
354
355/*!
356 Returns the duration of audio in this buffer, in microseconds.
357
358 This depends on the \l format(), and the \l frameCount().
359*/
360qint64 QAudioBuffer::duration() const
361{
362 return format().durationForFrames(frameCount: frameCount());
363}
364
365/*!
366 Returns the time in a stream that this buffer starts at (in microseconds).
367
368 If this buffer is not part of a stream, this will return -1.
369 */
370qint64 QAudioBuffer::startTime() const
371{
372 if (!isValid())
373 return -1;
374 return d->mProvider->startTime();
375}
376
377/*!
378 Returns a pointer to this buffer's data. You can only read it.
379
380 This method is preferred over the const version of \l data() to
381 prevent unnecessary copying.
382
383 There is also a templatized version of this constData() function that
384 allows you to retrieve a specific type of read-only pointer to
385 the data. Note that there is no checking done on the format of
386 the audio buffer - this is simply a convenience function.
387
388 \code
389 // With a 16bit sample buffer:
390 const quint16 *data = buffer->constData<quint16>();
391 \endcode
392
393*/
394const void* QAudioBuffer::constData() const
395{
396 if (!isValid())
397 return nullptr;
398 return d->mProvider->constData();
399}
400
401/*!
402 Returns a pointer to this buffer's data. You can only read it.
403
404 You should use the \l constData() function rather than this
405 to prevent accidental deep copying.
406
407 There is also a templatized version of this data() function that
408 allows you to retrieve a specific type of read-only pointer to
409 the data. Note that there is no checking done on the format of
410 the audio buffer - this is simply a convenience function.
411
412 \code
413 // With a 16bit sample const buffer:
414 const quint16 *data = buffer->data<quint16>();
415 \endcode
416*/
417const void* QAudioBuffer::data() const
418{
419 if (!isValid())
420 return nullptr;
421 return d->mProvider->constData();
422}
423
424
425/*
426 Template data/constData functions caused override problems with qdoc,
427 so moved their docs into the non template versions.
428*/
429
430/*!
431 Returns a pointer to this buffer's data. You can modify the
432 data through the returned pointer.
433
434 Since QAudioBuffers can share the actual sample data, calling
435 this function will result in a deep copy being made if there
436 are any other buffers using the sample. You should avoid calling
437 this unless you really need to modify the data.
438
439 This pointer will remain valid until the underlying storage is
440 detached. In particular, if you obtain a pointer, and then
441 copy this audio buffer, changing data through this pointer may
442 change both buffer instances. Calling \l data() on either instance
443 will again cause a deep copy to be made, which may invalidate
444 the pointers returned from this function previously.
445
446 There is also a templatized version of data() allows you to retrieve
447 a specific type of pointer to the data. Note that there is no
448 checking done on the format of the audio buffer - this is
449 simply a convenience function.
450
451 \code
452 // With a 16bit sample buffer:
453 quint16 *data = buffer->data<quint16>(); // May cause deep copy
454 \endcode
455*/
456void *QAudioBuffer::data()
457{
458 if (!isValid())
459 return nullptr;
460
461 if (d->mCount.loadRelaxed() != 1) {
462 // Can't share a writable buffer
463 // so we need to detach
464 QAudioBufferPrivate *newd = d->clone();
465
466 // This shouldn't happen
467 if (!newd)
468 return nullptr;
469
470 d->deref();
471 d = newd;
472 }
473
474 // We're (now) the only user of this qaab, so
475 // see if it's writable directly
476 void *buffer = d->mProvider->writableData();
477 if (buffer) {
478 return buffer;
479 }
480
481 // Wasn't writable, so turn it into a memory provider
482 QAbstractAudioBuffer *memBuffer = new QMemoryAudioBufferProvider(constData(), frameCount(), format(), startTime());
483
484 if (memBuffer) {
485 d->mProvider->release();
486 d->mCount.storeRelaxed(newValue: 1);
487 d->mProvider = memBuffer;
488
489 return memBuffer->writableData();
490 }
491
492 return nullptr;
493}
494
495// Template helper classes worth documenting
496
497/*!
498 \class QAudioBuffer::StereoFrameDefault
499 \internal
500
501 Just a trait class for the default value.
502*/
503
504/*!
505 \class QAudioBuffer::StereoFrame
506 \brief The StereoFrame class provides a simple wrapper for a stereo audio frame.
507 \inmodule QtMultimedia
508 \ingroup multimedia
509 \ingroup multimedia_audio
510
511 This templatized structure lets you treat a block of individual samples as an
512 interleaved stereo stream frame. This is most useful when used with the templatized
513 \l {QAudioBuffer::data()}{data()} functions of QAudioBuffer. Generally the data
514 is accessed as a pointer, so no copying should occur.
515
516 There are some predefined instantiations of this template for working with common
517 stereo sample depths in a convenient way.
518
519 This frame structure has \e left and \e right members for accessing individual channel data.
520
521 For example:
522 \code
523 // Assuming 'buffer' is an unsigned 16 bit stereo buffer..
524 QAudioBuffer::S16U *frames = buffer->data<QAudioBuffer::S16U>();
525 for (int i=0; i < buffer->frameCount(); i++) {
526 qSwap(frames[i].left, frames[i].right);
527 }
528 \endcode
529
530 \sa QAudioBuffer::S8U, QAudioBuffer::S8S, QAudioBuffer::S16S, QAudioBuffer::S16U, QAudioBuffer::S32F
531*/
532
533/*!
534 \fn template <typename T> QAudioBuffer::StereoFrame<T>::StereoFrame()
535
536 Constructs a new frame with the "silent" value for this
537 sample format (0 for signed formats and floats, 0x8* for unsigned formats).
538*/
539
540/*!
541 \fn template <typename T> QAudioBuffer::StereoFrame<T>::StereoFrame(T leftSample, T rightSample)
542
543 Constructs a new frame with the supplied \a leftSample and \a rightSample values.
544*/
545
546/*!
547 \fn template <typename T> QAudioBuffer::StereoFrame<T>::operator=(const StereoFrame &other)
548
549 Assigns \a other to this frame.
550 */
551
552
553/*!
554 \fn template <typename T> QAudioBuffer::StereoFrame<T>::average() const
555
556 Returns the arithmetic average of the left and right samples.
557 */
558
559/*! \fn template <typename T> QAudioBuffer::StereoFrame<T>::clear()
560
561 Sets the values of this frame to the "silent" value.
562*/
563
564/*!
565 \variable QAudioBuffer::StereoFrame::left
566 \brief the left sample
567*/
568
569/*!
570 \variable QAudioBuffer::StereoFrame::right
571 \brief the right sample
572*/
573
574/*!
575 \typedef QAudioBuffer::S8U
576
577 This is a predefined specialization for an unsigned stereo 8 bit sample. Each
578 channel is an \e {unsigned char}.
579*/
580/*!
581 \typedef QAudioBuffer::S8S
582
583 This is a predefined specialization for a signed stereo 8 bit sample. Each
584 channel is a \e {signed char}.
585*/
586/*!
587 \typedef QAudioBuffer::S16U
588
589 This is a predefined specialization for an unsigned stereo 16 bit sample. Each
590 channel is an \e {unsigned short}.
591*/
592/*!
593 \typedef QAudioBuffer::S16S
594
595 This is a predefined specialization for a signed stereo 16 bit sample. Each
596 channel is a \e {signed short}.
597*/
598/*!
599 \typedef QAudioBuffer::S32F
600
601 This is a predefined specialization for an 32 bit float sample. Each
602 channel is a \e float.
603*/
604
605QT_END_NAMESPACE
606

source code of qtmultimedia/src/multimedia/audio/qaudiobuffer.cpp