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 "qaudiohelpers_p.h"
41
42#include <QDebug>
43
44QT_BEGIN_NAMESPACE
45
46// Base implementation of 24 bits number.
47// Used to adjust 3 bytes values by a factor.
48// TODO: Uses little-endian only.
49class Int24
50{
51public:
52 quint8 data[3];
53 Int24(qint32 v) {
54 data[0] = v & 0xFF;
55 data[1] = (v & 0xFF00) >> 8;
56 data[2] = (v & 0xFF0000) >> 16;
57 }
58 template<class T>
59 T multiply(qreal factor, T v = 0) const {
60 v |= data[0];
61 v |= data[1] << 8;
62 v |= data[2] << 16;
63 v *= factor;
64 return v;
65 }
66};
67
68class qint24: public Int24
69{
70public:
71 qint24(qint32 v): Int24(v) {}
72 qint24 operator*(qreal factor) const {
73 // Checks if it is a signed value.
74 qint32 v = (data[2] & 0x80) ? 0xFF000000 : 0;
75 return multiply(factor, v);
76 }
77};
78
79class quint24: public Int24
80{
81public:
82 quint24(quint32 v): Int24(v) {}
83 quint24 operator*(qreal factor) const {
84 return multiply<quint32>(factor);
85 }
86};
87
88
89namespace QAudioHelperInternal
90{
91
92template<class T> void adjustSamples(qreal factor, const void *src, void *dst, int samples)
93{
94 const T *pSrc = (const T *)src;
95 T *pDst = (T*)dst;
96 for ( int i = 0; i < samples; i++ )
97 pDst[i] = pSrc[i] * factor;
98}
99
100// Unsigned samples are biased around 0x80/0x8000 :/
101// This makes a pure template solution a bit unwieldy but possible
102template<class T> struct signedVersion {};
103template<> struct signedVersion<quint8>
104{
105 typedef qint8 TS;
106 enum {offset = 0x80};
107};
108
109template<> struct signedVersion<quint16>
110{
111 typedef qint16 TS;
112 enum {offset = 0x8000};
113};
114
115template<> struct signedVersion<quint32>
116{
117 typedef qint32 TS;
118 enum {offset = 0x80000000};
119};
120
121template<class T> void adjustUnsignedSamples(qreal factor, const void *src, void *dst, int samples)
122{
123 const T *pSrc = (const T *)src;
124 T *pDst = (T*)dst;
125 for ( int i = 0; i < samples; i++ ) {
126 pDst[i] = signedVersion<T>::offset + ((typename signedVersion<T>::TS)(pSrc[i] - signedVersion<T>::offset) * factor);
127 }
128}
129
130void qMultiplySamples(qreal factor, const QAudioFormat &format, const void* src, void* dest, int len)
131{
132 int samplesCount = len / (format.sampleSize()/8);
133
134 switch ( format.sampleSize() ) {
135 case 8:
136 if (format.sampleType() == QAudioFormat::SignedInt)
137 QAudioHelperInternal::adjustSamples<qint8>(factor,src,dst: dest,samples: samplesCount);
138 else if (format.sampleType() == QAudioFormat::UnSignedInt)
139 QAudioHelperInternal::adjustUnsignedSamples<quint8>(factor,src,dst: dest,samples: samplesCount);
140 break;
141 case 16:
142 if (format.sampleType() == QAudioFormat::SignedInt)
143 QAudioHelperInternal::adjustSamples<qint16>(factor,src,dst: dest,samples: samplesCount);
144 else if (format.sampleType() == QAudioFormat::UnSignedInt)
145 QAudioHelperInternal::adjustUnsignedSamples<quint16>(factor,src,dst: dest,samples: samplesCount);
146 break;
147 case 24:
148 if (format.sampleType() == QAudioFormat::SignedInt)
149 QAudioHelperInternal::adjustSamples<qint24>(factor,src,dst: dest,samples: samplesCount);
150 else if (format.sampleType() == QAudioFormat::UnSignedInt)
151 QAudioHelperInternal::adjustSamples<quint24>(factor,src,dst: dest,samples: samplesCount);
152 break;
153 default:
154 if (format.sampleType() == QAudioFormat::SignedInt)
155 QAudioHelperInternal::adjustSamples<qint32>(factor,src,dst: dest,samples: samplesCount);
156 else if (format.sampleType() == QAudioFormat::UnSignedInt)
157 QAudioHelperInternal::adjustUnsignedSamples<quint32>(factor,src,dst: dest,samples: samplesCount);
158 else if (format.sampleType() == QAudioFormat::Float)
159 QAudioHelperInternal::adjustSamples<float>(factor,src,dst: dest,samples: samplesCount);
160 }
161}
162}
163
164QT_END_NAMESPACE
165

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