react-native-audio-api 0.6.0-rc.2 → 0.6.0-rc.4

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.
@@ -154,9 +154,10 @@ void AnalyserNode::processNode(
154
154
  // Down mix the input bus to mono
155
155
  downMixBus_->copy(processingBus.get());
156
156
 
157
+ auto framesToCopy = 0;
158
+
157
159
  if (vWriteIndex_ + framesToProcess > inputBuffer_->getSize()) {
158
- auto framesToCopy =
159
- static_cast<int>(inputBuffer_->getSize()) - vWriteIndex_;
160
+ framesToCopy = static_cast<int>(inputBuffer_->getSize()) - vWriteIndex_;
160
161
  memcpy(
161
162
  inputBuffer_->getData() + vWriteIndex_,
162
163
  downMixBus_->getChannel(0)->getData(),
@@ -168,7 +169,7 @@ void AnalyserNode::processNode(
168
169
 
169
170
  memcpy(
170
171
  inputBuffer_->getData() + vWriteIndex_,
171
- downMixBus_->getChannel(0)->getData(),
172
+ downMixBus_->getChannel(0)->getData() + framesToCopy,
172
173
  framesToProcess * sizeof(float));
173
174
 
174
175
  vWriteIndex_ += framesToProcess;
@@ -31,6 +31,10 @@ class IOSAudioRecorder : public AudioRecorder {
31
31
  private:
32
32
  NativeAudioRecorder *audioRecorder_;
33
33
  std::atomic<bool> isRunning_;
34
+
35
+ std::shared_ptr<AudioBus> circularBuffer_;
36
+ int writeIdx_ = 0;
37
+ int readIdx_ = 0;
34
38
  };
35
39
 
36
40
  } // namespace audioapi
@@ -16,19 +16,65 @@ IOSAudioRecorder::IOSAudioRecorder(
16
16
  const std::function<void(std::shared_ptr<AudioBus>, int, double)> &onAudioReady)
17
17
  : AudioRecorder(sampleRate, bufferLength, onError, onStatusChange, onAudioReady)
18
18
  {
19
+ circularBuffer_ = std::make_shared<AudioBus>(std::max(2 * bufferLength, 2048), 1, sampleRate);
20
+
19
21
  AudioReceiverBlock audioReceiverBlock = ^(const AudioBufferList *inputBuffer, int numFrames, AVAudioTime *when) {
20
22
  if (isRunning_.load()) {
21
- auto bus = std::make_shared<AudioBus>(numFrames, 1, sampleRate);
22
-
23
+ // copying to circularBuffer_
24
+ auto *circularBufferChannel = circularBuffer_->getChannel(0)->getData();
23
25
  auto *inputChannel = (float *)inputBuffer->mBuffers[0].mData;
24
- auto *outputChannel = bus->getChannel(0)->getData();
25
26
 
26
- memcpy(outputChannel, inputChannel, numFrames * sizeof(float));
27
- onAudioReady_(bus, numFrames, [when sampleTime] / [when sampleRate]);
27
+ auto framesToProcess = numFrames;
28
+ auto framesToCopy = 0;
29
+
30
+ if (writeIdx_ + numFrames > circularBuffer_->getSize()) {
31
+ framesToCopy = circularBuffer_->getSize() - writeIdx_;
32
+ memcpy(circularBufferChannel + writeIdx_, inputChannel, framesToCopy * sizeof(float));
33
+ framesToProcess -= framesToCopy;
34
+ writeIdx_ = 0;
35
+ }
36
+
37
+ memcpy(circularBufferChannel + writeIdx_, inputChannel + framesToCopy, framesToProcess * sizeof(float));
38
+
39
+ writeIdx_ += framesToProcess;
40
+ if (writeIdx_ >= circularBuffer_->getSize()) {
41
+ writeIdx_ = 0;
42
+ }
43
+
44
+ // copying to output bus and invoking callback
45
+ auto availableFrames =
46
+ writeIdx_ >= readIdx_ ? writeIdx_ - readIdx_ : circularBuffer_->getSize() - (readIdx_ - writeIdx_);
47
+
48
+ while (availableFrames >= bufferLength_) {
49
+ auto bus = std::make_shared<AudioBus>(bufferLength_, 1, sampleRate_);
50
+ auto *outputChannel = bus->getChannel(0)->getData();
51
+
52
+ framesToProcess = bufferLength_;
53
+ framesToCopy = 0;
54
+ if (readIdx_ + bufferLength_ > circularBuffer_->getSize()) {
55
+ framesToCopy = circularBuffer_->getSize() - readIdx_;
56
+ memcpy(outputChannel, circularBufferChannel + readIdx_, framesToCopy * sizeof(float));
57
+ framesToProcess -= framesToCopy;
58
+ readIdx_ = 0;
59
+ }
60
+
61
+ memcpy(outputChannel + framesToCopy, circularBufferChannel + readIdx_, framesToProcess * sizeof(float));
62
+
63
+ readIdx_ += framesToProcess;
64
+ if (readIdx_ >= circularBuffer_->getSize()) {
65
+ readIdx_ = 0;
66
+ }
67
+
68
+ onAudioReady_(bus, bufferLength_, [when sampleTime] / [when sampleRate]);
69
+
70
+ availableFrames -= bufferLength_;
71
+ }
28
72
  }
29
73
  };
30
74
 
31
- audioRecorder_ = [[NativeAudioRecorder alloc] initWithReceiverBlock:audioReceiverBlock bufferLength:bufferLength];
75
+ audioRecorder_ = [[NativeAudioRecorder alloc] initWithReceiverBlock:audioReceiverBlock
76
+ bufferLength:bufferLength
77
+ sampleRate:sampleRate];
32
78
  }
33
79
 
34
80
  IOSAudioRecorder::~IOSAudioRecorder()
@@ -8,13 +8,19 @@ typedef void (^AudioReceiverBlock)(const AudioBufferList *inputBuffer, int numFr
8
8
  @interface NativeAudioRecorder : NSObject
9
9
 
10
10
  @property (nonatomic, assign) int bufferLength;
11
- @property (nonatomic, assign) double sampleRate;
11
+ @property (nonatomic, assign) float sampleRate;
12
12
 
13
13
  @property (nonatomic, strong) AVAudioSinkNode *sinkNode;
14
14
  @property (nonatomic, copy) AVAudioSinkNodeReceiverBlock receiverSinkBlock;
15
15
  @property (nonatomic, copy) AudioReceiverBlock receiverBlock;
16
16
 
17
- - (instancetype)initWithReceiverBlock:(AudioReceiverBlock)receiverBlock bufferLength:(int)bufferLength;
17
+ @property (nonatomic, strong) AVAudioConverter *audioConverter;
18
+ @property (nonatomic, strong) AVAudioFormat *inputFormat;
19
+ @property (nonatomic, strong) AVAudioFormat *outputFormat;
20
+
21
+ - (instancetype)initWithReceiverBlock:(AudioReceiverBlock)receiverBlock
22
+ bufferLength:(int)bufferLength
23
+ sampleRate:(float)sampleRate;
18
24
 
19
25
  - (void)start;
20
26
 
@@ -4,23 +4,34 @@
4
4
 
5
5
  @implementation NativeAudioRecorder
6
6
 
7
- - (instancetype)initWithReceiverBlock:(AudioReceiverBlock)receiverBlock bufferLength:(int)bufferLength
7
+ - (instancetype)initWithReceiverBlock:(AudioReceiverBlock)receiverBlock
8
+ bufferLength:(int)bufferLength
9
+ sampleRate:(float)sampleRate
8
10
  {
9
11
  if (self = [super init]) {
10
12
  self.bufferLength = bufferLength;
11
- self.sampleRate = [[[AudioSessionManager sharedInstance] getDevicePreferredSampleRate] doubleValue];
13
+ self.sampleRate = sampleRate;
12
14
 
13
15
  self.receiverBlock = [receiverBlock copy];
14
16
 
17
+ float devicePrefferedSampleRate = [[[AudioSessionManager sharedInstance] getDevicePreferredSampleRate] floatValue];
18
+
19
+ self.inputFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
20
+ sampleRate:devicePrefferedSampleRate
21
+ channels:1
22
+ interleaved:NO];
23
+ self.outputFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
24
+ sampleRate:sampleRate
25
+ channels:1
26
+ interleaved:NO];
27
+ self.audioConverter = [[AVAudioConverter alloc] initFromFormat:self.inputFormat toFormat:self.outputFormat];
28
+
15
29
  __weak typeof(self) weakSelf = self;
16
30
  self.receiverSinkBlock = ^OSStatus(
17
31
  const AudioTimeStamp *_Nonnull timestamp,
18
32
  AVAudioFrameCount frameCount,
19
33
  const AudioBufferList *_Nonnull inputData) {
20
- AVAudioTime *time = [[AVAudioTime alloc] initWithAudioTimeStamp:timestamp sampleRate:weakSelf.sampleRate];
21
- weakSelf.receiverBlock(inputData, frameCount, time);
22
-
23
- return kAudioServicesNoError;
34
+ return [weakSelf processAudioInput:inputData withFrameCount:frameCount atTimestamp:timestamp];
24
35
  };
25
36
 
26
37
  self.sinkNode = [[AVAudioSinkNode alloc] initWithReceiverBlock:self.receiverSinkBlock];
@@ -29,6 +40,55 @@
29
40
  return self;
30
41
  }
31
42
 
43
+ - (OSStatus)processAudioInput:(const AudioBufferList *)inputData
44
+ withFrameCount:(AVAudioFrameCount)frameCount
45
+ atTimestamp:(const AudioTimeStamp *)timestamp
46
+ {
47
+ float inputSampleRate = self.inputFormat.sampleRate;
48
+ float outputSampleRate = self.outputFormat.sampleRate;
49
+
50
+ AVAudioTime *time = [[AVAudioTime alloc] initWithAudioTimeStamp:timestamp sampleRate:outputSampleRate];
51
+
52
+ if (inputSampleRate != outputSampleRate) {
53
+ AVAudioPCMBuffer *inputBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:self.inputFormat
54
+ frameCapacity:frameCount];
55
+
56
+ memcpy(
57
+ inputBuffer.mutableAudioBufferList->mBuffers[0].mData,
58
+ inputData->mBuffers[0].mData,
59
+ inputData->mBuffers[0].mDataByteSize);
60
+ inputBuffer.frameLength = frameCount;
61
+
62
+ int outputFrameCount = frameCount * outputSampleRate / inputSampleRate;
63
+
64
+ AVAudioPCMBuffer *outputBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:self.audioConverter.outputFormat
65
+ frameCapacity:outputFrameCount];
66
+
67
+ NSError *error = nil;
68
+ AVAudioConverterInputBlock inputBlock =
69
+ ^AVAudioBuffer *_Nullable(AVAudioPacketCount inNumberOfPackets, AVAudioConverterInputStatus *outStatus)
70
+ {
71
+ *outStatus = AVAudioConverterInputStatus_HaveData;
72
+ return inputBuffer;
73
+ };
74
+
75
+ [self.audioConverter convertToBuffer:outputBuffer error:&error withInputFromBlock:inputBlock];
76
+
77
+ if (error) {
78
+ NSLog(@"Error during audio conversion: %@", error.localizedDescription);
79
+ return kAudioServicesBadSpecifierSizeError;
80
+ }
81
+
82
+ self.receiverBlock(outputBuffer.audioBufferList, outputBuffer.frameLength, time);
83
+
84
+ return kAudioServicesNoError;
85
+ }
86
+
87
+ self.receiverBlock(inputData, frameCount, time);
88
+
89
+ return kAudioServicesNoError;
90
+ }
91
+
32
92
  - (void)start
33
93
  {
34
94
  [[AudioEngine sharedInstance] attachInputNode:self.sinkNode];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-audio-api",
3
- "version": "0.6.0-rc.2",
3
+ "version": "0.6.0-rc.4",
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"