react-native-audio-api 0.4.1 → 0.4.2

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.
Files changed (68) hide show
  1. package/android/src/main/cpp/core/AudioPlayer.cpp +4 -4
  2. package/android/src/main/cpp/core/AudioPlayer.h +4 -4
  3. package/common/cpp/HostObjects/AnalyserNodeHostObject.h +19 -6
  4. package/common/cpp/HostObjects/AudioAPIInstallerHostObject.h +1 -1
  5. package/common/cpp/HostObjects/AudioBufferHostObject.h +6 -5
  6. package/common/cpp/HostObjects/AudioParamHostObject.h +2 -1
  7. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +4 -3
  8. package/common/cpp/core/AnalyserNode.cpp +56 -34
  9. package/common/cpp/core/AnalyserNode.h +51 -19
  10. package/common/cpp/core/AudioArray.cpp +14 -14
  11. package/common/cpp/core/AudioArray.h +16 -15
  12. package/common/cpp/core/AudioBuffer.cpp +12 -9
  13. package/common/cpp/core/AudioBuffer.h +9 -8
  14. package/common/cpp/core/AudioBufferSourceNode.cpp +25 -20
  15. package/common/cpp/core/AudioBufferSourceNode.h +1 -0
  16. package/common/cpp/core/AudioBus.cpp +22 -26
  17. package/common/cpp/core/AudioBus.h +24 -24
  18. package/common/cpp/core/AudioContext.cpp +1 -1
  19. package/common/cpp/core/AudioContext.h +1 -1
  20. package/common/cpp/core/AudioDecoder.h +2 -2
  21. package/common/cpp/core/AudioDestinationNode.cpp +1 -1
  22. package/common/cpp/core/AudioDestinationNode.h +2 -1
  23. package/common/cpp/core/AudioNode.cpp +7 -5
  24. package/common/cpp/core/AudioNode.h +9 -10
  25. package/common/cpp/core/AudioNodeManager.cpp +1 -3
  26. package/common/cpp/core/AudioNodeManager.h +1 -1
  27. package/common/cpp/core/AudioParam.cpp +6 -3
  28. package/common/cpp/core/AudioParam.h +2 -1
  29. package/common/cpp/core/AudioScheduledSourceNode.cpp +1 -1
  30. package/common/cpp/core/AudioScheduledSourceNode.h +1 -0
  31. package/common/cpp/core/BaseAudioContext.cpp +7 -3
  32. package/common/cpp/core/BaseAudioContext.h +6 -4
  33. package/common/cpp/core/BiquadFilterNode.cpp +13 -14
  34. package/common/cpp/core/Constants.h +25 -12
  35. package/common/cpp/core/GainNode.cpp +1 -1
  36. package/common/cpp/core/OscillatorNode.cpp +4 -3
  37. package/common/cpp/core/PeriodicWave.cpp +7 -6
  38. package/common/cpp/core/PeriodicWave.h +4 -4
  39. package/common/cpp/core/StereoPannerNode.cpp +4 -4
  40. package/common/cpp/utils/AudioUtils.cpp +2 -2
  41. package/common/cpp/utils/AudioUtils.h +2 -2
  42. package/common/cpp/utils/Locker.h +2 -2
  43. package/ios/core/AudioPlayer.h +3 -3
  44. package/ios/core/AudioPlayer.m +2 -2
  45. package/ios/core/IOSAudioPlayer.h +2 -2
  46. package/ios/core/IOSAudioPlayer.mm +2 -2
  47. package/lib/module/core/AnalyserNode.js +6 -0
  48. package/lib/module/core/AnalyserNode.js.map +1 -1
  49. package/lib/module/index.js +6 -0
  50. package/lib/module/index.js.map +1 -1
  51. package/lib/module/index.native.js +1 -1
  52. package/lib/module/index.native.js.map +1 -1
  53. package/lib/typescript/core/AnalyserNode.d.ts +3 -0
  54. package/lib/typescript/core/AnalyserNode.d.ts.map +1 -1
  55. package/lib/typescript/core/types.d.ts +1 -0
  56. package/lib/typescript/core/types.d.ts.map +1 -1
  57. package/lib/typescript/index.d.ts +3 -1
  58. package/lib/typescript/index.d.ts.map +1 -1
  59. package/lib/typescript/index.native.d.ts +1 -1
  60. package/lib/typescript/index.native.d.ts.map +1 -1
  61. package/lib/typescript/interfaces.d.ts +2 -1
  62. package/lib/typescript/interfaces.d.ts.map +1 -1
  63. package/package.json +1 -1
  64. package/src/core/AnalyserNode.ts +9 -0
  65. package/src/core/types.ts +2 -0
  66. package/src/index.native.ts +1 -0
  67. package/src/index.ts +15 -1
  68. package/src/interfaces.ts +2 -0
