react-native-audio-api 0.5.1 → 0.5.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.
- package/android/src/main/cpp/audioapi/android/core/AudioDecoder.cpp +0 -35
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +2 -2
- package/common/cpp/audioapi/HostObjects/AudioBufferHostObject.h +4 -2
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +11 -3
- package/common/cpp/audioapi/core/AudioNode.cpp +3 -1
- package/common/cpp/audioapi/core/AudioNode.h +1 -1
- package/common/cpp/audioapi/core/effects/PeriodicWave.cpp +1 -1
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +22 -1
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +1 -0
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +2 -2
- package/common/cpp/audioapi/dsp/VectorMath.cpp +1 -0
- package/common/cpp/audioapi/dsp/VectorMath.h +1 -0
- package/common/cpp/audioapi/jsi/JsiHostObject.cpp +26 -0
- package/common/cpp/audioapi/jsi/JsiHostObject.h +1 -0
- package/ios/audioapi/ios/core/AudioPlayer.h +3 -0
- package/ios/audioapi/ios/core/AudioPlayer.m +57 -12
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +3 -8
- package/package.json +1 -1
|
@@ -109,39 +109,4 @@ std::shared_ptr<AudioBus> AudioDecoder::decodeWithMemoryBlock(
|
|
|
109
109
|
return audioBus;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
// std::shared_ptr<AudioBus> AudioDecoder::decode(ma_decoder &decoder) const {
|
|
113
|
-
// ma_uint64 totalFrameCount;
|
|
114
|
-
// ma_decoder_get_length_in_pcm_frames(&decoder, &totalFrameCount);
|
|
115
|
-
//
|
|
116
|
-
// auto audioBus = std::make_shared<AudioBus>(
|
|
117
|
-
// static_cast<int>(totalFrameCount), 2, sampleRate_);
|
|
118
|
-
// auto *buffer = new float[totalFrameCount * 2];
|
|
119
|
-
//
|
|
120
|
-
// ma_uint64 framesDecoded;
|
|
121
|
-
// ma_decoder_read_pcm_frames(&decoder, buffer, totalFrameCount,
|
|
122
|
-
// &framesDecoded); if (framesDecoded == 0) {
|
|
123
|
-
// __android_log_print(
|
|
124
|
-
// ANDROID_LOG_ERROR,
|
|
125
|
-
// "AudioDecoder",
|
|
126
|
-
// "Failed to decode");
|
|
127
|
-
//
|
|
128
|
-
// delete[] buffer;
|
|
129
|
-
// ma_decoder_uninit(&decoder);
|
|
130
|
-
//
|
|
131
|
-
// return nullptr;
|
|
132
|
-
// }
|
|
133
|
-
//
|
|
134
|
-
// for (int i = 0; i < decoder.outputChannels; ++i) {
|
|
135
|
-
// auto channelData = audioBus->getChannel(i)->getData();
|
|
136
|
-
//
|
|
137
|
-
// for (ma_uint64 j = 0; j < framesDecoded; ++j) {
|
|
138
|
-
// channelData[j] = buffer[j * decoder.outputChannels + i];
|
|
139
|
-
// }
|
|
140
|
-
// }
|
|
141
|
-
//
|
|
142
|
-
// delete[] buffer;
|
|
143
|
-
// ma_decoder_uninit(&decoder);
|
|
144
|
-
//
|
|
145
|
-
// return audioBus;
|
|
146
|
-
// }
|
|
147
112
|
} // namespace audioapi
|
|
@@ -14,7 +14,7 @@ AudioPlayer::AudioPlayer(
|
|
|
14
14
|
builder.setSharingMode(SharingMode::Exclusive)
|
|
15
15
|
->setFormat(AudioFormat::Float)
|
|
16
16
|
->setFormatConversionAllowed(true)
|
|
17
|
-
->setPerformanceMode(PerformanceMode::
|
|
17
|
+
->setPerformanceMode(PerformanceMode::None)
|
|
18
18
|
->setChannelCount(channelCount_)
|
|
19
19
|
->setSampleRateConversionQuality(SampleRateConversionQuality::Medium)
|
|
20
20
|
->setDataCallback(this)
|
|
@@ -35,7 +35,7 @@ AudioPlayer::AudioPlayer(
|
|
|
35
35
|
builder.setSharingMode(SharingMode::Exclusive)
|
|
36
36
|
->setFormat(AudioFormat::Float)
|
|
37
37
|
->setFormatConversionAllowed(true)
|
|
38
|
-
->setPerformanceMode(PerformanceMode::
|
|
38
|
+
->setPerformanceMode(PerformanceMode::None)
|
|
39
39
|
->setChannelCount(2)
|
|
40
40
|
->setSampleRateConversionQuality(SampleRateConversionQuality::Medium)
|
|
41
41
|
->setDataCallback(this)
|
|
@@ -31,6 +31,10 @@ class AudioBufferHostObject : public JsiHostObject {
|
|
|
31
31
|
JSI_EXPORT_FUNCTION(AudioBufferHostObject, copyToChannel));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
[[nodiscard]] size_t getSizeInBytes() const {
|
|
35
|
+
return audioBuffer_->getLength() * audioBuffer_->getNumberOfChannels() * sizeof(float);
|
|
36
|
+
}
|
|
37
|
+
|
|
34
38
|
JSI_PROPERTY_GETTER(sampleRate) {
|
|
35
39
|
return {audioBuffer_->getSampleRate()};
|
|
36
40
|
}
|
|
@@ -48,8 +52,6 @@ class AudioBufferHostObject : public JsiHostObject {
|
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
JSI_HOST_FUNCTION(getChannelData) {
|
|
51
|
-
// this method could cause a crash if channelData is already deallocated,
|
|
52
|
-
// but we handle deallocation internally so it should be safe
|
|
53
55
|
auto channel = static_cast<int>(args[0].getNumber());
|
|
54
56
|
auto channelData = reinterpret_cast<uint8_t *>(audioBuffer_->getChannelData(channel));
|
|
55
57
|
auto length = static_cast<int>(audioBuffer_->getLength());
|
|
@@ -109,7 +109,11 @@ class BaseAudioContextHostObject : public JsiHostObject {
|
|
|
109
109
|
auto sampleRate = static_cast<float>(args[2].getNumber());
|
|
110
110
|
auto buffer = BaseAudioContext::createBuffer(numberOfChannels, length, sampleRate);
|
|
111
111
|
auto bufferHostObject = std::make_shared<AudioBufferHostObject>(buffer);
|
|
112
|
-
|
|
112
|
+
|
|
113
|
+
auto jsiObject = jsi::Object::createFromHostObject(runtime, bufferHostObject);
|
|
114
|
+
jsiObject.setExternalMemoryPressure(runtime, bufferHostObject->getSizeInBytes());
|
|
115
|
+
|
|
116
|
+
return jsiObject;
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
JSI_HOST_FUNCTION(createPeriodicWave) {
|
|
@@ -158,7 +162,9 @@ class BaseAudioContextHostObject : public JsiHostObject {
|
|
|
158
162
|
}
|
|
159
163
|
|
|
160
164
|
promise->resolve([audioBufferHostObject = std::move(audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
161
|
-
|
|
165
|
+
auto jsiObject = jsi::Object::createFromHostObject(runtime, audioBufferHostObject);
|
|
166
|
+
jsiObject.setExternalMemoryPressure(runtime, audioBufferHostObject->getSizeInBytes());
|
|
167
|
+
return jsiObject;
|
|
162
168
|
});
|
|
163
169
|
}).detach();
|
|
164
170
|
});
|
|
@@ -182,7 +188,9 @@ class BaseAudioContextHostObject : public JsiHostObject {
|
|
|
182
188
|
}
|
|
183
189
|
|
|
184
190
|
promise->resolve([audioBufferHostObject = std::move(audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
185
|
-
|
|
191
|
+
auto jsiObject = jsi::Object::createFromHostObject(runtime, audioBufferHostObject);
|
|
192
|
+
jsiObject.setExternalMemoryPressure(runtime, audioBufferHostObject->getSizeInBytes());
|
|
193
|
+
return jsiObject;
|
|
186
194
|
});
|
|
187
195
|
}).detach();
|
|
188
196
|
});
|
|
@@ -254,7 +254,9 @@ void AudioNode::cleanup() {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
for (const auto &inputNode : inputNodes_) {
|
|
257
|
-
inputNode
|
|
257
|
+
if (inputNode) {
|
|
258
|
+
inputNode->disconnectNode(shared_from_this());
|
|
259
|
+
}
|
|
258
260
|
}
|
|
259
261
|
|
|
260
262
|
outputNodes_.clear();
|
|
@@ -121,7 +121,7 @@ int PeriodicWave::getNumberOfPartialsPerRange(int rangeIndex) const {
|
|
|
121
121
|
|
|
122
122
|
// The very top range will have all the partials culled.
|
|
123
123
|
int numberOfPartials =
|
|
124
|
-
|
|
124
|
+
int(static_cast<float>(getMaxNumberOfPartials()) * cullingScale);
|
|
125
125
|
|
|
126
126
|
return numberOfPartials;
|
|
127
127
|
}
|
|
@@ -109,6 +109,11 @@ void AudioBufferSourceNode::start(double when, double offset, double duration) {
|
|
|
109
109
|
vReadIndex_ = static_cast<double>(buffer_->getSampleRate() * offset);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
void AudioBufferSourceNode::disable() {
|
|
113
|
+
AudioNode::disable();
|
|
114
|
+
buffer_ = nullptr;
|
|
115
|
+
}
|
|
116
|
+
|
|
112
117
|
std::mutex &AudioBufferSourceNode::getBufferLock() {
|
|
113
118
|
return bufferLock_;
|
|
114
119
|
}
|
|
@@ -160,9 +165,19 @@ void AudioBufferSourceNode::processNode(
|
|
|
160
165
|
updatePlaybackInfo(
|
|
161
166
|
playbackRateBus_, framesNeededToStretch, startOffset, offsetLength);
|
|
162
167
|
|
|
168
|
+
if (playbackRate == 0.0f || !isPlaying() || !buffer_) {
|
|
169
|
+
processingBus->zero();
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
163
173
|
processWithoutInterpolation(
|
|
164
174
|
playbackRateBus_, startOffset, offsetLength, playbackRate);
|
|
165
175
|
|
|
176
|
+
if (!buffer_) {
|
|
177
|
+
processingBus->zero();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
166
181
|
auto stretch = buffer_->stretch_;
|
|
167
182
|
|
|
168
183
|
stretch->process(
|
|
@@ -171,7 +186,9 @@ void AudioBufferSourceNode::processNode(
|
|
|
171
186
|
processingBus.get()[0],
|
|
172
187
|
framesToProcess);
|
|
173
188
|
|
|
174
|
-
|
|
189
|
+
if (detune != 0.0f) {
|
|
190
|
+
stretch->setTransposeSemitones(detune);
|
|
191
|
+
}
|
|
175
192
|
}
|
|
176
193
|
|
|
177
194
|
handleStopScheduled();
|
|
@@ -233,6 +250,10 @@ void AudioBufferSourceNode::processWithoutInterpolation(
|
|
|
233
250
|
|
|
234
251
|
if (!loop_) {
|
|
235
252
|
processingBus->zero(writeIndex, framesLeft);
|
|
253
|
+
|
|
254
|
+
if (onendedCallback_) {
|
|
255
|
+
onendedCallback_(getStopTime());
|
|
256
|
+
}
|
|
236
257
|
playbackState_ = PlaybackState::FINISHED;
|
|
237
258
|
disable();
|
|
238
259
|
break;
|
|
@@ -30,6 +30,7 @@ class AudioBufferSourceNode : public AudioScheduledSourceNode {
|
|
|
30
30
|
void setBuffer(const std::shared_ptr<AudioBuffer> &buffer);
|
|
31
31
|
|
|
32
32
|
void start(double when, double offset, double duration = -1);
|
|
33
|
+
void disable() override;
|
|
33
34
|
|
|
34
35
|
protected:
|
|
35
36
|
std::mutex &getBufferLock();
|
|
@@ -36,6 +36,8 @@ class AudioScheduledSourceNode : public AudioNode {
|
|
|
36
36
|
protected:
|
|
37
37
|
PlaybackState playbackState_;
|
|
38
38
|
|
|
39
|
+
std::function<void(double)> onendedCallback_;
|
|
40
|
+
|
|
39
41
|
void updatePlaybackInfo(
|
|
40
42
|
const std::shared_ptr<AudioBus>& processingBus,
|
|
41
43
|
int framesToProcess,
|
|
@@ -47,8 +49,6 @@ class AudioScheduledSourceNode : public AudioNode {
|
|
|
47
49
|
private:
|
|
48
50
|
double startTime_;
|
|
49
51
|
double stopTime_;
|
|
50
|
-
|
|
51
|
-
std::function<void(double)> onendedCallback_;
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
} // namespace audioapi
|
|
@@ -46,4 +46,5 @@ void multiply(const float *inputVector1, const float *inputVector2, float *outpu
|
|
|
46
46
|
float maximumMagnitude(const float *inputVector, size_t numberOfElementsToProcess);
|
|
47
47
|
|
|
48
48
|
void linearToDecibels(const float *inputVector, float *outputVector, size_t numberOfElementsToProcess);
|
|
49
|
+
|
|
49
50
|
} // namespace audioapi::dsp
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
#include <audioapi/jsi/JsiHostObject.h>
|
|
2
2
|
|
|
3
|
+
// set this value to 1 in order to debug the construction/destruction
|
|
4
|
+
#define JSI_DEBUG_ALLOCATIONS 1
|
|
5
|
+
|
|
3
6
|
namespace audioapi {
|
|
7
|
+
|
|
8
|
+
#if JSI_DEBUG_ALLOCATIONS
|
|
9
|
+
int objCounter = 0;
|
|
10
|
+
std::vector<JsiHostObject *> objects;
|
|
11
|
+
#endif
|
|
12
|
+
|
|
4
13
|
JsiHostObject::JsiHostObject() {
|
|
5
14
|
getters_ = std::make_unique<std::unordered_map<
|
|
6
15
|
std::string,
|
|
@@ -12,6 +21,23 @@ JsiHostObject::JsiHostObject() {
|
|
|
12
21
|
setters_ = std::make_unique<std::unordered_map<
|
|
13
22
|
std::string,
|
|
14
23
|
void (JsiHostObject::*)(jsi::Runtime &, const jsi::Value &)>>();
|
|
24
|
+
|
|
25
|
+
#if JSI_DEBUG_ALLOCATIONS
|
|
26
|
+
objects.push_back(this);
|
|
27
|
+
objCounter++;
|
|
28
|
+
#endif
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
JsiHostObject::~JsiHostObject() {
|
|
32
|
+
#if JSI_DEBUG_ALLOCATIONS
|
|
33
|
+
for (size_t i = 0; i < objects.size(); ++i) {
|
|
34
|
+
if (objects.at(i) == this) {
|
|
35
|
+
objects.erase(objects.begin() + i);
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
objCounter--;
|
|
40
|
+
#endif
|
|
15
41
|
}
|
|
16
42
|
|
|
17
43
|
std::vector<jsi::PropNameID> JsiHostObject::getPropertyNames(jsi::Runtime &rt) {
|
|
@@ -16,6 +16,8 @@ typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
|
|
|
16
16
|
@property (nonatomic, assign) float sampleRate;
|
|
17
17
|
@property (nonatomic, assign) int channelCount;
|
|
18
18
|
@property (nonatomic, assign) bool isRunning;
|
|
19
|
+
@property (nonatomic, assign) bool isInterrupted;
|
|
20
|
+
@property (nonatomic, assign) bool configurationChanged;
|
|
19
21
|
|
|
20
22
|
- (instancetype)initWithRenderAudioBlock:(RenderAudioBlock)renderAudio channelCount:(int)channelCount;
|
|
21
23
|
|
|
@@ -42,5 +44,6 @@ typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
|
|
|
42
44
|
- (void)connectAudioEngine;
|
|
43
45
|
|
|
44
46
|
- (void)handleEngineConfigurationChange:(NSNotification *)notification;
|
|
47
|
+
- (void)handleInterruption:(NSNotification *)notification;
|
|
45
48
|
|
|
46
49
|
@end
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
self.audioEngine = [[AVAudioEngine alloc] init];
|
|
10
10
|
self.audioEngine.mainMixerNode.outputVolume = 1;
|
|
11
11
|
self.isRunning = true;
|
|
12
|
+
self.isInterrupted = false;
|
|
13
|
+
self.configurationChanged = false;
|
|
12
14
|
|
|
13
15
|
[self setupAndInitAudioSession];
|
|
14
16
|
[self setupAndInitNotificationHandlers];
|
|
@@ -44,6 +46,8 @@
|
|
|
44
46
|
self.audioEngine = [[AVAudioEngine alloc] init];
|
|
45
47
|
self.audioEngine.mainMixerNode.outputVolume = 1;
|
|
46
48
|
self.isRunning = true;
|
|
49
|
+
self.isInterrupted = false;
|
|
50
|
+
self.configurationChanged = false;
|
|
47
51
|
|
|
48
52
|
[self setupAndInitAudioSession];
|
|
49
53
|
[self setupAndInitNotificationHandlers];
|
|
@@ -94,7 +98,7 @@
|
|
|
94
98
|
[self.audioSession setActive:false error:&error];
|
|
95
99
|
|
|
96
100
|
if (error != nil) {
|
|
97
|
-
@
|
|
101
|
+
NSLog(@"Error while deactivating audio session: %@", [error debugDescription]);
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
104
|
|
|
@@ -140,20 +144,25 @@
|
|
|
140
144
|
self.audioSession = [AVAudioSession sharedInstance];
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
[self.audioSession
|
|
144
|
-
mode:AVAudioSessionModeDefault
|
|
145
|
-
options:AVAudioSessionCategoryOptionDuckOthers | AVAudioSessionCategoryOptionAllowBluetooth |
|
|
146
|
-
AVAudioSessionCategoryOptionAllowAirPlay
|
|
147
|
-
error:&error];
|
|
147
|
+
[self.audioSession setPreferredIOBufferDuration:0.022 error:&error];
|
|
148
148
|
|
|
149
149
|
if (error != nil) {
|
|
150
|
-
NSLog(@"Error while
|
|
150
|
+
NSLog(@"Error while setting buffer size in audio session: %@", [error debugDescription]);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
[self.audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
|
|
155
|
+
|
|
156
|
+
if (error != nil) {
|
|
157
|
+
NSLog(@"Error while configuring audio session: %@", [error debugDescription]);
|
|
158
|
+
return;
|
|
151
159
|
}
|
|
152
160
|
|
|
153
161
|
[self.audioSession setActive:true error:&error];
|
|
154
162
|
|
|
155
163
|
if (error != nil) {
|
|
156
|
-
NSLog(@"Error while activating audio session: %@", [error
|
|
164
|
+
NSLog(@"Error while activating audio session: %@", [error debugDescription]);
|
|
165
|
+
return;
|
|
157
166
|
}
|
|
158
167
|
}
|
|
159
168
|
|
|
@@ -166,7 +175,11 @@
|
|
|
166
175
|
[self.notificationCenter addObserver:self
|
|
167
176
|
selector:@selector(handleEngineConfigurationChange:)
|
|
168
177
|
name:AVAudioEngineConfigurationChangeNotification
|
|
169
|
-
object:
|
|
178
|
+
object:self];
|
|
179
|
+
[self.notificationCenter addObserver:self
|
|
180
|
+
selector:@selector(handleInterruption:)
|
|
181
|
+
name:AVAudioSessionInterruptionNotification
|
|
182
|
+
object:self];
|
|
170
183
|
}
|
|
171
184
|
|
|
172
185
|
- (void)connectAudioEngine
|
|
@@ -182,18 +195,50 @@
|
|
|
182
195
|
NSError *error = nil;
|
|
183
196
|
|
|
184
197
|
if (![self.audioEngine startAndReturnError:&error]) {
|
|
185
|
-
NSLog(@"Error starting audio engine: %@", [error
|
|
198
|
+
NSLog(@"Error starting audio engine: %@", [error debugDescription]);
|
|
186
199
|
}
|
|
187
200
|
}
|
|
188
201
|
}
|
|
189
202
|
|
|
190
203
|
- (void)handleEngineConfigurationChange:(NSNotification *)notification
|
|
191
204
|
{
|
|
192
|
-
if (!self.isRunning) {
|
|
205
|
+
if (!self.isRunning || self.isInterrupted) {
|
|
206
|
+
self.configurationChanged = true;
|
|
193
207
|
return;
|
|
194
208
|
}
|
|
195
209
|
|
|
196
|
-
|
|
210
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
211
|
+
[self connectAudioEngine];
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
- (void)handleInterruption:(NSNotification *)notification
|
|
216
|
+
{
|
|
217
|
+
NSError *error;
|
|
218
|
+
UInt8 type = [[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] intValue];
|
|
219
|
+
UInt8 option = [[notification.userInfo valueForKey:AVAudioSessionInterruptionOptionKey] intValue];
|
|
220
|
+
|
|
221
|
+
if (type == AVAudioSessionInterruptionTypeBegan) {
|
|
222
|
+
self.isInterrupted = true;
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (type != AVAudioSessionInterruptionTypeEnded || option != AVAudioSessionInterruptionOptionShouldResume) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
bool success = [self.audioSession setActive:true error:&error];
|
|
231
|
+
|
|
232
|
+
if (!success) {
|
|
233
|
+
NSLog(@"ERror: %@", [error debugDescription]);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (self.configurationChanged && self.isRunning) {
|
|
238
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
239
|
+
[self connectAudioEngine];
|
|
240
|
+
});
|
|
241
|
+
}
|
|
197
242
|
}
|
|
198
243
|
|
|
199
244
|
@end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#import <AVFoundation/AVFoundation.h>
|
|
2
2
|
|
|
3
3
|
#include <audioapi/core/Constants.h>
|
|
4
|
+
#include <audioapi/dsp/VectorMath.h>
|
|
4
5
|
#include <audioapi/ios/core/IOSAudioPlayer.h>
|
|
5
6
|
#include <audioapi/utils/AudioArray.h>
|
|
6
7
|
#include <audioapi/utils/AudioBus.h>
|
|
@@ -17,14 +18,11 @@ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus
|
|
|
17
18
|
int framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE);
|
|
18
19
|
renderAudio_(audioBus_, framesToProcess);
|
|
19
20
|
|
|
20
|
-
// TODO: optimize this with SIMD?
|
|
21
21
|
for (int channel = 0; channel < channelCount_; channel += 1) {
|
|
22
22
|
float *outputChannel = (float *)outputData->mBuffers[channel].mData;
|
|
23
23
|
auto *inputChannel = audioBus_->getChannel(channel)->getData();
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
outputChannel[processedFrames + i] = inputChannel[i];
|
|
27
|
-
}
|
|
25
|
+
memcpy(outputChannel + processedFrames, inputChannel, framesToProcess * sizeof(float));
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
processedFrames += framesToProcess;
|
|
@@ -45,14 +43,11 @@ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus
|
|
|
45
43
|
int framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE);
|
|
46
44
|
renderAudio_(audioBus_, framesToProcess);
|
|
47
45
|
|
|
48
|
-
// TODO: optimize this with SIMD?
|
|
49
46
|
for (int channel = 0; channel < channelCount_; channel += 1) {
|
|
50
47
|
float *outputChannel = (float *)outputData->mBuffers[channel].mData;
|
|
51
48
|
auto *inputChannel = audioBus_->getChannel(channel)->getData();
|
|
52
49
|
|
|
53
|
-
|
|
54
|
-
outputChannel[processedFrames + i] = inputChannel[i];
|
|
55
|
-
}
|
|
50
|
+
memcpy(outputChannel + processedFrames, inputChannel, framesToProcess * sizeof(float));
|
|
56
51
|
}
|
|
57
52
|
|
|
58
53
|
processedFrames += framesToProcess;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-audio-api",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "react-native-audio-api provides system for controlling audio in React Native environment compatible with Web Audio API specification",
|
|
5
5
|
"bin": {
|
|
6
6
|
"setup-rn-audio-api-web": "./scripts/setup-rn-audio-api-web.js"
|