react-native-audio-api 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -1
- package/RNAudioAPI.podspec +46 -0
- package/android/CMakeLists.txt +74 -0
- package/android/build.gradle +194 -0
- package/android/gradle.properties +5 -0
- package/android/libs/fftw3/arm64-v8a/libfftw3.a +0 -0
- package/android/libs/fftw3/armeabi-v7a/libfftw3.a +0 -0
- package/android/libs/fftw3/x86/libfftw3.a +0 -0
- package/android/libs/fftw3/x86_64/libfftw3.a +0 -0
- package/android/libs/include/fftw3/fftw3.h +413 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.cpp +22 -0
- package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.h +48 -0
- package/android/src/main/cpp/AudioPlayer/AudioPlayer.cpp +66 -0
- package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +33 -0
- package/android/src/main/cpp/OnLoad.cpp +9 -0
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +14 -0
- package/android/src/main/java/com/swmansion/audioapi/module/AudioAPIInstaller.kt +21 -0
- package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +25 -0
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +52 -0
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +45 -0
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerWrapper.h +38 -0
- package/common/cpp/AudioAPIInstaller/android/AudioAPIInstallerWrapper.cpp +16 -0
- package/common/cpp/AudioAPIInstaller/ios/AudioAPIInstallerWrapper.cpp +12 -0
- package/common/cpp/HostObjects/AudioBufferHostObject.cpp +143 -0
- package/common/cpp/HostObjects/AudioBufferHostObject.h +33 -0
- package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +79 -0
- package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.h +37 -0
- package/common/cpp/HostObjects/AudioContextHostObject.cpp +54 -0
- package/common/cpp/HostObjects/AudioContextHostObject.h +36 -0
- package/common/cpp/HostObjects/AudioDestinationNodeHostObject.cpp +33 -0
- package/common/cpp/HostObjects/AudioDestinationNodeHostObject.h +31 -0
- package/common/cpp/HostObjects/AudioNodeHostObject.cpp +102 -0
- package/common/cpp/HostObjects/AudioNodeHostObject.h +29 -0
- package/common/cpp/HostObjects/AudioParamHostObject.cpp +115 -0
- package/common/cpp/HostObjects/AudioParamHostObject.h +34 -0
- package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.cpp +73 -0
- package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.h +31 -0
- package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +214 -0
- package/common/cpp/HostObjects/BaseAudioContextHostObject.h +39 -0
- package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +125 -0
- package/common/cpp/HostObjects/BiquadFilterNodeHostObject.h +42 -0
- package/common/cpp/HostObjects/Constants.h +22 -0
- package/common/cpp/HostObjects/GainNodeHostObject.cpp +41 -0
- package/common/cpp/HostObjects/GainNodeHostObject.h +32 -0
- package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +88 -0
- package/common/cpp/HostObjects/OscillatorNodeHostObject.h +41 -0
- package/common/cpp/HostObjects/PeriodicWaveHostObject.cpp +33 -0
- package/common/cpp/HostObjects/PeriodicWaveHostObject.h +33 -0
- package/common/cpp/HostObjects/StereoPannerNodeHostObject.cpp +41 -0
- package/common/cpp/HostObjects/StereoPannerNodeHostObject.h +36 -0
- package/common/cpp/core/AudioArray.cpp +103 -0
- package/common/cpp/core/AudioArray.h +42 -0
- package/common/cpp/core/AudioBuffer.cpp +55 -0
- package/common/cpp/core/AudioBuffer.h +40 -0
- package/common/cpp/core/AudioBufferSourceNode.cpp +135 -0
- package/common/cpp/core/AudioBufferSourceNode.h +30 -0
- package/common/cpp/core/AudioBus.cpp +357 -0
- package/common/cpp/core/AudioBus.h +63 -0
- package/common/cpp/core/AudioContext.cpp +24 -0
- package/common/cpp/core/AudioContext.h +16 -0
- package/common/cpp/core/AudioDestinationNode.cpp +45 -0
- package/common/cpp/core/AudioDestinationNode.h +32 -0
- package/common/cpp/core/AudioNode.cpp +222 -0
- package/common/cpp/core/AudioNode.h +74 -0
- package/common/cpp/core/AudioNodeManager.cpp +72 -0
- package/common/cpp/core/AudioNodeManager.h +35 -0
- package/common/cpp/core/AudioParam.cpp +133 -0
- package/common/cpp/core/AudioParam.h +50 -0
- package/common/cpp/core/AudioScheduledSourceNode.cpp +53 -0
- package/common/cpp/core/AudioScheduledSourceNode.h +34 -0
- package/common/cpp/core/BaseAudioContext.cpp +157 -0
- package/common/cpp/core/BaseAudioContext.h +80 -0
- package/common/cpp/core/BiquadFilterNode.cpp +385 -0
- package/common/cpp/core/BiquadFilterNode.h +124 -0
- package/common/cpp/core/GainNode.cpp +30 -0
- package/common/cpp/core/GainNode.h +25 -0
- package/common/cpp/core/OscillatorNode.cpp +75 -0
- package/common/cpp/core/OscillatorNode.h +72 -0
- package/common/cpp/core/ParamChange.cpp +46 -0
- package/common/cpp/core/ParamChange.h +34 -0
- package/common/cpp/core/PeriodicWave.cpp +362 -0
- package/common/cpp/core/PeriodicWave.h +119 -0
- package/common/cpp/core/StereoPannerNode.cpp +56 -0
- package/common/cpp/core/StereoPannerNode.h +26 -0
- package/common/cpp/types/BiquadFilterType.h +19 -0
- package/common/cpp/types/ChannelCountMode.h +10 -0
- package/common/cpp/types/ChannelInterpretation.h +10 -0
- package/common/cpp/types/ContextState.h +10 -0
- package/common/cpp/types/OscillatorType.h +11 -0
- package/common/cpp/utils/FFTFrame.h +63 -0
- package/common/cpp/utils/Locker.h +47 -0
- package/common/cpp/utils/VectorMath.cpp +678 -0
- package/common/cpp/utils/VectorMath.h +71 -0
- package/common/cpp/utils/android/FFTFrame.cpp +22 -0
- package/common/cpp/utils/ios/FFTFrame.cpp +24 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +45 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +26 -0
- package/common/cpp/wrappers/AudioBufferWrapper.cpp +46 -0
- package/common/cpp/wrappers/AudioBufferWrapper.h +30 -0
- package/common/cpp/wrappers/AudioContextWrapper.cpp +17 -0
- package/common/cpp/wrappers/AudioContextWrapper.h +19 -0
- package/common/cpp/wrappers/AudioDestinationNodeWrapper.h +16 -0
- package/common/cpp/wrappers/AudioNodeWrapper.cpp +37 -0
- package/common/cpp/wrappers/AudioNodeWrapper.h +25 -0
- package/common/cpp/wrappers/AudioParamWrapper.cpp +42 -0
- package/common/cpp/wrappers/AudioParamWrapper.h +25 -0
- package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.cpp +23 -0
- package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.h +23 -0
- package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +76 -0
- package/common/cpp/wrappers/BaseAudioContextWrapper.h +49 -0
- package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +60 -0
- package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +37 -0
- package/common/cpp/wrappers/GainNodeWrapper.cpp +14 -0
- package/common/cpp/wrappers/GainNodeWrapper.h +20 -0
- package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +44 -0
- package/common/cpp/wrappers/OscillatorNodeWrapper.h +31 -0
- package/common/cpp/wrappers/PeriodicWaveWrapper.h +17 -0
- package/common/cpp/wrappers/StereoPannerNodeWrapper.cpp +16 -0
- package/common/cpp/wrappers/StereoPannerNodeWrapper.h +21 -0
- package/ios/AudioAPIModule.h +24 -0
- package/ios/AudioAPIModule.mm +44 -0
- package/ios/AudioPlayer/AudioPlayer.h +28 -0
- package/ios/AudioPlayer/AudioPlayer.m +119 -0
- package/ios/AudioPlayer/IOSAudioPlayer.h +33 -0
- package/ios/AudioPlayer/IOSAudioPlayer.mm +57 -0
- package/lib/module/core/AudioBuffer.js +37 -0
- package/lib/module/core/AudioBuffer.js.map +1 -0
- package/lib/module/core/AudioBufferSourceNode.js +28 -0
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -0
- package/lib/module/core/AudioContext.js +10 -0
- package/lib/module/core/AudioContext.js.map +1 -0
- package/lib/module/core/AudioDestinationNode.js +7 -0
- package/lib/module/core/AudioDestinationNode.js.map +1 -0
- package/lib/module/core/AudioNode.js +22 -0
- package/lib/module/core/AudioNode.js.map +1 -0
- package/lib/module/core/AudioParam.js +35 -0
- package/lib/module/core/AudioParam.js.map +1 -0
- package/lib/module/core/AudioScheduledSourceNode.js +28 -0
- package/lib/module/core/AudioScheduledSourceNode.js.map +1 -0
- package/lib/module/core/BaseAudioContext.js +57 -0
- package/lib/module/core/BaseAudioContext.js.map +1 -0
- package/lib/module/core/BiquadFilterNode.js +25 -0
- package/lib/module/core/BiquadFilterNode.js.map +1 -0
- package/lib/module/core/GainNode.js +9 -0
- package/lib/module/core/GainNode.js.map +1 -0
- package/lib/module/core/OscillatorNode.js +24 -0
- package/lib/module/core/OscillatorNode.js.map +1 -0
- package/lib/module/core/PeriodicWave.js +8 -0
- package/lib/module/core/PeriodicWave.js.map +1 -0
- package/lib/module/core/StereoPannerNode.js +9 -0
- package/lib/module/core/StereoPannerNode.js.map +1 -0
- package/lib/module/core/types.js +2 -0
- package/lib/module/core/types.js.map +1 -0
- package/lib/module/errors/IndexSizeError.js +8 -0
- package/lib/module/errors/IndexSizeError.js.map +1 -0
- package/lib/module/errors/InvalidAccessError.js +8 -0
- package/lib/module/errors/InvalidAccessError.js.map +1 -0
- package/lib/module/errors/InvalidStateError.js +8 -0
- package/lib/module/errors/InvalidStateError.js.map +1 -0
- package/lib/module/errors/RangeError.js +8 -0
- package/lib/module/errors/RangeError.js.map +1 -0
- package/lib/module/errors/index.js +5 -0
- package/lib/module/errors/index.js.map +1 -0
- package/lib/module/index.js +18 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/interfaces.js +2 -0
- package/lib/module/interfaces.js.map +1 -0
- package/lib/module/modules/global.d.js +2 -0
- package/lib/module/modules/global.d.js.map +1 -0
- package/lib/module/utils/install.js +22 -0
- package/lib/module/utils/install.js.map +1 -0
- package/lib/typescript/core/AudioBuffer.d.ts +12 -0
- package/lib/typescript/core/AudioBuffer.d.ts.map +1 -0
- package/lib/typescript/core/AudioBufferSourceNode.d.ts +12 -0
- package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -0
- package/lib/typescript/core/AudioContext.d.ts +6 -0
- package/lib/typescript/core/AudioContext.d.ts.map +1 -0
- package/lib/typescript/core/AudioDestinationNode.d.ts +7 -0
- package/lib/typescript/core/AudioDestinationNode.d.ts.map +1 -0
- package/lib/typescript/core/AudioNode.d.ts +16 -0
- package/lib/typescript/core/AudioNode.d.ts.map +1 -0
- package/lib/typescript/core/AudioParam.d.ts +14 -0
- package/lib/typescript/core/AudioParam.d.ts.map +1 -0
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts +10 -0
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -0
- package/lib/typescript/core/BaseAudioContext.d.ts +26 -0
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -0
- package/lib/typescript/core/BiquadFilterNode.d.ts +16 -0
- package/lib/typescript/core/BiquadFilterNode.d.ts.map +1 -0
- package/lib/typescript/core/GainNode.d.ts +9 -0
- package/lib/typescript/core/GainNode.d.ts.map +1 -0
- package/lib/typescript/core/OscillatorNode.d.ts +15 -0
- package/lib/typescript/core/OscillatorNode.d.ts.map +1 -0
- package/lib/typescript/core/PeriodicWave.d.ts +5 -0
- package/lib/typescript/core/PeriodicWave.d.ts.map +1 -0
- package/lib/typescript/core/StereoPannerNode.d.ts +9 -0
- package/lib/typescript/core/StereoPannerNode.d.ts.map +1 -0
- package/lib/typescript/core/types.d.ts +9 -0
- package/lib/typescript/core/types.d.ts.map +1 -0
- package/lib/typescript/errors/IndexSizeError.d.ts +5 -0
- package/lib/typescript/errors/IndexSizeError.d.ts.map +1 -0
- package/lib/typescript/errors/InvalidAccessError.d.ts +5 -0
- package/lib/typescript/errors/InvalidAccessError.d.ts.map +1 -0
- package/lib/typescript/errors/InvalidStateError.d.ts +5 -0
- package/lib/typescript/errors/InvalidStateError.d.ts.map +1 -0
- package/lib/typescript/errors/RangeError.d.ts +5 -0
- package/lib/typescript/errors/RangeError.d.ts.map +1 -0
- package/lib/typescript/errors/index.d.ts +5 -0
- package/lib/typescript/errors/index.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +14 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/interfaces.d.ts +78 -0
- package/lib/typescript/interfaces.d.ts.map +1 -0
- package/lib/typescript/utils/install.d.ts +7 -0
- package/lib/typescript/utils/install.d.ts.map +1 -0
- package/package.json +104 -5
- package/src/core/AudioBuffer.ts +68 -0
- package/src/core/AudioBufferSourceNode.ts +35 -0
- package/src/core/AudioContext.ts +12 -0
- package/src/core/AudioDestinationNode.ts +9 -0
- package/src/core/AudioNode.ts +38 -0
- package/src/core/AudioParam.ts +55 -0
- package/src/core/AudioScheduledSourceNode.ts +43 -0
- package/src/core/BaseAudioContext.ts +97 -0
- package/src/core/BiquadFilterNode.ts +49 -0
- package/src/core/GainNode.ts +13 -0
- package/src/core/OscillatorNode.ts +37 -0
- package/src/core/PeriodicWave.ts +10 -0
- package/src/core/StereoPannerNode.ts +13 -0
- package/src/core/types.ts +26 -0
- package/src/errors/IndexSizeError.ts +8 -0
- package/src/errors/InvalidAccessError.ts +8 -0
- package/src/errors/InvalidStateError.ts +8 -0
- package/src/errors/RangeError.ts +8 -0
- package/src/errors/index.ts +4 -0
- package/src/index.ts +25 -0
- package/src/interfaces.ts +120 -0
- package/src/modules/global.d.ts +10 -0
- package/src/utils/install.ts +39 -0
- package/index.ts +0 -1
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2012 Google Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Redistribution and use in source and binary forms, with or without
|
|
5
|
+
* modification, are permitted provided that the following conditions
|
|
6
|
+
* are met:
|
|
7
|
+
*
|
|
8
|
+
* 1. Redistributions of source code must retain the above copyright
|
|
9
|
+
* notice, this list of conditions and the following disclaimer.
|
|
10
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
12
|
+
* documentation and/or other materials provided with the distribution.
|
|
13
|
+
* 3. Neither the name of Apple Inc. ("Apple") nor the names of
|
|
14
|
+
* its contributors may be used to endorse or promote products derived
|
|
15
|
+
* from this software without specific prior written permission.
|
|
16
|
+
*
|
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
|
|
18
|
+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
19
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
20
|
+
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
|
21
|
+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
22
|
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
23
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
24
|
+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
25
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
26
|
+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
#include "PeriodicWave.h"
|
|
30
|
+
|
|
31
|
+
constexpr unsigned NumberOfOctaveBands = 3;
|
|
32
|
+
constexpr float CentsPerRange = 1200.0f / NumberOfOctaveBands;
|
|
33
|
+
constexpr float interpolate2Point = 0.3;
|
|
34
|
+
constexpr float interpolate3Point = 0.16;
|
|
35
|
+
|
|
36
|
+
namespace audioapi {
|
|
37
|
+
PeriodicWave::PeriodicWave(int sampleRate, bool disableNormalization)
|
|
38
|
+
: sampleRate_(sampleRate), disableNormalization_(disableNormalization) {
|
|
39
|
+
numberOfRanges_ = lround(
|
|
40
|
+
NumberOfOctaveBands * log2f(static_cast<float>(getPeriodicWaveSize())));
|
|
41
|
+
auto nyquistFrequency = sampleRate_ / 2;
|
|
42
|
+
lowestFundamentalFrequency_ = static_cast<float>(nyquistFrequency) /
|
|
43
|
+
static_cast<float>(getMaxNumberOfPartials());
|
|
44
|
+
scale_ = static_cast<float>(getPeriodicWaveSize()) /
|
|
45
|
+
static_cast<float>(sampleRate_);
|
|
46
|
+
bandLimitedTables_ = new float *[numberOfRanges_];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
PeriodicWave::PeriodicWave(
|
|
50
|
+
int sampleRate,
|
|
51
|
+
audioapi::OscillatorType type,
|
|
52
|
+
bool disableNormalization)
|
|
53
|
+
: PeriodicWave(sampleRate, disableNormalization) {
|
|
54
|
+
this->generateBasicWaveForm(type);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
PeriodicWave::PeriodicWave(
|
|
58
|
+
int sampleRate,
|
|
59
|
+
float *real,
|
|
60
|
+
float *imaginary,
|
|
61
|
+
int length,
|
|
62
|
+
bool disableNormalization)
|
|
63
|
+
: PeriodicWave(sampleRate, disableNormalization) {
|
|
64
|
+
createBandLimitedTables(real, imaginary, length);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
int PeriodicWave::getPeriodicWaveSize() const {
|
|
68
|
+
if (sampleRate_ <= 24000) {
|
|
69
|
+
return 2048;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (sampleRate_ <= 88200) {
|
|
73
|
+
return 4096;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return 16384;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
float PeriodicWave::getScale() const {
|
|
80
|
+
return scale_;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
float PeriodicWave::getSample(
|
|
84
|
+
float fundamentalFrequency,
|
|
85
|
+
float phase,
|
|
86
|
+
float phaseIncrement) {
|
|
87
|
+
float *lowerWaveData = nullptr;
|
|
88
|
+
float *higherWaveData = nullptr;
|
|
89
|
+
|
|
90
|
+
auto interpolationFactor = getWaveDataForFundamentalFrequency(
|
|
91
|
+
fundamentalFrequency, lowerWaveData, higherWaveData);
|
|
92
|
+
|
|
93
|
+
return doInterpolation(
|
|
94
|
+
phase,
|
|
95
|
+
phaseIncrement,
|
|
96
|
+
interpolationFactor,
|
|
97
|
+
lowerWaveData,
|
|
98
|
+
higherWaveData);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
int PeriodicWave::getMaxNumberOfPartials() const {
|
|
102
|
+
return getPeriodicWaveSize() / 2;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
int PeriodicWave::getNumberOfPartialsPerRange(int rangeIndex) const {
|
|
106
|
+
// Number of cents below nyquist where we cull partials.
|
|
107
|
+
auto centsToCull = static_cast<float>(rangeIndex) * CentsPerRange;
|
|
108
|
+
|
|
109
|
+
// A value from 0 -> 1 representing what fraction of the partials to keep.
|
|
110
|
+
auto cullingScale = std::powf(2, -centsToCull / 1200);
|
|
111
|
+
|
|
112
|
+
// The very top range will have all the partials culled.
|
|
113
|
+
int numberOfPartials =
|
|
114
|
+
floor(static_cast<float>(getMaxNumberOfPartials()) * cullingScale);
|
|
115
|
+
|
|
116
|
+
return numberOfPartials;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
void PeriodicWave::generateBasicWaveForm(OscillatorType type) {
|
|
120
|
+
auto fftSize = getPeriodicWaveSize();
|
|
121
|
+
/*
|
|
122
|
+
* For real-valued time-domain signals, the FFT outputs a Hermitian symmetric
|
|
123
|
+
* sequence (where the positive frequencies are the complex conjugate of the
|
|
124
|
+
* negative ones). This symmetry implies that real signals have mirrored
|
|
125
|
+
* frequency components. In such scenarios, all 'real' frequency information
|
|
126
|
+
* is contained in the first half of the transform, and altering parts such as
|
|
127
|
+
* real and imaginary can finely shape which harmonic content is retained or
|
|
128
|
+
* discarded.
|
|
129
|
+
*/
|
|
130
|
+
auto halfSize = fftSize / 2;
|
|
131
|
+
|
|
132
|
+
auto *real = new float[halfSize];
|
|
133
|
+
auto *imaginary = new float[halfSize];
|
|
134
|
+
|
|
135
|
+
// Reset Direct Current (DC) component. First element of frequency domain
|
|
136
|
+
// representation - c0. https://math24.net/complex-form-fourier-series.html
|
|
137
|
+
real[0] = 0.0f;
|
|
138
|
+
imaginary[0] = 0.0f;
|
|
139
|
+
|
|
140
|
+
for (int i = 1; i < halfSize; i++) {
|
|
141
|
+
// All waveforms are odd functions with a positive slope at time 0.
|
|
142
|
+
// Hence the coefficients for cos() are always 0.
|
|
143
|
+
|
|
144
|
+
// Formulas for Fourier coefficients:
|
|
145
|
+
// https://mathworld.wolfram.com/FourierSeries.html
|
|
146
|
+
|
|
147
|
+
// Coefficient for sin()
|
|
148
|
+
float b;
|
|
149
|
+
|
|
150
|
+
auto piFactor = static_cast<float>(1.0f / (i * M_PI));
|
|
151
|
+
|
|
152
|
+
switch (type) {
|
|
153
|
+
case OscillatorType::SINE:
|
|
154
|
+
b = (i == 1) ? 1.0f : 0.0f;
|
|
155
|
+
break;
|
|
156
|
+
case OscillatorType::SQUARE:
|
|
157
|
+
// https://mathworld.wolfram.com/FourierSeriesSquareWave.html
|
|
158
|
+
b = ((i & 1) == 1) ? 4 * piFactor : 0.0f;
|
|
159
|
+
break;
|
|
160
|
+
case OscillatorType::SAWTOOTH:
|
|
161
|
+
// https://mathworld.wolfram.com/FourierSeriesSawtoothWave.html - our
|
|
162
|
+
// Function differs from this one, but coefficients calculation looks
|
|
163
|
+
// similar. our function - f(x) = 2(x / (2 * pi) - floor(x / (2 * pi) +
|
|
164
|
+
// 0.5)));
|
|
165
|
+
// https://www.wolframalpha.com/input?i=2%28x+%2F+%282+*+pi%29+-+floor%28x+%2F+%282+*+pi%29+%2B+0.5%29%29%29%3B
|
|
166
|
+
b = 2 * piFactor * ((i & 1) == 1 ? 1.0f : -1.0f);
|
|
167
|
+
break;
|
|
168
|
+
case OscillatorType::TRIANGLE:
|
|
169
|
+
// https://mathworld.wolfram.com/FourierSeriesTriangleWave.html
|
|
170
|
+
if ((i & 1) == 1) {
|
|
171
|
+
b = 8.0f * piFactor * piFactor * ((i & 3) == 1 ? 1.0f : -1.0f);
|
|
172
|
+
} else {
|
|
173
|
+
b = 0.0f;
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
case OscillatorType::CUSTOM:
|
|
177
|
+
throw std::invalid_argument("Custom waveforms are not supported.");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
real[i] = 0.0f;
|
|
181
|
+
imaginary[i] = b;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
createBandLimitedTables(real, imaginary, halfSize);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
void PeriodicWave::createBandLimitedTables(
|
|
188
|
+
const float *realData,
|
|
189
|
+
const float *imaginaryData,
|
|
190
|
+
int size) {
|
|
191
|
+
float normalizationFactor = 0.5f;
|
|
192
|
+
|
|
193
|
+
auto fftSize = getPeriodicWaveSize();
|
|
194
|
+
auto halfSize = fftSize / 2;
|
|
195
|
+
|
|
196
|
+
size = std::min(size, halfSize);
|
|
197
|
+
|
|
198
|
+
for (int rangeIndex = 0; rangeIndex < numberOfRanges_; rangeIndex++) {
|
|
199
|
+
FFTFrame fftFrame(fftSize);
|
|
200
|
+
|
|
201
|
+
auto *realFFTFrameData = fftFrame.getRealData();
|
|
202
|
+
auto *imaginaryFFTFrameData = fftFrame.getImaginaryData();
|
|
203
|
+
|
|
204
|
+
// copy real and imaginary data to the FFT frame and scale it
|
|
205
|
+
VectorMath::multiplyByScalar(
|
|
206
|
+
realData, static_cast<float>(fftSize), realFFTFrameData, size);
|
|
207
|
+
VectorMath::multiplyByScalar(
|
|
208
|
+
imaginaryData,
|
|
209
|
+
-static_cast<float>(fftSize),
|
|
210
|
+
imaginaryFFTFrameData,
|
|
211
|
+
size);
|
|
212
|
+
|
|
213
|
+
// Find the starting partial where we should start culling.
|
|
214
|
+
// We need to clear out the highest frequencies to band-limit the waveform.
|
|
215
|
+
auto numberOfPartials = getNumberOfPartialsPerRange(rangeIndex);
|
|
216
|
+
|
|
217
|
+
// Clamp the size to the number of partials.
|
|
218
|
+
auto clampedSize = std::min(size, numberOfPartials);
|
|
219
|
+
if (clampedSize < halfSize) {
|
|
220
|
+
// Zero out the higher frequencies for certain range.
|
|
221
|
+
std::fill(
|
|
222
|
+
realFFTFrameData + clampedSize, realFFTFrameData + halfSize, 0.0f);
|
|
223
|
+
std::fill(
|
|
224
|
+
imaginaryFFTFrameData + clampedSize,
|
|
225
|
+
imaginaryFFTFrameData + halfSize,
|
|
226
|
+
0.0f);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Zero out the nquist and DC components.
|
|
230
|
+
realFFTFrameData[0] = 0.0f;
|
|
231
|
+
imaginaryFFTFrameData[0] = 0.0f;
|
|
232
|
+
|
|
233
|
+
bandLimitedTables_[rangeIndex] = new float[fftSize];
|
|
234
|
+
|
|
235
|
+
// Perform the inverse FFT to get the time domain representation of the
|
|
236
|
+
// band-limited waveform.
|
|
237
|
+
fftFrame.inverse(bandLimitedTables_[rangeIndex]);
|
|
238
|
+
|
|
239
|
+
if (!disableNormalization_ && rangeIndex == 0) {
|
|
240
|
+
float maxValue =
|
|
241
|
+
VectorMath::maximumMagnitude(bandLimitedTables_[rangeIndex], fftSize);
|
|
242
|
+
if (maxValue != 0) {
|
|
243
|
+
normalizationFactor = 1.0f / maxValue;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
VectorMath::multiplyByScalar(
|
|
248
|
+
bandLimitedTables_[rangeIndex],
|
|
249
|
+
normalizationFactor,
|
|
250
|
+
bandLimitedTables_[rangeIndex],
|
|
251
|
+
fftSize);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
float PeriodicWave::getWaveDataForFundamentalFrequency(
|
|
256
|
+
float fundamentalFrequency,
|
|
257
|
+
float *&lowerWaveData,
|
|
258
|
+
float *&higherWaveData) {
|
|
259
|
+
// negative frequencies are allowed and will be treated as positive.
|
|
260
|
+
fundamentalFrequency = std::fabs(fundamentalFrequency);
|
|
261
|
+
|
|
262
|
+
// calculating lower and higher range index for the given fundamental
|
|
263
|
+
// frequency.
|
|
264
|
+
float ratio = fundamentalFrequency > 0
|
|
265
|
+
? fundamentalFrequency / lowestFundamentalFrequency_
|
|
266
|
+
: 0.5f;
|
|
267
|
+
float centsAboveLowestFrequency = log2f(ratio) * 1200;
|
|
268
|
+
|
|
269
|
+
float pitchRange = 1 + centsAboveLowestFrequency / CentsPerRange;
|
|
270
|
+
|
|
271
|
+
pitchRange =
|
|
272
|
+
std::clamp(pitchRange, 0.0f, static_cast<float>(numberOfRanges_ - 1));
|
|
273
|
+
|
|
274
|
+
int lowerRangeIndex = static_cast<int>(pitchRange);
|
|
275
|
+
int higherRangeIndex = lowerRangeIndex < numberOfRanges_ - 1
|
|
276
|
+
? lowerRangeIndex + 1
|
|
277
|
+
: lowerRangeIndex;
|
|
278
|
+
|
|
279
|
+
// get the wave data for the lower and higher range index.
|
|
280
|
+
lowerWaveData = bandLimitedTables_[lowerRangeIndex];
|
|
281
|
+
higherWaveData = bandLimitedTables_[higherRangeIndex];
|
|
282
|
+
|
|
283
|
+
// calculate the interpolation factor between the lower and higher range data.
|
|
284
|
+
return pitchRange - static_cast<float>(lowerRangeIndex);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
float PeriodicWave::doInterpolation(
|
|
288
|
+
float phase,
|
|
289
|
+
float phaseIncrement,
|
|
290
|
+
float waveTableInterpolationFactor,
|
|
291
|
+
const float *lowerWaveData,
|
|
292
|
+
const float *higherWaveData) const {
|
|
293
|
+
float lowerWaveDataSample = 0;
|
|
294
|
+
float higherWaveDataSample = 0;
|
|
295
|
+
|
|
296
|
+
// We use linear, 3-point Lagrange, or 5-point Lagrange interpolation based on
|
|
297
|
+
// the value of phase increment. https://dlmf.nist.gov/3.3#ii
|
|
298
|
+
|
|
299
|
+
int index = static_cast<int>(phase);
|
|
300
|
+
auto factor = phase - static_cast<float>(index);
|
|
301
|
+
|
|
302
|
+
if (phaseIncrement >= interpolate2Point) { // linear interpolation
|
|
303
|
+
int indices[2];
|
|
304
|
+
|
|
305
|
+
for (int i = 0; i < 2; i++) {
|
|
306
|
+
indices[i] = (index + i) &
|
|
307
|
+
(getPeriodicWaveSize() -
|
|
308
|
+
1); // more efficient alternative to % getPeriodicWaveSize()
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
auto lowerWaveDataSample1 = lowerWaveData[indices[0]];
|
|
312
|
+
auto lowerWaveDataSample2 = lowerWaveData[indices[1]];
|
|
313
|
+
auto higherWaveDataSample1 = higherWaveData[indices[0]];
|
|
314
|
+
auto higherWaveDataSample2 = higherWaveData[indices[1]];
|
|
315
|
+
|
|
316
|
+
lowerWaveDataSample =
|
|
317
|
+
(1 - factor) * lowerWaveDataSample1 + factor * lowerWaveDataSample2;
|
|
318
|
+
higherWaveDataSample =
|
|
319
|
+
(1 - factor) * higherWaveDataSample1 + factor * higherWaveDataSample2;
|
|
320
|
+
} else if (phaseIncrement >= interpolate3Point) { // 3-point Lagrange
|
|
321
|
+
// interpolation
|
|
322
|
+
int indices[3];
|
|
323
|
+
|
|
324
|
+
for (int i = 0; i < 3; i++) {
|
|
325
|
+
indices[i] = (index + i - 1) & (getPeriodicWaveSize() - 1);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
float A[3];
|
|
329
|
+
|
|
330
|
+
A[0] = factor * (factor - 1) / 2;
|
|
331
|
+
A[1] = 1 - factor * factor;
|
|
332
|
+
A[2] = factor * (factor + 1) / 2;
|
|
333
|
+
|
|
334
|
+
for (int i = 0; i < 3; i++) {
|
|
335
|
+
lowerWaveDataSample += lowerWaveData[indices[i]] * A[i];
|
|
336
|
+
higherWaveDataSample += higherWaveData[indices[i]] * A[i];
|
|
337
|
+
}
|
|
338
|
+
} else { // 5-point Lagrange interpolation
|
|
339
|
+
int indices[5];
|
|
340
|
+
|
|
341
|
+
for (int i = 0; i < 5; i++) {
|
|
342
|
+
indices[i] = (index + i - 2) & (getPeriodicWaveSize() - 1);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
float A[5];
|
|
346
|
+
|
|
347
|
+
A[0] = factor * (factor * factor - 1) * (factor - 2) / 24;
|
|
348
|
+
A[1] = -factor * (factor - 1) * (factor * factor - 4) / 6;
|
|
349
|
+
A[2] = (factor * factor - 1) * (factor * factor - 4) / 4;
|
|
350
|
+
A[3] = -factor * (factor + 1) * (factor * factor - 4) / 6;
|
|
351
|
+
A[4] = factor * (factor * factor - 1) * (factor + 2) / 24;
|
|
352
|
+
|
|
353
|
+
for (int i = 0; i < 5; i++) {
|
|
354
|
+
lowerWaveDataSample += lowerWaveData[indices[i]] * A[i];
|
|
355
|
+
higherWaveDataSample += higherWaveData[indices[i]] * A[i];
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return (1 - waveTableInterpolationFactor) * higherWaveDataSample +
|
|
360
|
+
waveTableInterpolationFactor * lowerWaveDataSample;
|
|
361
|
+
}
|
|
362
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2012 Google Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Redistribution and use in source and binary forms, with or without
|
|
5
|
+
* modification, are permitted provided that the following conditions
|
|
6
|
+
* are met:
|
|
7
|
+
*
|
|
8
|
+
* 1. Redistributions of source code must retain the above copyright
|
|
9
|
+
* notice, this list of conditions and the following disclaimer.
|
|
10
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
12
|
+
* documentation and/or other materials provided with the distribution.
|
|
13
|
+
* 3. Neither the name of Apple Inc. ("Apple") nor the names of
|
|
14
|
+
* its contributors may be used to endorse or promote products derived
|
|
15
|
+
* from this software without specific prior written permission.
|
|
16
|
+
*
|
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
|
|
18
|
+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
19
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
20
|
+
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
|
21
|
+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
22
|
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
23
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
24
|
+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
25
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
26
|
+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
#pragma once
|
|
30
|
+
|
|
31
|
+
#include <algorithm>
|
|
32
|
+
#include <cmath>
|
|
33
|
+
#include <memory>
|
|
34
|
+
|
|
35
|
+
#include "FFTFrame.h"
|
|
36
|
+
#include "OscillatorType.h"
|
|
37
|
+
#include "VectorMath.h"
|
|
38
|
+
|
|
39
|
+
namespace audioapi {
|
|
40
|
+
class PeriodicWave {
|
|
41
|
+
public:
|
|
42
|
+
explicit PeriodicWave(
|
|
43
|
+
int sampleRate,
|
|
44
|
+
OscillatorType type,
|
|
45
|
+
bool disableNormalization);
|
|
46
|
+
explicit PeriodicWave(
|
|
47
|
+
int sampleRate,
|
|
48
|
+
float *real,
|
|
49
|
+
float *imaginary,
|
|
50
|
+
int length,
|
|
51
|
+
bool disableNormalization);
|
|
52
|
+
|
|
53
|
+
[[nodiscard]] int getPeriodicWaveSize() const;
|
|
54
|
+
[[nodiscard]] float getScale() const;
|
|
55
|
+
|
|
56
|
+
float
|
|
57
|
+
getSample(float fundamentalFrequency, float phase, float phaseIncrement);
|
|
58
|
+
|
|
59
|
+
private:
|
|
60
|
+
explicit PeriodicWave(int sampleRate, bool disableNormalization);
|
|
61
|
+
|
|
62
|
+
// Partial is any frequency component of a sound.
|
|
63
|
+
// Both harmonics(fundamentalFrequency * k) and overtones are partials.
|
|
64
|
+
[[nodiscard]] int getMaxNumberOfPartials() const;
|
|
65
|
+
|
|
66
|
+
// Returns the number of partials to keep for a given range.
|
|
67
|
+
// Controlling the number of partials in each range allows for a more
|
|
68
|
+
// efficient representation of the waveform and prevents aliasing.
|
|
69
|
+
[[nodiscard]] int getNumberOfPartialsPerRange(int rangeIndex) const;
|
|
70
|
+
|
|
71
|
+
// This function generates real and imaginary parts of the waveTable,
|
|
72
|
+
// real and imaginary arrays represent the coefficients of the harmonic
|
|
73
|
+
// components in the frequency domain, specifically as part of a complex
|
|
74
|
+
// representation used by Fourier Transform methods to describe signals.
|
|
75
|
+
void generateBasicWaveForm(OscillatorType type);
|
|
76
|
+
|
|
77
|
+
// This function creates band-limited tables for the given real and
|
|
78
|
+
// imaginary data. The tables are created for each range of the partials.
|
|
79
|
+
// The higher frequencies are culled to band-limit the waveform.
|
|
80
|
+
// For each range, the inverse FFT is performed to get the time domain
|
|
81
|
+
// representation of the band-limited waveform.
|
|
82
|
+
void
|
|
83
|
+
createBandLimitedTables(const float *real, const float *imaginary, int size);
|
|
84
|
+
|
|
85
|
+
// This function returns the interpolation factor between the lower and higher
|
|
86
|
+
// range data and sets the lower and higher wave data for the given
|
|
87
|
+
// fundamental frequency.
|
|
88
|
+
float getWaveDataForFundamentalFrequency(
|
|
89
|
+
float fundamentalFrequency,
|
|
90
|
+
float *&lowerWaveData,
|
|
91
|
+
float *&higherWaveData);
|
|
92
|
+
|
|
93
|
+
// This function performs interpolation between the lower and higher range
|
|
94
|
+
// data based on the interpolation factor and current buffer index. Type of
|
|
95
|
+
// interpolation is determined by the phase increment. Returns the
|
|
96
|
+
// interpolated sample.
|
|
97
|
+
float doInterpolation(
|
|
98
|
+
float bufferIndex,
|
|
99
|
+
float phaseIncrement,
|
|
100
|
+
float waveTableInterpolationFactor,
|
|
101
|
+
const float *lowerWaveData,
|
|
102
|
+
const float *higherWaveData) const;
|
|
103
|
+
|
|
104
|
+
// determines the time resolution of the waveform.
|
|
105
|
+
int sampleRate_;
|
|
106
|
+
// determines number of frequency segments (or bands) the signal is divided.
|
|
107
|
+
int numberOfRanges_;
|
|
108
|
+
// the lowest frequency (in hertz) where playback will include all of the
|
|
109
|
+
// partials.
|
|
110
|
+
float lowestFundamentalFrequency_;
|
|
111
|
+
// scaling factor used to adjust size of period of waveform to the sample
|
|
112
|
+
// rate.
|
|
113
|
+
float scale_;
|
|
114
|
+
// array of band-limited waveforms.
|
|
115
|
+
float **bandLimitedTables_;
|
|
116
|
+
// if true, the waveTable is not normalized.
|
|
117
|
+
bool disableNormalization_;
|
|
118
|
+
};
|
|
119
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#include "AudioBus.h"
|
|
2
|
+
#include "Constants.h"
|
|
3
|
+
#include "AudioArray.h"
|
|
4
|
+
#include "StereoPannerNode.h"
|
|
5
|
+
#include "BaseAudioContext.h"
|
|
6
|
+
|
|
7
|
+
// https://webaudio.github.io/web-audio-api/#stereopanner-algorithm
|
|
8
|
+
|
|
9
|
+
namespace audioapi {
|
|
10
|
+
|
|
11
|
+
StereoPannerNode::StereoPannerNode(BaseAudioContext *context)
|
|
12
|
+
: AudioNode(context) {
|
|
13
|
+
channelCountMode_ = ChannelCountMode::CLAMPED_MAX;
|
|
14
|
+
panParam_ = std::make_shared<AudioParam>(context, 0.0, -MAX_PAN, MAX_PAN);
|
|
15
|
+
isInitialized_ = true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
std::shared_ptr<AudioParam> StereoPannerNode::getPanParam() const {
|
|
19
|
+
return panParam_;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void StereoPannerNode::processNode(AudioBus* processingBus, int framesToProcess) {
|
|
23
|
+
// TODO: Currently assumed channelCount is 2
|
|
24
|
+
// it should:
|
|
25
|
+
// - support mono-channel buses
|
|
26
|
+
// - throw errors when trying to setup stereo panner with more than 2 channels
|
|
27
|
+
|
|
28
|
+
double time = context_->getCurrentTime();
|
|
29
|
+
double deltaTime = 1.0 / context_->getSampleRate();
|
|
30
|
+
|
|
31
|
+
AudioArray* left = processingBus->getChannelByType(AudioBus::ChannelLeft);
|
|
32
|
+
AudioArray* right = processingBus->getChannelByType(AudioBus::ChannelRight);
|
|
33
|
+
|
|
34
|
+
for (int i = 0; i < framesToProcess; i += 1) {
|
|
35
|
+
float pan = panParam_->getValueAtTime(time);
|
|
36
|
+
float x = (pan <= 0 ? pan + 1 : pan) * M_PI / 2;
|
|
37
|
+
|
|
38
|
+
float gainL = static_cast<float>(cos(x));
|
|
39
|
+
float gainR = static_cast<float>(sin(x));
|
|
40
|
+
|
|
41
|
+
float inputL = (*left)[i];
|
|
42
|
+
float inputR = (*right)[i];
|
|
43
|
+
|
|
44
|
+
if (pan <= 0) {
|
|
45
|
+
(*left)[i] = inputL + inputR * gainL;
|
|
46
|
+
(*right)[i] = inputR * gainR;
|
|
47
|
+
} else {
|
|
48
|
+
(*left)[i] = inputL * gainL;
|
|
49
|
+
(*right)[i] = inputR + inputL * gainR;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
time += deltaTime;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <memory>
|
|
5
|
+
|
|
6
|
+
#include "AudioNode.h"
|
|
7
|
+
#include "AudioParam.h"
|
|
8
|
+
|
|
9
|
+
namespace audioapi {
|
|
10
|
+
|
|
11
|
+
class AudioBus;
|
|
12
|
+
|
|
13
|
+
class StereoPannerNode : public AudioNode {
|
|
14
|
+
public:
|
|
15
|
+
explicit StereoPannerNode(BaseAudioContext *context);
|
|
16
|
+
|
|
17
|
+
[[nodiscard]] std::shared_ptr<AudioParam> getPanParam() const;
|
|
18
|
+
|
|
19
|
+
protected:
|
|
20
|
+
void processNode(AudioBus* processingBus, int framesToProcess) override;
|
|
21
|
+
|
|
22
|
+
private:
|
|
23
|
+
std::shared_ptr<AudioParam> panParam_;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <stdexcept>
|
|
5
|
+
#include <string>
|
|
6
|
+
|
|
7
|
+
namespace audioapi {
|
|
8
|
+
|
|
9
|
+
enum class BiquadFilterType {
|
|
10
|
+
LOWPASS,
|
|
11
|
+
HIGHPASS,
|
|
12
|
+
BANDPASS,
|
|
13
|
+
LOWSHELF,
|
|
14
|
+
HIGHSHELF,
|
|
15
|
+
PEAKING,
|
|
16
|
+
NOTCH,
|
|
17
|
+
ALLPASS
|
|
18
|
+
};
|
|
19
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2010 Google Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Redistribution and use in source and binary forms, with or without
|
|
5
|
+
* modification, are permitted provided that the following conditions
|
|
6
|
+
* are met:
|
|
7
|
+
*
|
|
8
|
+
* 1. Redistributions of source code must retain the above copyright
|
|
9
|
+
* notice, this list of conditions and the following disclaimer.
|
|
10
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
12
|
+
* documentation and/or other materials provided with the distribution.
|
|
13
|
+
* 3. Neither the name of Apple Inc. ("Apple") nor the names of
|
|
14
|
+
* its contributors may be used to endorse or promote products derived
|
|
15
|
+
* from this software without specific prior written permission.
|
|
16
|
+
*
|
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
|
|
18
|
+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
19
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
20
|
+
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
|
21
|
+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
22
|
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
23
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
24
|
+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
25
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
26
|
+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
#pragma once
|
|
30
|
+
|
|
31
|
+
#include <algorithm>
|
|
32
|
+
#include <cmath>
|
|
33
|
+
#include <utility>
|
|
34
|
+
|
|
35
|
+
#include "VectorMath.h"
|
|
36
|
+
|
|
37
|
+
namespace audioapi {
|
|
38
|
+
|
|
39
|
+
class FFTFrame {
|
|
40
|
+
public:
|
|
41
|
+
explicit FFTFrame(int size): size_(size), log2Size_(static_cast<int>(log2(size))), realData_(new float[size]), imaginaryData_(new float[size]) {}
|
|
42
|
+
~FFTFrame() {
|
|
43
|
+
delete[] realData_;
|
|
44
|
+
delete[] imaginaryData_;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
[[nodiscard]] float *getRealData() const {
|
|
48
|
+
return realData_;
|
|
49
|
+
}
|
|
50
|
+
[[nodiscard]] float *getImaginaryData() const {
|
|
51
|
+
return imaginaryData_;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void inverse(float *data);
|
|
55
|
+
|
|
56
|
+
private:
|
|
57
|
+
int size_;
|
|
58
|
+
int log2Size_;
|
|
59
|
+
float *realData_;
|
|
60
|
+
float *imaginaryData_;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
} // namespace audioapi
|