react-native-audio-api 0.1.0 → 0.3.0-rc1
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 +10 -8
- package/RNAudioAPI.podspec +5 -0
- package/android/CMakeLists.txt +21 -10
- 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/cpp/AudioPlayer/AudioPlayer.cpp +32 -2
- package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +6 -2
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +5 -3
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +5 -1
- package/common/cpp/HostObjects/AudioBufferHostObject.cpp +6 -0
- package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +13 -1
- package/common/cpp/HostObjects/AudioContextHostObject.cpp +12 -149
- package/common/cpp/HostObjects/AudioContextHostObject.h +8 -14
- package/common/cpp/HostObjects/AudioNodeHostObject.cpp +0 -6
- package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +240 -0
- package/common/cpp/HostObjects/BaseAudioContextHostObject.h +41 -0
- package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +44 -0
- package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +21 -0
- package/common/cpp/HostObjects/OscillatorNodeHostObject.h +1 -0
- package/common/cpp/HostObjects/PeriodicWaveHostObject.cpp +33 -0
- package/common/cpp/HostObjects/PeriodicWaveHostObject.h +33 -0
- package/common/cpp/core/AudioArray.cpp +117 -0
- package/common/cpp/core/AudioArray.h +48 -0
- package/common/cpp/core/AudioBuffer.cpp +23 -80
- package/common/cpp/core/AudioBuffer.h +12 -13
- package/common/cpp/core/AudioBufferSourceNode.cpp +112 -25
- package/common/cpp/core/AudioBufferSourceNode.h +10 -6
- package/common/cpp/core/AudioBus.cpp +518 -0
- package/common/cpp/core/AudioBus.h +83 -0
- package/common/cpp/core/AudioContext.cpp +7 -77
- package/common/cpp/core/AudioContext.h +3 -60
- package/common/cpp/core/AudioDestinationNode.cpp +27 -15
- package/common/cpp/core/AudioDestinationNode.h +13 -5
- package/common/cpp/core/AudioNode.cpp +184 -22
- package/common/cpp/core/AudioNode.h +37 -37
- package/common/cpp/core/AudioNodeManager.cpp +75 -0
- package/common/cpp/core/AudioNodeManager.h +42 -0
- package/common/cpp/core/AudioParam.cpp +8 -11
- package/common/cpp/core/AudioParam.h +8 -8
- package/common/cpp/core/AudioScheduledSourceNode.cpp +19 -5
- package/common/cpp/core/AudioScheduledSourceNode.h +6 -2
- package/common/cpp/core/BaseAudioContext.cpp +191 -0
- package/common/cpp/core/BaseAudioContext.h +87 -0
- package/common/cpp/core/BiquadFilterNode.cpp +92 -69
- package/common/cpp/core/BiquadFilterNode.h +53 -57
- package/common/cpp/core/GainNode.cpp +12 -12
- package/common/cpp/core/GainNode.h +5 -3
- package/common/cpp/core/OscillatorNode.cpp +38 -29
- package/common/cpp/core/OscillatorNode.h +29 -69
- package/common/cpp/core/ParamChange.h +6 -6
- package/common/cpp/core/PeriodicWave.cpp +362 -0
- package/common/cpp/core/PeriodicWave.h +119 -0
- package/common/cpp/core/StereoPannerNode.cpp +31 -30
- package/common/cpp/core/StereoPannerNode.h +6 -6
- 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 +67 -0
- package/common/cpp/utils/JsiPromise.cpp +59 -0
- package/common/cpp/utils/JsiPromise.h +42 -0
- package/common/cpp/utils/Locker.h +49 -0
- package/common/cpp/utils/VectorMath.cpp +88 -3
- package/common/cpp/utils/VectorMath.h +7 -1
- package/common/cpp/utils/android/FFTFrame.cpp +23 -0
- package/common/cpp/utils/ios/FFTFrame.cpp +29 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +10 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +3 -2
- package/common/cpp/wrappers/AudioBufferWrapper.h +5 -5
- package/common/cpp/wrappers/AudioContextWrapper.cpp +7 -60
- package/common/cpp/wrappers/AudioContextWrapper.h +5 -26
- package/common/cpp/wrappers/AudioNodeWrapper.h +5 -5
- package/common/cpp/wrappers/AudioParamWrapper.h +4 -4
- package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +83 -0
- package/common/cpp/wrappers/BaseAudioContextWrapper.h +50 -0
- package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +9 -0
- package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +9 -4
- package/common/cpp/wrappers/GainNodeWrapper.h +1 -1
- package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +6 -0
- package/common/cpp/wrappers/OscillatorNodeWrapper.h +5 -2
- package/common/cpp/wrappers/PeriodicWaveWrapper.h +17 -0
- package/common/cpp/wrappers/StereoPannerNodeWrapper.h +1 -1
- package/ios/AudioAPIModule.h +20 -1
- package/ios/AudioAPIModule.mm +6 -4
- package/ios/AudioDecoder/AudioDecoder.h +17 -0
- package/ios/AudioDecoder/AudioDecoder.m +167 -0
- package/ios/AudioDecoder/IOSAudioDecoder.h +26 -0
- package/ios/AudioDecoder/IOSAudioDecoder.mm +40 -0
- package/ios/AudioPlayer/AudioPlayer.h +3 -2
- package/ios/AudioPlayer/AudioPlayer.m +14 -17
- package/ios/AudioPlayer/IOSAudioPlayer.h +7 -3
- package/ios/AudioPlayer/IOSAudioPlayer.mm +31 -7
- 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 +62 -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.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 +212 -15
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.native.js +18 -0
- package/lib/module/index.native.js.map +1 -0
- package/lib/module/interfaces.js +2 -0
- package/lib/module/interfaces.js.map +1 -0
- package/lib/module/utils/resolveAudioSource.js +10 -0
- package/lib/module/utils/resolveAudioSource.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 +27 -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 +15 -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 +88 -5
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.native.d.ts +14 -0
- package/lib/typescript/index.native.d.ts.map +1 -0
- package/lib/typescript/interfaces.d.ts +79 -0
- package/lib/typescript/interfaces.d.ts.map +1 -0
- package/lib/typescript/utils/resolveAudioSource.d.ts +3 -0
- package/lib/typescript/utils/resolveAudioSource.d.ts.map +1 -0
- package/package.json +4 -2
- 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 +108 -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 +33 -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.native.ts +25 -0
- package/src/index.ts +380 -40
- package/src/interfaces.ts +121 -0
- package/src/modules/global.d.ts +3 -3
- package/src/utils/resolveAudioSource.ts +14 -0
- package/lib/module/types.js.map +0 -1
- package/lib/typescript/types.d.ts +0 -76
- package/lib/typescript/types.d.ts.map +0 -1
- package/src/types.ts +0 -108
- /package/lib/module/{types.js → core/types.js} +0 -0
|
@@ -24,6 +24,8 @@ std::vector<jsi::PropNameID> OscillatorNodeHostObject::getPropertyNames(
|
|
|
24
24
|
propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "frequency"));
|
|
25
25
|
propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "detune"));
|
|
26
26
|
propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "type"));
|
|
27
|
+
propertyNames.push_back(
|
|
28
|
+
jsi::PropNameID::forAscii(runtime, "setPeriodicWave"));
|
|
27
29
|
return propertyNames;
|
|
28
30
|
}
|
|
29
31
|
|
|
@@ -46,6 +48,25 @@ jsi::Value OscillatorNodeHostObject::get(
|
|
|
46
48
|
return jsi::String::createFromUtf8(runtime, waveType);
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
if (propName == "setPeriodicWave") {
|
|
52
|
+
return jsi::Function::createFromHostFunction(
|
|
53
|
+
runtime,
|
|
54
|
+
propNameId,
|
|
55
|
+
1,
|
|
56
|
+
[this](
|
|
57
|
+
jsi::Runtime &rt,
|
|
58
|
+
const jsi::Value &thisVal,
|
|
59
|
+
const jsi::Value *args,
|
|
60
|
+
size_t count) -> jsi::Value {
|
|
61
|
+
auto wrapper = getOscillatorNodeWrapperFromAudioNodeWrapper();
|
|
62
|
+
auto periodicWaveHostObject =
|
|
63
|
+
args[0].getObject(rt).asHostObject<PeriodicWaveHostObject>(rt);
|
|
64
|
+
|
|
65
|
+
wrapper->setPeriodicWave(periodicWaveHostObject->wrapper_);
|
|
66
|
+
return jsi::Value::undefined();
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
49
70
|
return AudioScheduledSourceNodeHostObject::get(runtime, propNameId);
|
|
50
71
|
}
|
|
51
72
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#include "PeriodicWaveHostObject.h"
|
|
2
|
+
|
|
3
|
+
namespace audioapi {
|
|
4
|
+
using namespace facebook;
|
|
5
|
+
|
|
6
|
+
PeriodicWaveHostObject::PeriodicWaveHostObject(
|
|
7
|
+
const std::shared_ptr<PeriodicWaveWrapper> &wrapper)
|
|
8
|
+
: wrapper_(wrapper) {}
|
|
9
|
+
|
|
10
|
+
std::vector<jsi::PropNameID> PeriodicWaveHostObject::getPropertyNames(
|
|
11
|
+
jsi::Runtime &runtime) {
|
|
12
|
+
std::vector<jsi::PropNameID> propertyNames;
|
|
13
|
+
return propertyNames;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
jsi::Value PeriodicWaveHostObject::get(
|
|
17
|
+
jsi::Runtime &runtime,
|
|
18
|
+
const jsi::PropNameID &propNameId) {
|
|
19
|
+
auto propName = propNameId.utf8(runtime);
|
|
20
|
+
|
|
21
|
+
throw std::runtime_error("Not yet implemented!");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void PeriodicWaveHostObject::set(
|
|
25
|
+
jsi::Runtime &runtime,
|
|
26
|
+
const jsi::PropNameID &propNameId,
|
|
27
|
+
const jsi::Value &value) {
|
|
28
|
+
auto propName = propNameId.utf8(runtime);
|
|
29
|
+
|
|
30
|
+
throw std::runtime_error("Not yet implemented!");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <memory>
|
|
5
|
+
#include <vector>
|
|
6
|
+
|
|
7
|
+
#include "PeriodicWaveWrapper.h"
|
|
8
|
+
|
|
9
|
+
namespace audioapi {
|
|
10
|
+
using namespace facebook;
|
|
11
|
+
|
|
12
|
+
class PeriodicWaveHostObject : public jsi::HostObject {
|
|
13
|
+
public:
|
|
14
|
+
std::shared_ptr<PeriodicWaveWrapper> wrapper_;
|
|
15
|
+
|
|
16
|
+
explicit PeriodicWaveHostObject(
|
|
17
|
+
const std::shared_ptr<PeriodicWaveWrapper> &wrapper);
|
|
18
|
+
|
|
19
|
+
jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override;
|
|
20
|
+
|
|
21
|
+
void set(
|
|
22
|
+
jsi::Runtime &runtime,
|
|
23
|
+
const jsi::PropNameID &name,
|
|
24
|
+
const jsi::Value &value) override;
|
|
25
|
+
|
|
26
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
|
27
|
+
|
|
28
|
+
static std::shared_ptr<PeriodicWaveHostObject> createFromWrapper(
|
|
29
|
+
const std::shared_ptr<PeriodicWaveWrapper> &wrapper) {
|
|
30
|
+
return std::make_shared<PeriodicWaveHostObject>(wrapper);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#include <algorithm>
|
|
2
|
+
|
|
3
|
+
#include "AudioArray.h"
|
|
4
|
+
#include "VectorMath.h"
|
|
5
|
+
|
|
6
|
+
namespace audioapi {
|
|
7
|
+
|
|
8
|
+
AudioArray::AudioArray(int size) : data_(nullptr), size_(size) {
|
|
9
|
+
resize(size);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
AudioArray::~AudioArray() {
|
|
13
|
+
if (data_) {
|
|
14
|
+
delete[] data_;
|
|
15
|
+
data_ = nullptr;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
int AudioArray::getSize() const {
|
|
20
|
+
return size_;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
float *AudioArray::getData() const {
|
|
24
|
+
return data_;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
float &AudioArray::operator[](int index) {
|
|
28
|
+
return data_[index];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const float &AudioArray::operator[](int index) const {
|
|
32
|
+
return data_[index];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void AudioArray::normalize() {
|
|
36
|
+
float maxAbsValue = getMaxAbsValue();
|
|
37
|
+
|
|
38
|
+
if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
VectorMath::multiplyByScalar(data_, 1.0f / maxAbsValue, data_, size_);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
void AudioArray::resize(int size) {
|
|
46
|
+
if (size == size_) {
|
|
47
|
+
if (!data_) {
|
|
48
|
+
data_ = new float[size];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
zero(0, size);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
delete[] data_;
|
|
56
|
+
size_ = size;
|
|
57
|
+
data_ = new float[size_];
|
|
58
|
+
|
|
59
|
+
zero(0, size_);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void AudioArray::scale(float value) {
|
|
63
|
+
VectorMath::multiplyByScalar(data_, value, data_, size_);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
float AudioArray::getMaxAbsValue() const {
|
|
67
|
+
return VectorMath::maximumMagnitude(data_, size_);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
void AudioArray::zero() {
|
|
71
|
+
zero(0, size_);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
void AudioArray::zero(int start, int length) {
|
|
75
|
+
memset(data_ + start, 0, length * sizeof(float));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
void AudioArray::sum(const AudioArray *source) {
|
|
79
|
+
sum(source, 0, 0, size_);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
void AudioArray::sum(const AudioArray *source, int start, int length) {
|
|
83
|
+
sum(source, start, start, length);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
void AudioArray::sum(
|
|
87
|
+
const AudioArray *source,
|
|
88
|
+
int sourceStart,
|
|
89
|
+
int destinationStart,
|
|
90
|
+
int length) {
|
|
91
|
+
VectorMath::add(
|
|
92
|
+
data_ + destinationStart,
|
|
93
|
+
source->getData() + sourceStart,
|
|
94
|
+
data_ + destinationStart,
|
|
95
|
+
length);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
void AudioArray::copy(const AudioArray *source) {
|
|
99
|
+
copy(source, 0, size_);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void AudioArray::copy(const AudioArray *source, int start, int length) {
|
|
103
|
+
copy(source, start, start, length);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
void AudioArray::copy(
|
|
107
|
+
const AudioArray *source,
|
|
108
|
+
int sourceStart,
|
|
109
|
+
int destinationStart,
|
|
110
|
+
int length) {
|
|
111
|
+
memcpy(
|
|
112
|
+
data_ + destinationStart,
|
|
113
|
+
source->getData() + sourceStart,
|
|
114
|
+
length * sizeof(float));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <memory>
|
|
5
|
+
|
|
6
|
+
namespace audioapi {
|
|
7
|
+
|
|
8
|
+
class AudioArray {
|
|
9
|
+
public:
|
|
10
|
+
explicit AudioArray(int size);
|
|
11
|
+
~AudioArray();
|
|
12
|
+
|
|
13
|
+
[[nodiscard]] int getSize() const;
|
|
14
|
+
[[nodiscard]] float *getData() const;
|
|
15
|
+
|
|
16
|
+
float &operator[](int index);
|
|
17
|
+
const float &operator[](int index) const;
|
|
18
|
+
|
|
19
|
+
void normalize();
|
|
20
|
+
void resize(int size);
|
|
21
|
+
void scale(float value);
|
|
22
|
+
[[nodiscard]] float getMaxAbsValue() const;
|
|
23
|
+
|
|
24
|
+
void zero();
|
|
25
|
+
void zero(int start, int length);
|
|
26
|
+
|
|
27
|
+
void sum(const AudioArray *source);
|
|
28
|
+
void sum(const AudioArray *source, int start, int length);
|
|
29
|
+
void sum(
|
|
30
|
+
const AudioArray *source,
|
|
31
|
+
int sourceStart,
|
|
32
|
+
int destinationStart,
|
|
33
|
+
int length);
|
|
34
|
+
|
|
35
|
+
void copy(const AudioArray *source);
|
|
36
|
+
void copy(const AudioArray *source, int start, int length);
|
|
37
|
+
void copy(
|
|
38
|
+
const AudioArray *source,
|
|
39
|
+
int sourceStart,
|
|
40
|
+
int destinationStart,
|
|
41
|
+
int length);
|
|
42
|
+
|
|
43
|
+
private:
|
|
44
|
+
float *data_;
|
|
45
|
+
int size_;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
} // namespace audioapi
|
|
@@ -1,77 +1,35 @@
|
|
|
1
1
|
#include "AudioBuffer.h"
|
|
2
|
+
#include "AudioArray.h"
|
|
3
|
+
#include "AudioBus.h"
|
|
2
4
|
|
|
3
5
|
namespace audioapi {
|
|
4
6
|
|
|
5
|
-
AudioBuffer::AudioBuffer(int numberOfChannels, int length, int sampleRate)
|
|
6
|
-
|
|
7
|
-
length_(length),
|
|
8
|
-
sampleRate_(sampleRate),
|
|
9
|
-
duration_(static_cast<double>(length) / sampleRate) {
|
|
10
|
-
if (numberOfChannels != 1 && numberOfChannels != 2) {
|
|
11
|
-
throw std::invalid_argument("Invalid number of channels");
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
channels_ = new float *[numberOfChannels];
|
|
15
|
-
|
|
16
|
-
for (int i = 0; i < numberOfChannels; i++) {
|
|
17
|
-
channels_[i] = new float[length];
|
|
18
|
-
|
|
19
|
-
for (int j = 0; j < length; j++) {
|
|
20
|
-
channels_[i][j] = 0.0f;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
7
|
+
AudioBuffer::AudioBuffer(int numberOfChannels, int length, int sampleRate) {
|
|
8
|
+
bus_ = std::make_shared<AudioBus>(sampleRate, length, numberOfChannels);
|
|
23
9
|
}
|
|
24
10
|
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
AudioBuffer::AudioBuffer(AudioBus *bus) {
|
|
12
|
+
bus_ = std::shared_ptr<AudioBus>(bus);
|
|
27
13
|
}
|
|
28
14
|
|
|
29
15
|
int AudioBuffer::getLength() const {
|
|
30
|
-
return
|
|
16
|
+
return bus_->getSize();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
int AudioBuffer::getNumberOfChannels() const {
|
|
20
|
+
return bus_->getNumberOfChannels();
|
|
31
21
|
}
|
|
32
22
|
|
|
33
23
|
int AudioBuffer::getSampleRate() const {
|
|
34
|
-
return
|
|
24
|
+
return bus_->getSampleRate();
|
|
35
25
|
}
|
|
36
26
|
|
|
37
27
|
double AudioBuffer::getDuration() const {
|
|
38
|
-
return
|
|
28
|
+
return static_cast<double>(getLength()) / getSampleRate();
|
|
39
29
|
}
|
|
40
30
|
|
|
41
31
|
float *AudioBuffer::getChannelData(int channel) const {
|
|
42
|
-
|
|
43
|
-
throw std::invalid_argument("Invalid channel number");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return channels_[channel];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
std::shared_ptr<AudioBuffer> AudioBuffer::mix(int outputNumberOfChannels) {
|
|
50
|
-
if (outputNumberOfChannels != 1 && outputNumberOfChannels != 2) {
|
|
51
|
-
throw std::invalid_argument("Invalid number of channels");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (outputNumberOfChannels == numberOfChannels_) {
|
|
55
|
-
return shared_from_this();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
auto mixedBuffer = std::make_shared<AudioBuffer>(
|
|
59
|
-
outputNumberOfChannels, length_, sampleRate_);
|
|
60
|
-
|
|
61
|
-
switch (this->numberOfChannels_) {
|
|
62
|
-
case 1:
|
|
63
|
-
mixedBuffer->copyToChannel(this->channels_[0], length_, 0, 0);
|
|
64
|
-
mixedBuffer->copyToChannel(this->channels_[0], length_, 1, 0);
|
|
65
|
-
break;
|
|
66
|
-
case 2:
|
|
67
|
-
for (int i = 0; i < length_; i++) {
|
|
68
|
-
mixedBuffer->channels_[0][i] =
|
|
69
|
-
(this->channels_[0][i] + this->channels_[1][i]) / 2;
|
|
70
|
-
}
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return mixedBuffer;
|
|
32
|
+
return bus_->getChannel(channel)->getData();
|
|
75
33
|
}
|
|
76
34
|
|
|
77
35
|
void AudioBuffer::copyFromChannel(
|
|
@@ -79,19 +37,11 @@ void AudioBuffer::copyFromChannel(
|
|
|
79
37
|
int destinationLength,
|
|
80
38
|
int channelNumber,
|
|
81
39
|
int startInChannel) const {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
throw std::invalid_argument("Invalid start in channel");
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
std::copy(
|
|
91
|
-
channels_[channelNumber] + startInChannel,
|
|
92
|
-
channels_[channelNumber] + startInChannel +
|
|
93
|
-
std::min(destinationLength, length_ - startInChannel),
|
|
94
|
-
destination);
|
|
40
|
+
memcpy(
|
|
41
|
+
destination,
|
|
42
|
+
bus_->getChannel(channelNumber)->getData() + startInChannel,
|
|
43
|
+
std::min(destinationLength, getLength() - startInChannel) *
|
|
44
|
+
sizeof(float));
|
|
95
45
|
}
|
|
96
46
|
|
|
97
47
|
void AudioBuffer::copyToChannel(
|
|
@@ -99,17 +49,10 @@ void AudioBuffer::copyToChannel(
|
|
|
99
49
|
int sourceLength,
|
|
100
50
|
int channelNumber,
|
|
101
51
|
int startInChannel) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (startInChannel < 0 || startInChannel >= length_) {
|
|
107
|
-
throw std::invalid_argument("Invalid start in channel");
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
std::copy(
|
|
52
|
+
memcpy(
|
|
53
|
+
bus_->getChannel(channelNumber)->getData() + startInChannel,
|
|
111
54
|
source,
|
|
112
|
-
|
|
113
|
-
channels_[channelNumber] + startInChannel);
|
|
55
|
+
std::min(sourceLength, getLength() - startInChannel) * sizeof(float));
|
|
114
56
|
}
|
|
57
|
+
|
|
115
58
|
} // namespace audioapi
|
|
@@ -7,15 +7,20 @@
|
|
|
7
7
|
|
|
8
8
|
namespace audioapi {
|
|
9
9
|
|
|
10
|
+
class AudioBus;
|
|
11
|
+
|
|
10
12
|
class AudioBuffer : public std::enable_shared_from_this<AudioBuffer> {
|
|
11
13
|
public:
|
|
12
14
|
explicit AudioBuffer(int numberOfChannels, int length, int sampleRate);
|
|
15
|
+
explicit AudioBuffer(AudioBus *bus);
|
|
16
|
+
|
|
17
|
+
[[nodiscard]] int getLength() const;
|
|
18
|
+
[[nodiscard]] int getSampleRate() const;
|
|
19
|
+
[[nodiscard]] double getDuration() const;
|
|
20
|
+
|
|
21
|
+
[[nodiscard]] int getNumberOfChannels() const;
|
|
22
|
+
[[nodiscard]] float *getChannelData(int channel) const;
|
|
13
23
|
|
|
14
|
-
int getNumberOfChannels() const;
|
|
15
|
-
int getLength() const;
|
|
16
|
-
int getSampleRate() const;
|
|
17
|
-
double getDuration() const;
|
|
18
|
-
float *getChannelData(int channel) const;
|
|
19
24
|
void copyFromChannel(
|
|
20
25
|
float *destination,
|
|
21
26
|
int destinationLength,
|
|
@@ -28,15 +33,9 @@ class AudioBuffer : public std::enable_shared_from_this<AudioBuffer> {
|
|
|
28
33
|
int startInChannel);
|
|
29
34
|
|
|
30
35
|
private:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
int numberOfChannels_;
|
|
34
|
-
int length_;
|
|
35
|
-
int sampleRate_;
|
|
36
|
-
double duration_;
|
|
37
|
-
float **channels_;
|
|
36
|
+
std::shared_ptr<AudioBus> bus_;
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
friend class AudioBufferSourceNode;
|
|
40
39
|
};
|
|
41
40
|
|
|
42
41
|
} // namespace audioapi
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
#include <algorithm>
|
|
2
|
+
|
|
3
|
+
#include "AudioArray.h"
|
|
1
4
|
#include "AudioBufferSourceNode.h"
|
|
2
|
-
#include "
|
|
5
|
+
#include "AudioBus.h"
|
|
6
|
+
#include "BaseAudioContext.h"
|
|
3
7
|
|
|
4
8
|
namespace audioapi {
|
|
5
9
|
|
|
6
|
-
AudioBufferSourceNode::AudioBufferSourceNode(
|
|
10
|
+
AudioBufferSourceNode::AudioBufferSourceNode(BaseAudioContext *context)
|
|
7
11
|
: AudioScheduledSourceNode(context), loop_(false), bufferIndex_(0) {
|
|
8
12
|
numberOfInputs_ = 0;
|
|
9
|
-
buffer_ = std::
|
|
13
|
+
buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
|
|
14
|
+
isInitialized_ = true;
|
|
10
15
|
}
|
|
11
16
|
|
|
12
17
|
bool AudioBufferSourceNode::getLoop() const {
|
|
@@ -14,11 +19,7 @@ bool AudioBufferSourceNode::getLoop() const {
|
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
std::shared_ptr<AudioBuffer> AudioBufferSourceNode::getBuffer() const {
|
|
17
|
-
|
|
18
|
-
throw std::runtime_error("Buffer is not set");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return buffer_.value();
|
|
22
|
+
return buffer_;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
void AudioBufferSourceNode::setLoop(bool loop) {
|
|
@@ -27,32 +28,118 @@ void AudioBufferSourceNode::setLoop(bool loop) {
|
|
|
27
28
|
|
|
28
29
|
void AudioBufferSourceNode::setBuffer(
|
|
29
30
|
const std::shared_ptr<AudioBuffer> &buffer) {
|
|
30
|
-
|
|
31
|
+
if (!buffer) {
|
|
32
|
+
buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
buffer_ = buffer;
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
// Note: AudioBus copy method will use memcpy if the source buffer and system
|
|
40
|
+
// processing bus have same channel count, otherwise it will use the summing
|
|
41
|
+
// function taking care of up/down mixing.
|
|
42
|
+
void AudioBufferSourceNode::processNode(
|
|
43
|
+
AudioBus *processingBus,
|
|
44
|
+
int framesToProcess) {
|
|
45
|
+
// No audio data to fill, zero the output and return.
|
|
46
|
+
if (!isPlaying() || !buffer_ || buffer_->getLength() == 0) {
|
|
47
|
+
processingBus->zero();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Easiest case, the buffer is the same length as the number of frames to
|
|
52
|
+
// process, just copy the data.
|
|
53
|
+
if (framesToProcess == buffer_->getLength()) {
|
|
54
|
+
processingBus->copy(buffer_->bus_.get());
|
|
55
|
+
|
|
56
|
+
if (!loop_) {
|
|
57
|
+
playbackState_ = PlaybackState::FINISHED;
|
|
58
|
+
disable();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The buffer is longer than the number of frames to process.
|
|
65
|
+
// We have to keep track of where we are in the buffer.
|
|
66
|
+
if (framesToProcess < buffer_->getLength()) {
|
|
67
|
+
int outputBusIndex = 0;
|
|
68
|
+
int framesToCopy = 0;
|
|
69
|
+
|
|
70
|
+
while (framesToProcess - outputBusIndex > 0) {
|
|
71
|
+
framesToCopy = std::min(
|
|
72
|
+
framesToProcess - outputBusIndex,
|
|
73
|
+
buffer_->getLength() - bufferIndex_);
|
|
74
|
+
|
|
75
|
+
processingBus->copy(
|
|
76
|
+
buffer_->bus_.get(), bufferIndex_, outputBusIndex, framesToCopy);
|
|
77
|
+
|
|
78
|
+
bufferIndex_ += framesToCopy;
|
|
79
|
+
outputBusIndex += framesToCopy;
|
|
80
|
+
|
|
81
|
+
if (bufferIndex_ < buffer_->getLength()) {
|
|
82
|
+
continue;
|
|
41
83
|
}
|
|
42
84
|
|
|
43
|
-
bufferIndex_
|
|
85
|
+
bufferIndex_ %= buffer_->getLength();
|
|
86
|
+
|
|
87
|
+
if (!loop_) {
|
|
88
|
+
playbackState_ = PlaybackState::FINISHED;
|
|
89
|
+
disable();
|
|
44
90
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
bufferIndex_ = 0;
|
|
48
|
-
} else {
|
|
49
|
-
isPlaying_ = false;
|
|
50
|
-
break;
|
|
91
|
+
if (framesToProcess - outputBusIndex > 0) {
|
|
92
|
+
processingBus->zero(outputBusIndex, framesToProcess - outputBusIndex);
|
|
51
93
|
}
|
|
52
94
|
}
|
|
53
95
|
}
|
|
54
96
|
|
|
55
|
-
return
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// processing bus is longer than the source buffer
|
|
101
|
+
if (!loop_) {
|
|
102
|
+
// If we don't loop the buffer, copy it once and zero the remaining
|
|
103
|
+
// processing bus frames.
|
|
104
|
+
processingBus->copy(buffer_->bus_.get());
|
|
105
|
+
processingBus->zero(
|
|
106
|
+
buffer_->getLength(), framesToProcess - buffer_->getLength());
|
|
107
|
+
|
|
108
|
+
playbackState_ = PlaybackState::FINISHED;
|
|
109
|
+
disable();
|
|
110
|
+
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// If we loop the buffer, we need to loop the buffer framesToProcess /
|
|
115
|
+
// bufferSize times There might also be a remainder of frames to copy after
|
|
116
|
+
// the loop, which will also carry over some buffer frames to the next render
|
|
117
|
+
// quantum.
|
|
118
|
+
int processingBusPosition = 0;
|
|
119
|
+
int bufferSize = buffer_->getLength();
|
|
120
|
+
int remainingFrames = framesToProcess - framesToProcess / bufferSize;
|
|
121
|
+
|
|
122
|
+
// Do we have some frames left in the buffer from the previous render quantum,
|
|
123
|
+
// if yes copy them over and reset the buffer position.
|
|
124
|
+
if (bufferIndex_ > 0) {
|
|
125
|
+
processingBus->copy(buffer_->bus_.get(), 0, bufferIndex_);
|
|
126
|
+
processingBusPosition += bufferIndex_;
|
|
127
|
+
bufferIndex_ = 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Copy the entire buffer n times to the processing bus.
|
|
131
|
+
while (processingBusPosition + bufferSize <= framesToProcess) {
|
|
132
|
+
processingBus->copy(buffer_->bus_.get());
|
|
133
|
+
processingBusPosition += bufferSize;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Fill in the remaining frames from the processing buffer and update buffer
|
|
137
|
+
// index for next render quantum.
|
|
138
|
+
if (remainingFrames > 0) {
|
|
139
|
+
processingBus->copy(
|
|
140
|
+
buffer_->bus_.get(), 0, processingBusPosition, remainingFrames);
|
|
141
|
+
bufferIndex_ = remainingFrames;
|
|
56
142
|
}
|
|
57
143
|
}
|
|
144
|
+
|
|
58
145
|
} // namespace audioapi
|
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <memory>
|
|
4
|
-
#include <optional>
|
|
5
4
|
|
|
6
5
|
#include "AudioBuffer.h"
|
|
7
6
|
#include "AudioScheduledSourceNode.h"
|
|
8
7
|
|
|
9
8
|
namespace audioapi {
|
|
10
9
|
|
|
10
|
+
class AudioBus;
|
|
11
|
+
|
|
11
12
|
class AudioBufferSourceNode : public AudioScheduledSourceNode {
|
|
12
13
|
public:
|
|
13
|
-
explicit AudioBufferSourceNode(
|
|
14
|
+
explicit AudioBufferSourceNode(BaseAudioContext *context);
|
|
14
15
|
|
|
15
|
-
bool getLoop() const;
|
|
16
|
-
std::shared_ptr<AudioBuffer> getBuffer() const;
|
|
16
|
+
[[nodiscard]] bool getLoop() const;
|
|
17
|
+
[[nodiscard]] std::shared_ptr<AudioBuffer> getBuffer() const;
|
|
17
18
|
void setLoop(bool loop);
|
|
18
19
|
void setBuffer(const std::shared_ptr<AudioBuffer> &buffer);
|
|
19
|
-
|
|
20
|
+
|
|
21
|
+
protected:
|
|
22
|
+
void processNode(AudioBus *processingBus, int framesToProcess) override;
|
|
20
23
|
|
|
21
24
|
private:
|
|
22
25
|
bool loop_;
|
|
23
|
-
std::
|
|
26
|
+
std::shared_ptr<AudioBuffer> buffer_;
|
|
24
27
|
int bufferIndex_;
|
|
25
28
|
};
|
|
29
|
+
|
|
26
30
|
} // namespace audioapi
|