@@ -21,7 +21,7 @@ AudioPlayer::AudioPlayer(
21
21
  ->setDataCallback(this)
22
22
  ->openStream(mStream_);
23
23
 
24
- sampleRate_ = mStream_->getSampleRate();
24
+ sampleRate_ = static_cast<float>(mStream_->getSampleRate());
25
25
  mBus_ = std::make_shared<AudioBus>(
26
26
  sampleRate_, RENDER_QUANTUM_SIZE, CHANNEL_COUNT);
27
27
  isInitialized_ = true;
@@ -29,7 +29,7 @@ AudioPlayer::AudioPlayer(
29
29
 
30
30
  AudioPlayer::AudioPlayer(
31
31
  const std::function<void(AudioBus *, int)> &renderAudio,
32
- int sampleRate)
32
+ float sampleRate)
33
33
  : renderAudio_(renderAudio) {
34
34
  AudioStreamBuilder builder;
35
35
 
@@ -40,7 +40,7 @@ AudioPlayer::AudioPlayer(
40
40
  ->setChannelCount(CHANNEL_COUNT)
41
41
  ->setSampleRateConversionQuality(SampleRateConversionQuality::Medium)
42
42
  ->setDataCallback(this)
43
- ->setSampleRate(sampleRate)
43
+ ->setSampleRate(static_cast<int>(sampleRate))
44
44
  ->openStream(mStream_);
45
45
 
46
46
  sampleRate_ = sampleRate;
@@ -49,7 +49,7 @@ AudioPlayer::AudioPlayer(
49
49
  isInitialized_ = true;
50
50
  }
51
51
 
52
- int AudioPlayer::getSampleRate() const {
52
+ float AudioPlayer::getSampleRate() const {
53
53
  return sampleRate_;
54
54
  }
55
55
 
@@ -1,8 +1,8 @@
1
1
  #pragma once
2
2
 
3
3
  #include <oboe/Oboe.h>
4
- #include <memory>
5
4
  #include <functional>
5
+ #include <memory>
6
6
 
7
7
  namespace audioapi {
8
8
 
@@ -16,9 +16,9 @@ class AudioPlayer : public AudioStreamDataCallback {
16
16
  explicit AudioPlayer(const std::function<void(AudioBus *, int)> &renderAudio);
17
17
  AudioPlayer(
18
18
  const std::function<void(AudioBus *, int)> &renderAudio,
19
- int sampleRate);
19
+ float sampleRate);
20
20
 
21
- [[nodiscard]] int getSampleRate() const;
21
+ [[nodiscard]] float getSampleRate() const;
22
22
  void start();
23
23
  void stop();
24
24
 
@@ -32,7 +32,7 @@ class AudioPlayer : public AudioStreamDataCallback {
32
32
  std::shared_ptr<AudioStream> mStream_;
33
33
  std::shared_ptr<AudioBus> mBus_;
34
34
  bool isInitialized_ = false;
35
- int sampleRate_;
35
+ float sampleRate_;
36
36
  };
37
37
 
38
38
  } // namespace audioapi
@@ -19,7 +19,8 @@ class AnalyserNodeHostObject : public AudioNodeHostObject {
19
19
  JSI_EXPORT_PROPERTY_GETTER(AnalyserNodeHostObject, frequencyBinCount),
20
20
  JSI_EXPORT_PROPERTY_GETTER(AnalyserNodeHostObject, minDecibels),
21
21
  JSI_EXPORT_PROPERTY_GETTER(AnalyserNodeHostObject, maxDecibels),
22
- JSI_EXPORT_PROPERTY_GETTER(AnalyserNodeHostObject, smoothingTimeConstant));
22
+ JSI_EXPORT_PROPERTY_GETTER(AnalyserNodeHostObject, smoothingTimeConstant),
23
+ JSI_EXPORT_PROPERTY_GETTER(AnalyserNodeHostObject, window));
23
24
 
24
25
  addFunctions(
25
26
  JSI_EXPORT_FUNCTION(
@@ -36,7 +37,8 @@ class AnalyserNodeHostObject : public AudioNodeHostObject {
36
37
  JSI_EXPORT_PROPERTY_SETTER(AnalyserNodeHostObject, minDecibels),
37
38
  JSI_EXPORT_PROPERTY_SETTER(AnalyserNodeHostObject, maxDecibels),
38
39
  JSI_EXPORT_PROPERTY_SETTER(
39
- AnalyserNodeHostObject, smoothingTimeConstant));
40
+ AnalyserNodeHostObject, smoothingTimeConstant),
41
+ JSI_EXPORT_PROPERTY_SETTER(AnalyserNodeHostObject, window));
40
42
  }
41
43
 
42
44
  JSI_PROPERTY_GETTER(fftSize) {
@@ -64,6 +66,12 @@ class AnalyserNodeHostObject : public AudioNodeHostObject {
64
66
  return {analyserNode->getSmoothingTimeConstant()};
65
67
  }
66
68
 
69
+ JSI_PROPERTY_GETTER(window) {
70
+ auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
71
+ auto windowType = analyserNode->getWindowType();
72
+ return jsi::String::createFromUtf8(runtime, windowType);
73
+ }
74
+
67
75
  JSI_HOST_FUNCTION(getFloatFrequencyData) {
68
76
  auto destination = args[0].getObject(runtime).asArray(runtime);
69
77
  auto length = static_cast<int>(destination.getProperty(runtime, "length").asNumber());
@@ -126,26 +134,31 @@ class AnalyserNodeHostObject : public AudioNodeHostObject {
126
134
 
127
135
  JSI_PROPERTY_SETTER(fftSize) {
128
136
  auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
129
- auto fftSize = static_cast<size_t>(value.getNumber());
137
+ auto fftSize = static_cast<int>(value.getNumber());
130
138
  analyserNode->setFftSize(fftSize);
131
139
  }
132
140
 
133
141
  JSI_PROPERTY_SETTER(minDecibels) {
134
142
  auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
135
- auto minDecibels = static_cast<int>(value.getNumber());
143
+ auto minDecibels = static_cast<float>(value.getNumber());
136
144
  analyserNode->setMinDecibels(minDecibels);
137
145
  }
138
146
 
139
147
  JSI_PROPERTY_SETTER(maxDecibels) {
140
148
  auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
141
- auto maxDecibels = static_cast<int>(value.getNumber());
149
+ auto maxDecibels = static_cast<float>(value.getNumber());
142
150
  analyserNode->setMaxDecibels(maxDecibels);
143
151
  }
144
152
 
145
153
  JSI_PROPERTY_SETTER(smoothingTimeConstant) {
146
154
  auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
147
- auto smoothingTimeConstant = static_cast<int>(value.getNumber());
155
+ auto smoothingTimeConstant = static_cast<float>(value.getNumber());
148
156
  analyserNode->setSmoothingTimeConstant(smoothingTimeConstant);
149
157
  }
158
+
159
+ JSI_PROPERTY_SETTER(window) {
160
+ auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
161
+ analyserNode->setWindowType(value.getString(runtime).utf8(runtime));
162
+ }
150
163
  };
151
164
  } // namespace audioapi
@@ -39,7 +39,7 @@ class AudioAPIInstallerHostObject
39
39
  if (args[0].isUndefined()) {
40
40
  audioContext = std::make_shared<AudioContext>();
41
41
  } else {
42
- int sampleRate = static_cast<int>(args[0].getNumber());
42
+ auto sampleRate = static_cast<float>(args[0].getNumber());
43
43
  audioContext = std::make_shared<AudioContext>(sampleRate);
44
44
  }
45
45
 
@@ -3,6 +3,7 @@
3
3
  #include <jsi/jsi.h>
4
4
  #include <memory>
5
5
  #include <vector>
6
+ #include <cstddef>
6
7
 
7
8
  #include <JsiHostObject.h>
8
9
  #include "AudioBuffer.h"
@@ -34,7 +35,7 @@ class AudioBufferHostObject : public JsiHostObject {
34
35
  }
35
36
 
36
37
  JSI_PROPERTY_GETTER(length) {
37
- return {audioBuffer_->getLength()};
38
+ return {static_cast<double>(audioBuffer_->getLength())};
38
39
  }
39
40
 
40
41
  JSI_PROPERTY_GETTER(duration) {
@@ -60,9 +61,9 @@ class AudioBufferHostObject : public JsiHostObject {
60
61
  JSI_HOST_FUNCTION(copyFromChannel) {
61
62
  auto destination = args[0].getObject(runtime).asArray(runtime);
62
63
  auto destinationLength =
63
- static_cast<int>(destination.getProperty(runtime, "length").asNumber());
64
+ static_cast<size_t>(destination.getProperty(runtime, "length").asNumber());
64
65
  auto channelNumber = static_cast<int>(args[1].getNumber());
65
- auto startInChannel = static_cast<int>(args[2].getNumber());
66
+ auto startInChannel = static_cast<size_t>(args[2].getNumber());
66
67
 
67
68
  auto *destinationData = new float[destinationLength];
68
69
 
@@ -79,9 +80,9 @@ class AudioBufferHostObject : public JsiHostObject {
79
80
  JSI_HOST_FUNCTION(copyToChannel) {
80
81
  auto source = args[0].getObject(runtime).asArray(runtime);
81
82
  auto sourceLength =
82
- static_cast<int>(source.getProperty(runtime, "length").asNumber());
83
+ static_cast<size_t>(source.getProperty(runtime, "length").asNumber());
83
84
  auto channelNumber = static_cast<int>(args[1].getNumber());
84
- auto startInChannel = static_cast<int>(args[2].getNumber());
85
+ auto startInChannel = static_cast<size_t>(args[2].getNumber());
85
86
 
86
87
  auto *sourceData = new float[sourceLength];
87
88
 
@@ -3,6 +3,7 @@
3
3
  #include <jsi/jsi.h>
4
4
  #include <memory>
5
5
  #include <vector>
6
+ #include <cstddef>
6
7
 
7
8
  #include <JsiHostObject.h>
8
9
  #include "AudioParam.h"
@@ -79,7 +80,7 @@ class AudioParamHostObject : public JsiHostObject {
79
80
 
80
81
  JSI_HOST_FUNCTION(setValueCurveAtTime) {
81
82
  auto values = args[0].getObject(runtime).asArray(runtime);
82
- auto length = static_cast<int>(values.length(runtime));
83
+ auto length = static_cast<size_t>(values.length(runtime));
83
84
  auto valuesData = new float[length];
84
85
  for (size_t i = 0; i < values.length(runtime); i++) {
85
86
  valuesData[i] =
@@ -4,6 +4,7 @@
4
4
  #include <memory>
5
5
  #include <utility>
6
6
  #include <vector>
7
+ #include <cstddef>
7
8
 
8
9
  #include <JsiHostObject.h>
9
10
  #include <JsiPromise.h>
@@ -100,9 +101,9 @@ class BaseAudioContextHostObject : public JsiHostObject {
100
101
 
101
102
  JSI_HOST_FUNCTION(createBuffer) {
102
103
  auto numberOfChannels = static_cast<int>(args[0].getNumber());
103
- auto length = static_cast<int>(args[1].getNumber());
104
- auto sampleRate = static_cast<int>(args[2].getNumber());
105
- auto buffer = context_->createBuffer(numberOfChannels, length, sampleRate);
104
+ auto length = static_cast<size_t>(args[1].getNumber());
105
+ auto sampleRate = static_cast<float>(args[2].getNumber());
106
+ auto buffer = BaseAudioContext::createBuffer(numberOfChannels, length, sampleRate);
106
107
  auto bufferHostObject = std::make_shared<AudioBufferHostObject>(buffer);
107
108
  return jsi::Object::createFromHostObject(runtime, bufferHostObject);
108
109
  }
@@ -16,34 +16,43 @@ AnalyserNode::AnalyserNode(audioapi::BaseAudioContext *context)
16
16
  minDecibels_(DEFAULT_MIN_DECIBELS),
17
17
  maxDecibels_(DEFAULT_MAX_DECIBELS),
18
18
  smoothingTimeConstant_(DEFAULT_SMOOTHING_TIME_CONSTANT),
19
+ windowType_(WindowType::BLACKMAN),
19
20
  vWriteIndex_(0) {
20
21
  inputBuffer_ = std::make_unique<AudioArray>(MAX_FFT_SIZE * 2);
21
- fftFrame_ = std::make_unique<FFTFrame>(fftSize_);
22
22
  magnitudeBuffer_ = std::make_unique<AudioArray>(fftSize_ / 2);
23
+ downMixBus_ = std::make_unique<AudioBus>(
24
+ context_->getSampleRate(), RENDER_QUANTUM_SIZE, 1);
25
+
26
+ fftFrame_ = std::make_unique<FFTFrame>(fftSize_);
27
+
23
28
  isInitialized_ = true;
24
29
  }
25
30
 
26
- size_t AnalyserNode::getFftSize() const {
31
+ int AnalyserNode::getFftSize() const {
27
32
  return fftSize_;
28
33
  }
29
34
 
30
- size_t AnalyserNode::getFrequencyBinCount() const {
35
+ int AnalyserNode::getFrequencyBinCount() const {
31
36
  return fftSize_ / 2;
32
37
  }
33
38
 
34
- double AnalyserNode::getMinDecibels() const {
39
+ float AnalyserNode::getMinDecibels() const {
35
40
  return minDecibels_;
36
41
  }
37
42
 
38
- double AnalyserNode::getMaxDecibels() const {
43
+ float AnalyserNode::getMaxDecibels() const {
39
44
  return maxDecibels_;
40
45
  }
41
46
 
42
- double AnalyserNode::getSmoothingTimeConstant() const {
47
+ float AnalyserNode::getSmoothingTimeConstant() const {
43
48
  return smoothingTimeConstant_;
44
49
  }
45
50
 
46
- void AnalyserNode::setFftSize(size_t fftSize) {
51
+ std::string AnalyserNode::getWindowType() const {
52
+ return AnalyserNode::toString(windowType_);
53
+ }
54
+
55
+ void AnalyserNode::setFftSize(int fftSize) {
47
56
  if (fftSize_ == fftSize) {
48
57
  return;
49
58
  }
@@ -53,35 +62,39 @@ void AnalyserNode::setFftSize(size_t fftSize) {
53
62
  magnitudeBuffer_ = std::make_unique<AudioArray>(fftSize_ / 2);
54
63
  }
55
64
 
56
- void AnalyserNode::setMinDecibels(double minDecibels) {
65
+ void AnalyserNode::setMinDecibels(float minDecibels) {
57
66
  minDecibels_ = minDecibels;
58
67
  }
59
68
 
60
- void AnalyserNode::setMaxDecibels(double maxDecibels) {
69
+ void AnalyserNode::setMaxDecibels(float maxDecibels) {
61
70
  maxDecibels_ = maxDecibels;
62
71
  }
63
72
 
64
- void AnalyserNode::setSmoothingTimeConstant(double smoothingTimeConstant) {
73
+ void AnalyserNode::setSmoothingTimeConstant(float smoothingTimeConstant) {
65
74
  smoothingTimeConstant_ = smoothingTimeConstant;
66
75
  }
67
76
 
68
- void AnalyserNode::getFloatFrequencyData(float *data, size_t length) {
77
+ void AnalyserNode::setWindowType(const std::string &type) {
78
+ windowType_ = AnalyserNode::fromString(type);
79
+ }
80
+
81
+ void AnalyserNode::getFloatFrequencyData(float *data, int length) {
69
82
  doFFTAnalysis();
70
83
 
71
- length = std::min<size_t>(magnitudeBuffer_->getSize(), length);
84
+ length = std::min(static_cast<int>(magnitudeBuffer_->getSize()), length);
72
85
  VectorMath::linearToDecibels(magnitudeBuffer_->getData(), data, length);
73
86
  }
74
87
 
75
- void AnalyserNode::getByteFrequencyData(uint8_t *data, size_t length) {
88
+ void AnalyserNode::getByteFrequencyData(uint8_t *data, int length) {
76
89
  doFFTAnalysis();
77
90
 
78
91
  auto magnitudeBufferData = magnitudeBuffer_->getData();
79
- length = std::min<size_t>(magnitudeBuffer_->getSize(), length);
92
+ length = std::min(static_cast<int>(magnitudeBuffer_->getSize()), length);
80
93
 
81
94
  const auto rangeScaleFactor =
82
95
  maxDecibels_ == minDecibels_ ? 1 : 1 / (maxDecibels_ - minDecibels_);
83
96
 
84
- for (size_t i = 0; i < length; i++) {
97
+ for (int i = 0; i < length; i++) {
85
98
  auto dbMag = magnitudeBufferData[i] == 0
86
99
  ? minDecibels_
87
100
  : AudioUtils::linearToDecibels(magnitudeBufferData[i]);
@@ -98,20 +111,20 @@ void AnalyserNode::getByteFrequencyData(uint8_t *data, size_t length) {
98
111
  }
99
112
  }
100
113
 
101
- void AnalyserNode::getFloatTimeDomainData(float *data, size_t length) {
114
+ void AnalyserNode::getFloatTimeDomainData(float *data, int length) {
102
115
  auto size = std::min(fftSize_, length);
103
116
 
104
- for (size_t i = 0; i < size; i++) {
117
+ for (int i = 0; i < size; i++) {
105
118
  data[i] = inputBuffer_->getData()
106
119
  [(vWriteIndex_ + i - fftSize_ + inputBuffer_->getSize()) %
107
120
  inputBuffer_->getSize()];
108
121
  }
109
122
  }
110
123
 
111
- void AnalyserNode::getByteTimeDomainData(uint8_t *data, size_t length) {
124
+ void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) {
112
125
  auto size = std::min(fftSize_, length);
113
126
 
114
- for (size_t i = 0; i < size; i++) {
127
+ for (int i = 0; i < size; i++) {
115
128
  auto value = inputBuffer_->getData()
116
129
  [(vWriteIndex_ + i - fftSize_ + inputBuffer_->getSize()) %
117
130
  inputBuffer_->getSize()];
@@ -140,15 +153,11 @@ void AnalyserNode::processNode(
140
153
  // Analyser should behave like a sniffer node, it should not modify the
141
154
  // processingBus but instead copy the data to its own input buffer.
142
155
 
143
- if (downMixBus_ == nullptr) {
144
- downMixBus_ = std::make_unique<AudioBus>(
145
- context_->getSampleRate(), processingBus->getSize(), 1);
146
- }
147
-
148
156
  downMixBus_->copy(processingBus);
149
157
 
150
158
  if (vWriteIndex_ + framesToProcess > inputBuffer_->getSize()) {
151
- auto framesToCopy = inputBuffer_->getSize() - vWriteIndex_;
159
+ auto framesToCopy =
160
+ static_cast<int>(inputBuffer_->getSize()) - vWriteIndex_;
152
161
  memcpy(
153
162
  inputBuffer_->getData() + vWriteIndex_,
154
163
  downMixBus_->getChannel(0)->getData(),
@@ -197,7 +206,14 @@ void AnalyserNode::doFFTAnalysis() {
197
206
  tempBuffer.copy(inputBuffer_.get(), vWriteIndex_ - fftSize_, 0, fftSize_);
198
207
  }
199
208
 
200
- AnalyserNode::applyWindow(tempBuffer.getData(), fftSize_);
209
+ switch (windowType_) {
210
+ case WindowType::BLACKMAN:
211
+ AnalyserNode::applyBlackManWindow(tempBuffer.getData(), fftSize_);
212
+ break;
213
+ case WindowType::HANN:
214
+ AnalyserNode::applyHannWindow(tempBuffer.getData(), fftSize_);
215
+ break;
216
+ }
201
217
 
202
218
  // do fft analysis - get frequency domain data
203
219
  fftFrame_->doFFT(tempBuffer.getData());
@@ -211,7 +227,7 @@ void AnalyserNode::doFFTAnalysis() {
211
227
  const float magnitudeScale = 1.0f / static_cast<float>(fftSize_);
212
228
  auto magnitudeBufferData = magnitudeBuffer_->getData();
213
229
 
214
- for (size_t i = 0; i < magnitudeBuffer_->getSize(); i++) {
230
+ for (int i = 0; i < magnitudeBuffer_->getSize(); i++) {
215
231
  std::complex<float> c(realFFTFrameData[i], imaginaryFFTFrameData[i]);
216
232
  auto scalarMagnitude = std::abs(c) * magnitudeScale;
217
233
  magnitudeBufferData[i] = static_cast<float>(
@@ -220,17 +236,23 @@ void AnalyserNode::doFFTAnalysis() {
220
236
  }
221
237
  }
222
238
 
223
- void AnalyserNode::applyWindow(float *data, size_t length) {
239
+ void AnalyserNode::applyBlackManWindow(float *data, int length) {
224
240
  // https://www.sciencedirect.com/topics/engineering/blackman-window
225
- auto alpha = 0.16f;
226
- auto a0 = 0.5f * (1 - alpha);
227
- auto a1 = 0.5f;
228
- auto a2 = 0.5f * alpha;
241
+ // https://docs.scipy.org/doc//scipy-1.2.3/reference/generated/scipy.signal.windows.blackman.html#scipy.signal.windows.blackman
229
242
 
230
243
  for (int i = 0; i < length; ++i) {
231
244
  auto x = static_cast<float>(i) / static_cast<float>(length);
232
- auto window = a0 - a1 * cos(2 * static_cast<float>(M_PI) * x) +
233
- a2 * cos(4 * static_cast<float>(M_PI) * x);
245
+ auto window = 0.42f - 0.5f * cos(2 * PI * x) + 0.08f * cos(4 * PI * x);
246
+ data[i] *= window;
247
+ }
248
+ }
249
+
250
+ void AnalyserNode::applyHannWindow(float *data, int length) {
251
+ // https://www.sciencedirect.com/topics/engineering/hanning-window
252
+ // https://docs.scipy.org/doc//scipy-1.2.3/reference/generated/scipy.signal.windows.hann.html#scipy.signal.windows.hann
253
+ for (int i = 0; i < length; ++i) {
254
+ auto x = static_cast<float>(i) / static_cast<float>(length - 1);
255
+ auto window = 0.5f - 0.5f * cos(2 * PI * x);
234
256
  data[i] *= window;
235
257
  }
236
258
  }
@@ -1,6 +1,8 @@
1
1
  #pragma once
2
2
 
3
3
  #include <memory>
4
+ #include <cstddef>
5
+ #include <string>
4
6
 
5
7
  #include "AudioNode.h"
6
8
 
@@ -12,32 +14,36 @@ class FFTFrame;
12
14
 
13
15
  class AnalyserNode : public AudioNode {
14
16
  public:
17
+ enum class WindowType { BLACKMAN, HANN };
15
18
  explicit AnalyserNode(BaseAudioContext *context);
16
19
 
17
- size_t getFftSize() const;
18
- size_t getFrequencyBinCount() const;
19
- double getMinDecibels() const;
20
- double getMaxDecibels() const;
20
+ int getFftSize() const;
21
+ int getFrequencyBinCount() const;
22
+ float getMinDecibels() const;
23
+ float getMaxDecibels() const;
24
+ float getSmoothingTimeConstant() const;
25
+ std::string getWindowType() const;
21
26
 
22
- double getSmoothingTimeConstant() const;
23
- void setFftSize(size_t fftSize);
24
- void setMinDecibels(double minDecibels);
25
- void setMaxDecibels(double maxDecibels);
26
- void setSmoothingTimeConstant(double smoothingTimeConstant);
27
+ void setFftSize(int fftSize);
28
+ void setMinDecibels(float minDecibels);
29
+ void setMaxDecibels(float maxDecibels);
30
+ void setSmoothingTimeConstant(float smoothingTimeConstant);
31
+ void setWindowType(const std::string &type);
27
32
 
28
- void getFloatFrequencyData(float *data, size_t length);
29
- void getByteFrequencyData(uint8_t *data, size_t length);
30
- void getFloatTimeDomainData(float *data, size_t length);
31
- void getByteTimeDomainData(uint8_t *data, size_t length);
33
+ void getFloatFrequencyData(float *data, int length);
34
+ void getByteFrequencyData(uint8_t *data, int length);
35
+ void getFloatTimeDomainData(float *data, int length);
36
+ void getByteTimeDomainData(uint8_t *data, int length);
32
37
 
33
38
  protected:
34
39
  void processNode(AudioBus *processingBus, int framesToProcess) override;
35
40
 
36
41
  private:
37
- size_t fftSize_;
38
- double minDecibels_;
39
- double maxDecibels_;
40
- double smoothingTimeConstant_;
42
+ int fftSize_;
43
+ float minDecibels_;
44
+ float maxDecibels_;
45
+ float smoothingTimeConstant_;
46
+ WindowType windowType_;
41
47
 
42
48
  std::unique_ptr<AudioArray> inputBuffer_;
43
49
  std::unique_ptr<AudioBus> downMixBus_;
@@ -47,8 +53,34 @@ class AnalyserNode : public AudioNode {
47
53
  std::unique_ptr<AudioArray> magnitudeBuffer_;
48
54
  bool shouldDoFFTAnalysis_ { true };
49
55
 
50
- void doFFTAnalysis();
51
- static void applyWindow(float *data, size_t length);
56
+ static WindowType fromString(const std::string &type) {
57
+ std::string lowerType = type;
58
+ std::transform(
59
+ lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
60
+ if (lowerType == "blackman") {
61
+ return WindowType::BLACKMAN;
62
+ }
63
+ if (lowerType == "hann") {
64
+ return WindowType::HANN;
65
+ }
66
+
67
+ throw std::invalid_argument("Unknown window type");
68
+ }
69
+
70
+ static std::string toString(WindowType type) {
71
+ switch (type) {
72
+ case WindowType::BLACKMAN:
73
+ return "blackman";
74
+ case WindowType::HANN:
75
+ return "hann";
76
+ default:
77
+ throw std::invalid_argument("Unknown window type");
78
+ }
79
+ }
80
+
81
+ void doFFTAnalysis();
82
+ static void applyBlackManWindow(float *data, int length);
83
+ static void applyHannWindow(float *data, int length);
52
84
  };
53
85
 
54
86
  } // namespace audioapi
@@ -5,7 +5,7 @@
5
5
 
6
6
  namespace audioapi {
7
7
 
8
- AudioArray::AudioArray(int size) : data_(nullptr), size_(size) {
8
+ AudioArray::AudioArray(size_t size) : data_(nullptr), size_(size) {
9
9
  resize(size);
10
10
  }
11
11
 
@@ -16,7 +16,7 @@ AudioArray::~AudioArray() {
16
16
  }
17
17
  }
18
18
 
19
- int AudioArray::getSize() const {
19
+ size_t AudioArray::getSize() const {
20
20
  return size_;
21
21
  }
22
22
 
@@ -24,11 +24,11 @@ float *AudioArray::getData() const {
24
24
  return data_;
25
25
  }
26
26
 
27
- float &AudioArray::operator[](int index) {
27
+ float &AudioArray::operator[](size_t index) {
28
28
  return data_[index];
29
29
  }
30
30
 
31
- const float &AudioArray::operator[](int index) const {
31
+ const float &AudioArray::operator[](size_t index) const {
32
32
  return data_[index];
33
33
  }
34
34
 
@@ -42,7 +42,7 @@ void AudioArray::normalize() {
42
42
  VectorMath::multiplyByScalar(data_, 1.0f / maxAbsValue, data_, size_);
43
43
  }
44
44
 
45
- void AudioArray::resize(int size) {
45
+ void AudioArray::resize(size_t size) {
46
46
  if (size == size_) {
47
47
  if (!data_) {
48
48
  data_ = new float[size];
@@ -71,7 +71,7 @@ void AudioArray::zero() {
71
71
  zero(0, size_);
72
72
  }
73
73
 
74
- void AudioArray::zero(int start, int length) {
74
+ void AudioArray::zero(size_t start, size_t length) {
75
75
  memset(data_ + start, 0, length * sizeof(float));
76
76
  }
77
77
 
@@ -79,15 +79,15 @@ void AudioArray::sum(const AudioArray *source) {
79
79
  sum(source, 0, 0, size_);
80
80
  }
81
81
 
82
- void AudioArray::sum(const AudioArray *source, int start, int length) {
82
+ void AudioArray::sum(const AudioArray *source, size_t start, size_t length) {
83
83
  sum(source, start, start, length);
84
84
  }
85
85
 
86
86
  void AudioArray::sum(
87
87
  const AudioArray *source,
88
- int sourceStart,
89
- int destinationStart,
90
- int length) {
88
+ size_t sourceStart,
89
+ size_t destinationStart,
90
+ size_t length) {
91
91
  VectorMath::add(
92
92
  data_ + destinationStart,
93
93
  source->getData() + sourceStart,
@@ -99,15 +99,15 @@ void AudioArray::copy(const AudioArray *source) {
99
99
  copy(source, 0, size_);
100
100
  }
101
101
 
102
- void AudioArray::copy(const AudioArray *source, int start, int length) {
102
+ void AudioArray::copy(const AudioArray *source, size_t start, size_t length) {
103
103
  copy(source, start, start, length);
104
104
  }
105
105
 
106
106
  void AudioArray::copy(
107
107
  const AudioArray *source,
108
- int sourceStart,
109
- int destinationStart,
110
- int length) {
108
+ size_t sourceStart,
109
+ size_t destinationStart,
110
+ size_t length) {
111
111
  memcpy(
112
112
  data_ + destinationStart,
113
113
  source->getData() + sourceStart,
@@ -2,47 +2,48 @@
2
2
 
3
3
  #include <algorithm>
4
4
  #include <memory>
5
+ #include <cstddef>
5
6
 
6
7
  namespace audioapi {
7
8
 
8
9
  class AudioArray {
9
10
  public:
10
- explicit AudioArray(int size);
11
+ explicit AudioArray(size_t size);
11
12
  ~AudioArray();
12
13
 
13
- [[nodiscard]] int getSize() const;
14
+ [[nodiscard]] size_t getSize() const;
14
15
  [[nodiscard]] float *getData() const;
15
16
 
16
- float &operator[](int index);
17
- const float &operator[](int index) const;
17
+ float &operator[](size_t index);
18
+ const float &operator[](size_t index) const;
18
19
 
19
20
  void normalize();
20
- void resize(int size);
21
+ void resize(size_t size);
21
22
  void scale(float value);
22
23
  [[nodiscard]] float getMaxAbsValue() const;
23
24
 
24
25
  void zero();
25
- void zero(int start, int length);
26
+ void zero(size_t start, size_t length);
26
27
 
27
28
  void sum(const AudioArray *source);
28
- void sum(const AudioArray *source, int start, int length);
29
+ void sum(const AudioArray *source, size_t start, size_t length);
29
30
  void sum(
30
31
  const AudioArray *source,
31
- int sourceStart,
32
- int destinationStart,
33
- int length);
32
+ size_t sourceStart,
33
+ size_t destinationStart,
34
+ size_t length);
34
35
 
35
36
  void copy(const AudioArray *source);
36
- void copy(const AudioArray *source, int start, int length);
37
+ void copy(const AudioArray *source, size_t start, size_t length);
37
38
  void copy(
38
39
  const AudioArray *source,
39
- int sourceStart,
40
- int destinationStart,
41
- int length);
40
+ size_t sourceStart,
41
+ size_t destinationStart,
42
+ size_t length);
42
43
 
43
44
  private:
44
45
  float *data_;
45
- int size_;
46
+ size_t size_;
46
47
  };
47
48
 
48
49
  } // namespace audioapi