react-native-audio-api 0.0.1 → 0.1.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 +58 -1
- package/RNAudioAPI.podspec +41 -0
- package/android/CMakeLists.txt +63 -0
- package/android/build.gradle +194 -0
- package/android/gradle.properties +5 -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 +45 -0
- package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +30 -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 +67 -0
- package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.h +37 -0
- package/common/cpp/HostObjects/AudioContextHostObject.cpp +191 -0
- package/common/cpp/HostObjects/AudioContextHostObject.h +43 -0
- package/common/cpp/HostObjects/AudioDestinationNodeHostObject.cpp +33 -0
- package/common/cpp/HostObjects/AudioDestinationNodeHostObject.h +31 -0
- package/common/cpp/HostObjects/AudioNodeHostObject.cpp +108 -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/BiquadFilterNodeHostObject.cpp +81 -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 +67 -0
- package/common/cpp/HostObjects/OscillatorNodeHostObject.h +40 -0
- package/common/cpp/HostObjects/StereoPannerNodeHostObject.cpp +41 -0
- package/common/cpp/HostObjects/StereoPannerNodeHostObject.h +36 -0
- package/common/cpp/core/AudioBuffer.cpp +115 -0
- package/common/cpp/core/AudioBuffer.h +42 -0
- package/common/cpp/core/AudioBufferSourceNode.cpp +58 -0
- package/common/cpp/core/AudioBufferSourceNode.h +26 -0
- package/common/cpp/core/AudioContext.cpp +90 -0
- package/common/cpp/core/AudioContext.h +73 -0
- package/common/cpp/core/AudioDestinationNode.cpp +35 -0
- package/common/cpp/core/AudioDestinationNode.h +24 -0
- package/common/cpp/core/AudioNode.cpp +68 -0
- package/common/cpp/core/AudioNode.h +74 -0
- package/common/cpp/core/AudioParam.cpp +136 -0
- package/common/cpp/core/AudioParam.h +50 -0
- package/common/cpp/core/AudioScheduledSourceNode.cpp +39 -0
- package/common/cpp/core/AudioScheduledSourceNode.h +30 -0
- package/common/cpp/core/BiquadFilterNode.cpp +364 -0
- package/common/cpp/core/BiquadFilterNode.h +128 -0
- package/common/cpp/core/GainNode.cpp +30 -0
- package/common/cpp/core/GainNode.h +23 -0
- package/common/cpp/core/OscillatorNode.cpp +66 -0
- package/common/cpp/core/OscillatorNode.h +112 -0
- package/common/cpp/core/ParamChange.cpp +46 -0
- package/common/cpp/core/ParamChange.h +34 -0
- package/common/cpp/core/StereoPannerNode.cpp +58 -0
- package/common/cpp/core/StereoPannerNode.h +26 -0
- package/common/cpp/utils/VectorMath.cpp +609 -0
- package/common/cpp/utils/VectorMath.h +65 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +35 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +25 -0
- package/common/cpp/wrappers/AudioBufferWrapper.cpp +46 -0
- package/common/cpp/wrappers/AudioBufferWrapper.h +30 -0
- package/common/cpp/wrappers/AudioContextWrapper.cpp +70 -0
- package/common/cpp/wrappers/AudioContextWrapper.h +40 -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/BiquadFilterNodeWrapper.cpp +51 -0
- package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +32 -0
- package/common/cpp/wrappers/GainNodeWrapper.cpp +14 -0
- package/common/cpp/wrappers/GainNodeWrapper.h +20 -0
- package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +38 -0
- package/common/cpp/wrappers/OscillatorNodeWrapper.h +28 -0
- package/common/cpp/wrappers/StereoPannerNodeWrapper.cpp +16 -0
- package/common/cpp/wrappers/StereoPannerNodeWrapper.h +21 -0
- package/ios/AudioAPIModule.h +5 -0
- package/ios/AudioAPIModule.mm +44 -0
- package/ios/AudioPlayer/AudioPlayer.h +27 -0
- package/ios/AudioPlayer/AudioPlayer.m +121 -0
- package/ios/AudioPlayer/IOSAudioPlayer.h +29 -0
- package/ios/AudioPlayer/IOSAudioPlayer.mm +34 -0
- package/lib/module/index.js +39 -0
- package/lib/module/index.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/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/install.js +22 -0
- package/lib/module/utils/install.js.map +1 -0
- package/lib/typescript/index.d.ts +18 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +76 -0
- package/lib/typescript/types.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/index.ts +79 -0
- package/src/modules/global.d.ts +10 -0
- package/src/types.ts +108 -0
- package/src/utils/install.ts +39 -0
- package/index.ts +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <cmath>
|
|
5
|
+
#include <memory>
|
|
6
|
+
#include <stdexcept>
|
|
7
|
+
#include <string>
|
|
8
|
+
|
|
9
|
+
#include "AudioNode.h"
|
|
10
|
+
#include "AudioParam.h"
|
|
11
|
+
|
|
12
|
+
namespace audioapi {
|
|
13
|
+
|
|
14
|
+
class BiquadFilterNode : public AudioNode {
|
|
15
|
+
public:
|
|
16
|
+
explicit BiquadFilterNode(AudioContext *context);
|
|
17
|
+
|
|
18
|
+
std::string getType() const;
|
|
19
|
+
void setType(const std::string &type);
|
|
20
|
+
std::shared_ptr<AudioParam> getFrequencyParam() const;
|
|
21
|
+
std::shared_ptr<AudioParam> getDetuneParam() const;
|
|
22
|
+
std::shared_ptr<AudioParam> getQParam() const;
|
|
23
|
+
std::shared_ptr<AudioParam> getGainParam() const;
|
|
24
|
+
|
|
25
|
+
protected:
|
|
26
|
+
bool processAudio(float *audioData, int32_t numFrames) override;
|
|
27
|
+
|
|
28
|
+
private:
|
|
29
|
+
enum class FilterType {
|
|
30
|
+
LOWPASS,
|
|
31
|
+
HIGHPASS,
|
|
32
|
+
BANDPASS,
|
|
33
|
+
LOWSHELF,
|
|
34
|
+
HIGHSHELF,
|
|
35
|
+
PEAKING,
|
|
36
|
+
NOTCH,
|
|
37
|
+
ALLPASS
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
static FilterType fromString(const std::string &type) {
|
|
41
|
+
std::string lowerType = type;
|
|
42
|
+
std::transform(
|
|
43
|
+
lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
|
|
44
|
+
|
|
45
|
+
if (lowerType == "lowpass")
|
|
46
|
+
return FilterType::LOWPASS;
|
|
47
|
+
if (lowerType == "highpass")
|
|
48
|
+
return FilterType::HIGHPASS;
|
|
49
|
+
if (lowerType == "bandpass")
|
|
50
|
+
return FilterType::BANDPASS;
|
|
51
|
+
if (lowerType == "lowshelf")
|
|
52
|
+
return FilterType::LOWSHELF;
|
|
53
|
+
if (lowerType == "highshelf")
|
|
54
|
+
return FilterType::HIGHSHELF;
|
|
55
|
+
if (lowerType == "peaking")
|
|
56
|
+
return FilterType::PEAKING;
|
|
57
|
+
if (lowerType == "notch")
|
|
58
|
+
return FilterType::NOTCH;
|
|
59
|
+
if (lowerType == "allpass")
|
|
60
|
+
return FilterType::ALLPASS;
|
|
61
|
+
|
|
62
|
+
throw std::invalid_argument("Invalid filter type: " + type);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static std::string toString(FilterType type) {
|
|
66
|
+
switch (type) {
|
|
67
|
+
case FilterType::LOWPASS:
|
|
68
|
+
return "lowpass";
|
|
69
|
+
case FilterType::HIGHPASS:
|
|
70
|
+
return "highpass";
|
|
71
|
+
case FilterType::BANDPASS:
|
|
72
|
+
return "bandpass";
|
|
73
|
+
case FilterType::LOWSHELF:
|
|
74
|
+
return "lowshelf";
|
|
75
|
+
case FilterType::HIGHSHELF:
|
|
76
|
+
return "highshelf";
|
|
77
|
+
case FilterType::PEAKING:
|
|
78
|
+
return "peaking";
|
|
79
|
+
case FilterType::NOTCH:
|
|
80
|
+
return "notch";
|
|
81
|
+
case FilterType::ALLPASS:
|
|
82
|
+
return "allpass";
|
|
83
|
+
default:
|
|
84
|
+
throw std::invalid_argument("Unknown filter type");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private:
|
|
89
|
+
std::shared_ptr<AudioParam> frequencyParam_;
|
|
90
|
+
std::shared_ptr<AudioParam> detuneParam_;
|
|
91
|
+
std::shared_ptr<AudioParam> QParam_;
|
|
92
|
+
std::shared_ptr<AudioParam> gainParam_;
|
|
93
|
+
FilterType type_;
|
|
94
|
+
|
|
95
|
+
// delayed samples
|
|
96
|
+
float x1_ = 0;
|
|
97
|
+
float x2_ = 0;
|
|
98
|
+
float y1_ = 0;
|
|
99
|
+
float y2_ = 0;
|
|
100
|
+
|
|
101
|
+
// coefficients
|
|
102
|
+
float b0_ = 1.0;
|
|
103
|
+
float b1_ = 0;
|
|
104
|
+
float b2_ = 0;
|
|
105
|
+
float a1_ = 1.0;
|
|
106
|
+
float a2_ = 0;
|
|
107
|
+
|
|
108
|
+
static float clamp(float value, float min, float max);
|
|
109
|
+
void resetCoefficients();
|
|
110
|
+
void setNormalizedCoefficients(
|
|
111
|
+
float b0,
|
|
112
|
+
float b1,
|
|
113
|
+
float b2,
|
|
114
|
+
float a0,
|
|
115
|
+
float a1,
|
|
116
|
+
float a2);
|
|
117
|
+
void setLowpassCoefficients(float frequency, float Q);
|
|
118
|
+
void setHighpassCoefficients(float frequency, float Q);
|
|
119
|
+
void setBandpassCoefficients(float frequency, float Q);
|
|
120
|
+
void setLowshelfCoefficients(float frequency, float gain);
|
|
121
|
+
void setHighshelfCoefficients(float frequency, float gain);
|
|
122
|
+
void setPeakingCoefficients(float frequency, float Q, float gain);
|
|
123
|
+
void setNotchCoefficients(float frequency, float Q);
|
|
124
|
+
void setAllpassCoefficients(float frequency, float Q);
|
|
125
|
+
void applyFilter();
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#include "GainNode.h"
|
|
2
|
+
#include "AudioContext.h"
|
|
3
|
+
|
|
4
|
+
namespace audioapi {
|
|
5
|
+
|
|
6
|
+
GainNode::GainNode(AudioContext *context) : AudioNode(context) {
|
|
7
|
+
gainParam_ = std::make_shared<AudioParam>(context, 1.0, -MAX_GAIN, MAX_GAIN);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
std::shared_ptr<AudioParam> GainNode::getGainParam() const {
|
|
11
|
+
return gainParam_;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
bool GainNode::processAudio(float *audioData, int32_t numFrames) {
|
|
15
|
+
if (!AudioNode::processAudio(audioData, numFrames)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
auto time = context_->getCurrentTime();
|
|
20
|
+
auto deltaTime = 1.0 / context_->getSampleRate();
|
|
21
|
+
|
|
22
|
+
for (int i = 0; i < numFrames * channelCount_; i++) {
|
|
23
|
+
audioData[i] *= gainParam_->getValueAtTime(time);
|
|
24
|
+
time += deltaTime;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
|
|
5
|
+
#include "AudioNode.h"
|
|
6
|
+
#include "AudioParam.h"
|
|
7
|
+
|
|
8
|
+
namespace audioapi {
|
|
9
|
+
|
|
10
|
+
class GainNode : public AudioNode {
|
|
11
|
+
public:
|
|
12
|
+
explicit GainNode(AudioContext *context);
|
|
13
|
+
|
|
14
|
+
std::shared_ptr<AudioParam> getGainParam() const;
|
|
15
|
+
|
|
16
|
+
protected:
|
|
17
|
+
bool processAudio(float *audioData, int32_t numFrames) override;
|
|
18
|
+
|
|
19
|
+
private:
|
|
20
|
+
std::shared_ptr<AudioParam> gainParam_;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#include "OscillatorNode.h"
|
|
2
|
+
#include "AudioContext.h"
|
|
3
|
+
|
|
4
|
+
namespace audioapi {
|
|
5
|
+
|
|
6
|
+
OscillatorNode::OscillatorNode(AudioContext *context)
|
|
7
|
+
: AudioScheduledSourceNode(context) {
|
|
8
|
+
frequencyParam_ = std::make_shared<AudioParam>(
|
|
9
|
+
context, 444.0, -NYQUIST_FREQUENCY, NYQUIST_FREQUENCY);
|
|
10
|
+
detuneParam_ =
|
|
11
|
+
std::make_shared<AudioParam>(context, 0.0, -MAX_DETUNE, MAX_DETUNE);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
std::shared_ptr<AudioParam> OscillatorNode::getFrequencyParam() const {
|
|
15
|
+
return frequencyParam_;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
std::shared_ptr<AudioParam> OscillatorNode::getDetuneParam() const {
|
|
19
|
+
return detuneParam_;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
std::string OscillatorNode::getType() {
|
|
23
|
+
return OscillatorNode::toString(type_);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void OscillatorNode::setType(const std::string &type) {
|
|
27
|
+
type_ = OscillatorNode::fromString(type);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
bool OscillatorNode::processAudio(float *audioData, int32_t numFrames) {
|
|
31
|
+
if (!isPlaying_) {
|
|
32
|
+
return false;
|
|
33
|
+
} else {
|
|
34
|
+
auto time = context_->getCurrentTime();
|
|
35
|
+
auto deltaTime = 1.0 / context_->getSampleRate();
|
|
36
|
+
|
|
37
|
+
for (int i = 0; i < numFrames; ++i) {
|
|
38
|
+
auto detuneRatio =
|
|
39
|
+
std::pow(2.0f, detuneParam_->getValueAtTime(time) / 1200.0f);
|
|
40
|
+
auto detunedFrequency =
|
|
41
|
+
round(frequencyParam_->getValueAtTime(time) * detuneRatio);
|
|
42
|
+
auto phaseIncrement = static_cast<float>(
|
|
43
|
+
2 * M_PI * detunedFrequency / context_->getSampleRate());
|
|
44
|
+
|
|
45
|
+
float value = OscillatorNode::getWaveBufferElement(phase_, type_);
|
|
46
|
+
|
|
47
|
+
for (int j = 0; j < channelCount_; j++) {
|
|
48
|
+
audioData[i * channelCount_ + j] = value;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
phase_ += phaseIncrement;
|
|
52
|
+
time += deltaTime;
|
|
53
|
+
|
|
54
|
+
if (phase_ >= 2 * M_PI) {
|
|
55
|
+
phase_ -= 2 * M_PI;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (phase_ < 0) {
|
|
59
|
+
phase_ += 2 * M_PI;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <cmath>
|
|
4
|
+
#include <memory>
|
|
5
|
+
#include <string>
|
|
6
|
+
|
|
7
|
+
#include "AudioParam.h"
|
|
8
|
+
#include "AudioScheduledSourceNode.h"
|
|
9
|
+
|
|
10
|
+
namespace audioapi {
|
|
11
|
+
|
|
12
|
+
class OscillatorNode : public AudioScheduledSourceNode {
|
|
13
|
+
public:
|
|
14
|
+
explicit OscillatorNode(AudioContext *context);
|
|
15
|
+
|
|
16
|
+
std::shared_ptr<AudioParam> getFrequencyParam() const;
|
|
17
|
+
std::shared_ptr<AudioParam> getDetuneParam() const;
|
|
18
|
+
std::string getType();
|
|
19
|
+
void setType(const std::string &type);
|
|
20
|
+
|
|
21
|
+
protected:
|
|
22
|
+
bool processAudio(float *audioData, int32_t numFrames) override;
|
|
23
|
+
|
|
24
|
+
private:
|
|
25
|
+
enum class WaveType { SINE, SQUARE, SAWTOOTH, TRIANGLE, CUSTOM };
|
|
26
|
+
|
|
27
|
+
static float sineWave(double wavePhase) {
|
|
28
|
+
return static_cast<float>(std::sin(wavePhase));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static float squareWave(double wavePhase) {
|
|
32
|
+
return static_cast<float>(std::sin(wavePhase) >= 0 ? 1.0 : -1.0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static float sawtoothWave(double wavePhase) {
|
|
36
|
+
return static_cast<float>(
|
|
37
|
+
2.0 *
|
|
38
|
+
(wavePhase / (2 * M_PI) - std::floor(wavePhase / (2 * M_PI) + 0.5)));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static float triangleWave(double wavePhase) {
|
|
42
|
+
return static_cast<float>(
|
|
43
|
+
2.0 *
|
|
44
|
+
std::abs(
|
|
45
|
+
2.0 *
|
|
46
|
+
(wavePhase / (2 * M_PI) -
|
|
47
|
+
std::floor(wavePhase / (2 * M_PI) + 0.5))) -
|
|
48
|
+
1.0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static float getWaveValue(double wavePhase, WaveType type) {
|
|
52
|
+
switch (type) {
|
|
53
|
+
case WaveType::SINE:
|
|
54
|
+
return sineWave(wavePhase);
|
|
55
|
+
case WaveType::SQUARE:
|
|
56
|
+
return squareWave(wavePhase);
|
|
57
|
+
case WaveType::SAWTOOTH:
|
|
58
|
+
return sawtoothWave(wavePhase);
|
|
59
|
+
case WaveType::TRIANGLE:
|
|
60
|
+
return triangleWave(wavePhase);
|
|
61
|
+
default:
|
|
62
|
+
throw std::invalid_argument("Unknown wave type");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static WaveType fromString(const std::string &type) {
|
|
67
|
+
std::string lowerType = type;
|
|
68
|
+
std::transform(
|
|
69
|
+
lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
|
|
70
|
+
|
|
71
|
+
if (lowerType == "sine")
|
|
72
|
+
return WaveType::SINE;
|
|
73
|
+
if (lowerType == "square")
|
|
74
|
+
return WaveType::SQUARE;
|
|
75
|
+
if (lowerType == "sawtooth")
|
|
76
|
+
return WaveType::SAWTOOTH;
|
|
77
|
+
if (lowerType == "triangle")
|
|
78
|
+
return WaveType::TRIANGLE;
|
|
79
|
+
if (lowerType == "custom")
|
|
80
|
+
return WaveType::CUSTOM;
|
|
81
|
+
|
|
82
|
+
throw std::invalid_argument("Unknown wave type: " + type);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static std::string toString(WaveType type) {
|
|
86
|
+
switch (type) {
|
|
87
|
+
case WaveType::SINE:
|
|
88
|
+
return "sine";
|
|
89
|
+
case WaveType::SQUARE:
|
|
90
|
+
return "square";
|
|
91
|
+
case WaveType::SAWTOOTH:
|
|
92
|
+
return "sawtooth";
|
|
93
|
+
case WaveType::TRIANGLE:
|
|
94
|
+
return "triangle";
|
|
95
|
+
case WaveType::CUSTOM:
|
|
96
|
+
return "custom";
|
|
97
|
+
default:
|
|
98
|
+
throw std::invalid_argument("Unknown wave type");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static float getWaveBufferElement(double wavePhase, WaveType waveType) {
|
|
103
|
+
return getWaveValue(wavePhase, waveType);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private:
|
|
107
|
+
std::shared_ptr<AudioParam> frequencyParam_;
|
|
108
|
+
std::shared_ptr<AudioParam> detuneParam_;
|
|
109
|
+
WaveType type_ = WaveType::SINE;
|
|
110
|
+
float phase_ = 0.0;
|
|
111
|
+
};
|
|
112
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#include "ParamChange.h"
|
|
2
|
+
|
|
3
|
+
#include <utility>
|
|
4
|
+
|
|
5
|
+
namespace audioapi {
|
|
6
|
+
|
|
7
|
+
ParamChange::ParamChange(
|
|
8
|
+
double startTime,
|
|
9
|
+
double endTime,
|
|
10
|
+
float startValue,
|
|
11
|
+
float endValue,
|
|
12
|
+
std::function<float(double, double, float, float, double)> calculateValue)
|
|
13
|
+
: startTime_(startTime),
|
|
14
|
+
endTime_(endTime),
|
|
15
|
+
startValue_(startValue),
|
|
16
|
+
endValue_(endValue),
|
|
17
|
+
calculateValue_(std::move(calculateValue)) {}
|
|
18
|
+
|
|
19
|
+
double ParamChange::getEndTime() const {
|
|
20
|
+
return endTime_;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
double ParamChange::getStartTime() const {
|
|
24
|
+
return startTime_;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
float ParamChange::getEndValue() const {
|
|
28
|
+
return endValue_;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
float ParamChange::getStartValue() const {
|
|
32
|
+
return startValue_;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
std::function<float(double, double, float, float, double)>
|
|
36
|
+
ParamChange::getCalculateValue() const {
|
|
37
|
+
return calculateValue_;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
bool ParamChange::operator<(const ParamChange &other) const {
|
|
41
|
+
if (startTime_ != other.startTime_)
|
|
42
|
+
return startTime_ < other.startTime_;
|
|
43
|
+
return endTime_ < other.endTime_;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <functional>
|
|
4
|
+
#include <memory>
|
|
5
|
+
|
|
6
|
+
namespace audioapi {
|
|
7
|
+
|
|
8
|
+
class ParamChange {
|
|
9
|
+
public:
|
|
10
|
+
explicit ParamChange(
|
|
11
|
+
double startTime,
|
|
12
|
+
double endTime,
|
|
13
|
+
float startValue,
|
|
14
|
+
float endValue,
|
|
15
|
+
std::function<float(double, double, float, float, double)>
|
|
16
|
+
calculateValue);
|
|
17
|
+
|
|
18
|
+
double getEndTime() const;
|
|
19
|
+
double getStartTime() const;
|
|
20
|
+
float getEndValue() const;
|
|
21
|
+
float getStartValue() const;
|
|
22
|
+
std::function<float(double, double, float, float, double)> getCalculateValue()
|
|
23
|
+
const;
|
|
24
|
+
bool operator<(const ParamChange &other) const;
|
|
25
|
+
|
|
26
|
+
private:
|
|
27
|
+
double startTime_;
|
|
28
|
+
double endTime_;
|
|
29
|
+
float startValue_;
|
|
30
|
+
float endValue_;
|
|
31
|
+
std::function<float(double, double, float, float, double)> calculateValue_;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#include "StereoPannerNode.h"
|
|
2
|
+
#include "AudioContext.h"
|
|
3
|
+
|
|
4
|
+
// https://webaudio.github.io/web-audio-api/#stereopanner-algorithm
|
|
5
|
+
|
|
6
|
+
namespace audioapi {
|
|
7
|
+
|
|
8
|
+
StereoPannerNode::StereoPannerNode(AudioContext *context) : AudioNode(context) {
|
|
9
|
+
channelCountMode_ = ChannelCountMode::CLAMPED_MAX;
|
|
10
|
+
panParam_ = std::make_shared<AudioParam>(context, 0.0, -MAX_PAN, MAX_PAN);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
std::shared_ptr<AudioParam> StereoPannerNode::getPanParam() const {
|
|
14
|
+
return panParam_;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
bool StereoPannerNode::processAudio(float *audioData, int32_t numFrames) {
|
|
18
|
+
// assumed channelCount = 2
|
|
19
|
+
if (!AudioNode::processAudio(audioData, numFrames)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
auto time = context_->getCurrentTime();
|
|
24
|
+
auto deltaTime = 1.0 / context_->getSampleRate();
|
|
25
|
+
|
|
26
|
+
for (int i = 0; i < numFrames; i++) {
|
|
27
|
+
auto pan = panParam_->getValueAtTime(time);
|
|
28
|
+
auto x = (pan <= 0 ? pan + 1 : pan) * M_PI / 2;
|
|
29
|
+
|
|
30
|
+
auto gainL = static_cast<float>(cos(x));
|
|
31
|
+
auto gainR = static_cast<float>(sin(x));
|
|
32
|
+
|
|
33
|
+
auto inputL = audioData[i * 2];
|
|
34
|
+
auto inputR = audioData[i * 2 + 1];
|
|
35
|
+
|
|
36
|
+
if (pan <= 0) {
|
|
37
|
+
audioData[i * 2] = inputL + inputR * gainL;
|
|
38
|
+
audioData[i * 2 + 1] = inputR * gainR;
|
|
39
|
+
} else {
|
|
40
|
+
audioData[i * 2] = inputL * gainL;
|
|
41
|
+
audioData[i * 2 + 1] = inputR + inputL * gainR;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
time += deltaTime;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
normalize(audioData, numFrames);
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void StereoPannerNode::normalize(float *audioData, int32_t numFrames) {
|
|
53
|
+
auto maxValue = std::max(
|
|
54
|
+
1.0f, VectorMath::maximumMagnitude(audioData, numFrames * channelCount_));
|
|
55
|
+
VectorMath::multiplyByScalar(
|
|
56
|
+
audioData, 1.0f / maxValue, audioData, numFrames * channelCount_);
|
|
57
|
+
}
|
|
58
|
+
} // 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
|
+
#include "VectorMath.h"
|
|
9
|
+
|
|
10
|
+
namespace audioapi {
|
|
11
|
+
|
|
12
|
+
class StereoPannerNode : public AudioNode {
|
|
13
|
+
public:
|
|
14
|
+
explicit StereoPannerNode(AudioContext *context);
|
|
15
|
+
std::shared_ptr<AudioParam> getPanParam() const;
|
|
16
|
+
|
|
17
|
+
protected:
|
|
18
|
+
bool processAudio(float *audioData, int32_t numFrames) override;
|
|
19
|
+
|
|
20
|
+
private:
|
|
21
|
+
std::shared_ptr<AudioParam> panParam_;
|
|
22
|
+
|
|
23
|
+
void normalize(float *audioData, int32_t numFrames);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
} // namespace audioapi
|