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
4#include "qaudiohelpers_p.h"
5
6#include <limits>
7
8QT_BEGIN_NAMESPACE
9
10namespace QAudioHelperInternal
11{
12
13#if defined(Q_CC_GNU)
14# define QT_MM_RESTRICT __restrict__
15#elif defined(Q_CC_MSVC)
16# define QT_MM_RESTRICT __restrict
17#else
18# define QT_MM_RESTRICT /*__restrict__*/
19#endif
20
21namespace {
22
23template<class T>
24inline T applyVolumeOnSample(T sample, float factor)
25{
26 if constexpr (std::is_signed_v<T>) {
27 return sample * factor;
28 } else {
29 using SignedT = std::make_signed_t<T>;
30 // Unsigned samples are biased around 0x80/0x8000
31 constexpr T offset = SignedT(1) << (std::numeric_limits<T>::digits - 1);
32 return offset + (SignedT(sample - offset) * factor);
33 }
34}
35
36template<class T>
37void adjustSamples(float factor,
38 const void *QT_MM_RESTRICT src,
39 void *QT_MM_RESTRICT dst,
40 int samples)
41{
42 const T *pSrc = (const T *)src;
43 T *pDst = (T *)dst;
44
45 for (int i = 0; i < samples; i++)
46 pDst[i] = applyVolumeOnSample(pSrc[i], factor);
47}
48
49} // namespace
50
51void qMultiplySamples(float factor,
52 const QAudioFormat &format,
53 const void *src,
54 void *dest,
55 int len) QT_MM_NONBLOCKING
56{
57 const int samplesCount = len / qMax(a: 1, b: format.bytesPerSample());
58
59 auto clamp = [](float arg) {
60 float realVolume = std::clamp<float>(val: arg, lo: 0.f, hi: 1.f);
61 return realVolume;
62 };
63
64 switch (format.sampleFormat()) {
65 case QAudioFormat::UInt8:
66 return QAudioHelperInternal::adjustSamples<quint8>(factor: clamp(factor), src, dst: dest, samples: samplesCount);
67 case QAudioFormat::Int16:
68 return QAudioHelperInternal::adjustSamples<qint16>(factor: clamp(factor), src, dst: dest, samples: samplesCount);
69 case QAudioFormat::Int32:
70 return QAudioHelperInternal::adjustSamples<qint32>(factor: clamp(factor), src, dst: dest, samples: samplesCount);
71 case QAudioFormat::Float:
72 return QAudioHelperInternal::adjustSamples<float>(factor, src, dst: dest, samples: samplesCount);
73 default:
74 Q_UNREACHABLE_RETURN();
75 }
76}
77
78void applyVolume(float volume,
79 const QAudioFormat &format,
80 QSpan<const std::byte> source,
81 QSpan<std::byte> destination) QT_MM_NONBLOCKING
82{
83 Q_ASSERT(source.size() == destination.size());
84
85 if (Q_LIKELY(volume == 1.f)) {
86 std::copy(first: source.begin(), last: source.end(), result: destination.begin());
87 } else if (volume == 0) {
88 std::byte zero =
89 format.sampleFormat() == QAudioFormat::UInt8 ? std::byte{ 0x80 } : std::byte{ 0 };
90
91 std::fill(first: destination.begin(), last: destination.begin() + source.size(), value: zero);
92 } else {
93 QAudioHelperInternal::qMultiplySamples(factor: volume, format, src: source.data(), dest: destination.data(),
94 len: source.size());
95 }
96}
97
98} // namespace QAudioHelperInternal
99
100#undef QT_MM_RESTRICT
101
102QT_END_NAMESPACE
103

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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