react-native-audio-api 0.6.0-rc.4 → 0.6.0-rc.5
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/java/com/swmansion/audioapi/AudioManagerModule.kt +13 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +20 -0
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +1 -0
- package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +19 -56
- package/common/cpp/audioapi/core/analysis/AnalyserNode.h +3 -2
- package/common/cpp/audioapi/utils/AudioArray.h +1 -1
- package/common/cpp/audioapi/utils/CircularAudioArray.cpp +94 -0
- package/common/cpp/audioapi/utils/CircularAudioArray.h +26 -0
- package/ios/audioapi/ios/AudioManagerModule.mm +15 -0
- package/ios/audioapi/ios/core/IOSAudioRecorder.h +4 -3
- package/ios/audioapi/ios/core/IOSAudioRecorder.mm +24 -50
- package/ios/audioapi/ios/system/AudioSessionManager.h +2 -0
- package/ios/audioapi/ios/system/AudioSessionManager.mm +35 -0
- package/lib/commonjs/specs/NativeAudioManagerModule.js +6 -0
- package/lib/commonjs/specs/NativeAudioManagerModule.js.map +1 -1
- package/lib/commonjs/system/AudioManager.js +6 -0
- package/lib/commonjs/system/AudioManager.js.map +1 -1
- package/lib/module/specs/NativeAudioManagerModule.js +6 -0
- package/lib/module/specs/NativeAudioManagerModule.js.map +1 -1
- package/lib/module/system/AudioManager.js +6 -0
- package/lib/module/system/AudioManager.js.map +1 -1
- package/lib/typescript/specs/NativeAudioManagerModule.d.ts +3 -0
- package/lib/typescript/specs/NativeAudioManagerModule.d.ts.map +1 -1
- package/lib/typescript/system/AudioManager.d.ts +3 -1
- package/lib/typescript/system/AudioManager.d.ts.map +1 -1
- package/lib/typescript/system/types.d.ts +1 -0
- package/lib/typescript/system/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/specs/NativeAudioManagerModule.ts +8 -0
- package/src/system/AudioManager.ts +9 -0
- package/src/system/types.ts +2 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.swmansion.audioapi
|
|
2
2
|
|
|
3
|
+
import com.facebook.react.bridge.Promise
|
|
3
4
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
5
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
5
6
|
import com.facebook.react.bridge.ReactMethod
|
|
@@ -60,5 +61,17 @@ class AudioManagerModule(
|
|
|
60
61
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
61
62
|
fun observeVolumeChanges(enable: Boolean) = MediaSessionManager.observeVolumeChanges(enable)
|
|
62
63
|
|
|
64
|
+
@ReactMethod
|
|
65
|
+
fun requestRecordingPermissions(promise: Promise) {
|
|
66
|
+
val res = MediaSessionManager.requestRecordingPermissions(currentActivity)
|
|
67
|
+
promise.resolve(res)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@ReactMethod
|
|
71
|
+
fun checkRecordingPermissions(promise: Promise) {
|
|
72
|
+
val res = MediaSessionManager.checkRecordingPermissions()
|
|
73
|
+
promise.resolve(res)
|
|
74
|
+
}
|
|
75
|
+
|
|
63
76
|
override fun getName(): String = NAME
|
|
64
77
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package com.swmansion.audioapi.system
|
|
2
2
|
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.app.Activity
|
|
3
5
|
import android.app.NotificationChannel
|
|
4
6
|
import android.app.NotificationManager
|
|
5
7
|
import android.content.ComponentName
|
|
@@ -7,12 +9,14 @@ import android.content.Context
|
|
|
7
9
|
import android.content.Intent
|
|
8
10
|
import android.content.IntentFilter
|
|
9
11
|
import android.content.ServiceConnection
|
|
12
|
+
import android.content.pm.PackageManager
|
|
10
13
|
import android.media.AudioManager
|
|
11
14
|
import android.os.Build
|
|
12
15
|
import android.os.IBinder
|
|
13
16
|
import android.support.v4.media.session.MediaSessionCompat
|
|
14
17
|
import android.util.Log
|
|
15
18
|
import androidx.annotation.RequiresApi
|
|
19
|
+
import androidx.core.app.ActivityCompat
|
|
16
20
|
import androidx.core.app.NotificationCompat
|
|
17
21
|
import androidx.core.content.ContextCompat
|
|
18
22
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
@@ -147,6 +151,22 @@ object MediaSessionManager {
|
|
|
147
151
|
}
|
|
148
152
|
}
|
|
149
153
|
|
|
154
|
+
fun requestRecordingPermissions(currentActivity: Activity?): String {
|
|
155
|
+
ActivityCompat.requestPermissions(currentActivity!!, arrayOf(Manifest.permission.RECORD_AUDIO), 200)
|
|
156
|
+
return checkRecordingPermissions()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
fun checkRecordingPermissions(): String =
|
|
160
|
+
if (ContextCompat.checkSelfPermission(
|
|
161
|
+
reactContext,
|
|
162
|
+
Manifest.permission.RECORD_AUDIO,
|
|
163
|
+
) == PackageManager.PERMISSION_GRANTED
|
|
164
|
+
) {
|
|
165
|
+
"Granted"
|
|
166
|
+
} else {
|
|
167
|
+
"Denied"
|
|
168
|
+
}
|
|
169
|
+
|
|
150
170
|
@RequiresApi(Build.VERSION_CODES.O)
|
|
151
171
|
private fun createChannel() {
|
|
152
172
|
val notificationManager =
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include <audioapi/dsp/Windows.h>
|
|
6
6
|
#include <audioapi/utils/AudioArray.h>
|
|
7
7
|
#include <audioapi/utils/AudioBus.h>
|
|
8
|
+
#include <audioapi/utils/CircularAudioArray.h>
|
|
8
9
|
|
|
9
10
|
namespace audioapi {
|
|
10
11
|
AnalyserNode::AnalyserNode(audioapi::BaseAudioContext *context)
|
|
@@ -13,9 +14,9 @@ AnalyserNode::AnalyserNode(audioapi::BaseAudioContext *context)
|
|
|
13
14
|
minDecibels_(-100),
|
|
14
15
|
maxDecibels_(-30),
|
|
15
16
|
smoothingTimeConstant_(0.8),
|
|
16
|
-
windowType_(WindowType::BLACKMAN)
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
windowType_(WindowType::BLACKMAN) {
|
|
18
|
+
inputBuffer_ = std::make_unique<CircularAudioArray>(MAX_FFT_SIZE * 2);
|
|
19
|
+
tempBuffer_ = std::make_unique<AudioArray>(fftSize_);
|
|
19
20
|
magnitudeBuffer_ = std::make_unique<AudioArray>(fftSize_ / 2);
|
|
20
21
|
downMixBus_ = std::make_unique<AudioBus>(
|
|
21
22
|
RENDER_QUANTUM_SIZE, 1, context_->getSampleRate());
|
|
@@ -61,6 +62,7 @@ void AnalyserNode::setFftSize(int fftSize) {
|
|
|
61
62
|
fft_ = std::make_unique<dsp::FFT>(fftSize_);
|
|
62
63
|
complexData_ = std::vector<std::complex<float>>(fftSize_);
|
|
63
64
|
magnitudeBuffer_ = std::make_unique<AudioArray>(fftSize_ / 2);
|
|
65
|
+
tempBuffer_ = std::make_unique<AudioArray>(fftSize_);
|
|
64
66
|
setWindowData(windowType_, fftSize_);
|
|
65
67
|
}
|
|
66
68
|
|
|
@@ -116,21 +118,17 @@ void AnalyserNode::getByteFrequencyData(uint8_t *data, int length) {
|
|
|
116
118
|
|
|
117
119
|
void AnalyserNode::getFloatTimeDomainData(float *data, int length) {
|
|
118
120
|
auto size = std::min(fftSize_, length);
|
|
119
|
-
|
|
120
|
-
for (int i = 0; i < size; i++) {
|
|
121
|
-
data[i] = inputBuffer_->getData()
|
|
122
|
-
[(vWriteIndex_ + i - fftSize_ + inputBuffer_->getSize()) %
|
|
123
|
-
inputBuffer_->getSize()];
|
|
124
|
-
}
|
|
121
|
+
inputBuffer_->pop_back(data, size, std::max(0, fftSize_ - size), true);
|
|
125
122
|
}
|
|
126
123
|
|
|
127
124
|
void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) {
|
|
128
125
|
auto size = std::min(fftSize_, length);
|
|
129
126
|
|
|
127
|
+
inputBuffer_->pop_back(
|
|
128
|
+
tempBuffer_->getData(), fftSize_, std::max(0, fftSize_ - size), true);
|
|
129
|
+
|
|
130
130
|
for (int i = 0; i < size; i++) {
|
|
131
|
-
auto value =
|
|
132
|
-
[(vWriteIndex_ + i - fftSize_ + inputBuffer_->getSize()) %
|
|
133
|
-
inputBuffer_->getSize()];
|
|
131
|
+
auto value = tempBuffer_->getData()[i];
|
|
134
132
|
|
|
135
133
|
float scaledValue = 128 * (value + 1);
|
|
136
134
|
|
|
@@ -153,29 +151,9 @@ void AnalyserNode::processNode(
|
|
|
153
151
|
|
|
154
152
|
// Down mix the input bus to mono
|
|
155
153
|
downMixBus_->copy(processingBus.get());
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (vWriteIndex_ + framesToProcess > inputBuffer_->getSize()) {
|
|
160
|
-
framesToCopy = static_cast<int>(inputBuffer_->getSize()) - vWriteIndex_;
|
|
161
|
-
memcpy(
|
|
162
|
-
inputBuffer_->getData() + vWriteIndex_,
|
|
163
|
-
downMixBus_->getChannel(0)->getData(),
|
|
164
|
-
framesToCopy * sizeof(float));
|
|
165
|
-
|
|
166
|
-
vWriteIndex_ = 0;
|
|
167
|
-
framesToProcess -= framesToCopy;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
memcpy(
|
|
171
|
-
inputBuffer_->getData() + vWriteIndex_,
|
|
172
|
-
downMixBus_->getChannel(0)->getData() + framesToCopy,
|
|
173
|
-
framesToProcess * sizeof(float));
|
|
174
|
-
|
|
175
|
-
vWriteIndex_ += framesToProcess;
|
|
176
|
-
if (vWriteIndex_ >= inputBuffer_->getSize()) {
|
|
177
|
-
vWriteIndex_ = 0;
|
|
178
|
-
}
|
|
154
|
+
// Copy the down mixed bus to the input buffer (circular buffer)
|
|
155
|
+
inputBuffer_->push_back(
|
|
156
|
+
downMixBus_->getChannel(0)->getData(), framesToProcess, true);
|
|
179
157
|
|
|
180
158
|
shouldDoFFTAnalysis_ = true;
|
|
181
159
|
}
|
|
@@ -187,33 +165,18 @@ void AnalyserNode::doFFTAnalysis() {
|
|
|
187
165
|
|
|
188
166
|
shouldDoFFTAnalysis_ = false;
|
|
189
167
|
|
|
190
|
-
// We
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
// We want to copy last fftSize_ elements added to the input buffer(fftSize_
|
|
195
|
-
// elements before vWriteIndex_). However inputBuffer_ works like a circular
|
|
196
|
-
// buffer so we have two cases to consider.
|
|
197
|
-
if (vWriteIndex_ < fftSize_) {
|
|
198
|
-
tempBuffer.copy(
|
|
199
|
-
inputBuffer_.get(),
|
|
200
|
-
vWriteIndex_ - fftSize_ + inputBuffer_->getSize(),
|
|
201
|
-
0,
|
|
202
|
-
fftSize_ - vWriteIndex_);
|
|
203
|
-
tempBuffer.copy(
|
|
204
|
-
inputBuffer_.get(), 0, fftSize_ - vWriteIndex_, vWriteIndex_);
|
|
205
|
-
} else {
|
|
206
|
-
tempBuffer.copy(inputBuffer_.get(), vWriteIndex_ - fftSize_, 0, fftSize_);
|
|
207
|
-
}
|
|
168
|
+
// We want to copy last fftSize_ elements added to the input buffer to apply
|
|
169
|
+
// the window.
|
|
170
|
+
inputBuffer_->pop_back(tempBuffer_->getData(), fftSize_, 0, true);
|
|
208
171
|
|
|
209
172
|
dsp::multiply(
|
|
210
|
-
|
|
173
|
+
tempBuffer_->getData(),
|
|
211
174
|
windowData_->getData(),
|
|
212
|
-
|
|
175
|
+
tempBuffer_->getData(),
|
|
213
176
|
fftSize_);
|
|
214
177
|
|
|
215
178
|
// do fft analysis - get frequency domain data
|
|
216
|
-
fft_->doFFT(
|
|
179
|
+
fft_->doFFT(tempBuffer_->getData(), complexData_);
|
|
217
180
|
|
|
218
181
|
// Zero out nquist component
|
|
219
182
|
complexData_[0] = std::complex<float>(complexData_[0].real(), 0);
|
|
@@ -13,6 +13,7 @@ namespace audioapi {
|
|
|
13
13
|
|
|
14
14
|
class AudioBus;
|
|
15
15
|
class AudioArray;
|
|
16
|
+
class CircularAudioArray;
|
|
16
17
|
|
|
17
18
|
class AnalyserNode : public AudioNode {
|
|
18
19
|
public:
|
|
@@ -49,9 +50,9 @@ class AnalyserNode : public AudioNode {
|
|
|
49
50
|
WindowType windowType_;
|
|
50
51
|
std::shared_ptr<AudioArray> windowData_;
|
|
51
52
|
|
|
52
|
-
std::unique_ptr<
|
|
53
|
+
std::unique_ptr<CircularAudioArray> inputBuffer_;
|
|
53
54
|
std::unique_ptr<AudioBus> downMixBus_;
|
|
54
|
-
|
|
55
|
+
std::unique_ptr<AudioArray> tempBuffer_;
|
|
55
56
|
|
|
56
57
|
std::unique_ptr<dsp::FFT> fft_;
|
|
57
58
|
std::vector<std::complex<float>> complexData_;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#include <audioapi/utils/CircularAudioArray.h>
|
|
2
|
+
|
|
3
|
+
namespace audioapi {
|
|
4
|
+
|
|
5
|
+
CircularAudioArray::CircularAudioArray(size_t size) : AudioArray(size) {}
|
|
6
|
+
|
|
7
|
+
void CircularAudioArray::push_back(
|
|
8
|
+
const float *data,
|
|
9
|
+
size_t size,
|
|
10
|
+
bool skipAvailableSpaceCheck) {
|
|
11
|
+
if (size > size_) {
|
|
12
|
+
throw std::overflow_error("size exceeds CircularAudioArray size_");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (size > getAvailableSpace() && !skipAvailableSpaceCheck) {
|
|
16
|
+
throw std::overflow_error("not enough space in CircularAudioArray");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (vWriteIndex_ + size > size_) {
|
|
20
|
+
auto partSize = size_ - vWriteIndex_;
|
|
21
|
+
memcpy(data_ + vWriteIndex_, data, partSize * sizeof(float));
|
|
22
|
+
memcpy(data_, data + partSize, (size - partSize) * sizeof(float));
|
|
23
|
+
} else {
|
|
24
|
+
memcpy(data_ + vWriteIndex_, data, size * sizeof(float));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
vWriteIndex_ = vWriteIndex_ + size > size_ ? vWriteIndex_ + size - size_
|
|
28
|
+
: vWriteIndex_ + size;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
void CircularAudioArray::pop_front(
|
|
32
|
+
float *data,
|
|
33
|
+
size_t size,
|
|
34
|
+
bool skipAvailableDataCheck) {
|
|
35
|
+
if (size > size_) {
|
|
36
|
+
throw std::overflow_error("size exceeds CircularAudioArray size_");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (size > getNumberOfAvailableFrames() && !skipAvailableDataCheck) {
|
|
40
|
+
throw std::overflow_error("not enough data in CircularAudioArray");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (vReadIndex_ + size > size_) {
|
|
44
|
+
auto partSize = size_ - vReadIndex_;
|
|
45
|
+
memcpy(data, data_ + vReadIndex_, partSize * sizeof(float));
|
|
46
|
+
memcpy(data + partSize, data_, (size - partSize) * sizeof(float));
|
|
47
|
+
} else {
|
|
48
|
+
memcpy(data, data_ + vReadIndex_, size * sizeof(float));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
vReadIndex_ = vReadIndex_ + size > size_ ? vReadIndex_ + size - size_
|
|
52
|
+
: vReadIndex_ + size;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
void CircularAudioArray::pop_back(
|
|
56
|
+
float *data,
|
|
57
|
+
size_t size,
|
|
58
|
+
size_t offset,
|
|
59
|
+
bool skipAvailableDataCheck) {
|
|
60
|
+
if (size > size_) {
|
|
61
|
+
throw std::overflow_error("size exceeds CircularAudioArray size_");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (size + offset > getNumberOfAvailableFrames() && !skipAvailableDataCheck) {
|
|
65
|
+
throw std::overflow_error("not enough data in CircularAudioArray");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (vWriteIndex_ <= offset) {
|
|
69
|
+
memcpy(
|
|
70
|
+
data,
|
|
71
|
+
data_ + size_ - (offset - vWriteIndex_) - size,
|
|
72
|
+
size * sizeof(float));
|
|
73
|
+
} else if (vWriteIndex_ <= size + offset) {
|
|
74
|
+
auto partSize = size + offset - vWriteIndex_;
|
|
75
|
+
memcpy(data, data_ + size_ - partSize, partSize * sizeof(float));
|
|
76
|
+
memcpy(data + partSize, data_, (size - partSize) * sizeof(float));
|
|
77
|
+
} else {
|
|
78
|
+
memcpy(data, data_ + vWriteIndex_ - size - offset, size * sizeof(float));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
vReadIndex_ = vWriteIndex_ - offset < 0 ? size + vWriteIndex_ - offset
|
|
82
|
+
: vWriteIndex_ - offset;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
size_t CircularAudioArray::getNumberOfAvailableFrames() const {
|
|
86
|
+
return vWriteIndex_ >= vReadIndex_ ? vWriteIndex_ - vReadIndex_
|
|
87
|
+
: size_ - vReadIndex_ + vWriteIndex_;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
size_t CircularAudioArray::getAvailableSpace() const {
|
|
91
|
+
return size_ - getNumberOfAvailableFrames();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <audioapi/utils/AudioArray.h>
|
|
4
|
+
|
|
5
|
+
namespace audioapi {
|
|
6
|
+
|
|
7
|
+
class CircularAudioArray : public AudioArray {
|
|
8
|
+
public:
|
|
9
|
+
explicit CircularAudioArray(size_t size);
|
|
10
|
+
CircularAudioArray(const CircularAudioArray &other) = default;
|
|
11
|
+
~CircularAudioArray() = default;
|
|
12
|
+
|
|
13
|
+
void push_back(const float *data, size_t size, bool skipAvailableSpaceCheck = false);
|
|
14
|
+
void pop_front(float *data, size_t size, bool skipAvailableDataCheck = false);
|
|
15
|
+
void pop_back(float *data, size_t size, size_t offset = 0, bool skipAvailableDataCheck = false);
|
|
16
|
+
|
|
17
|
+
[[nodiscard]] size_t getNumberOfAvailableFrames() const;
|
|
18
|
+
|
|
19
|
+
private:
|
|
20
|
+
size_t vWriteIndex_ = 0;
|
|
21
|
+
size_t vReadIndex_ = 0;
|
|
22
|
+
|
|
23
|
+
[[nodiscard]] size_t getAvailableSpace() const;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
} // namespace audioapi
|
|
@@ -69,6 +69,21 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getDevicePreferredSampleRate)
|
|
|
69
69
|
return [self.audioSessionManager getDevicePreferredSampleRate];
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
RCT_EXPORT_METHOD(requestRecordingPermissions : (RCTPromiseResolveBlock)resolve
|
|
73
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
74
|
+
{
|
|
75
|
+
|
|
76
|
+
NSString* res = [self.audioSessionManager requestRecordingPermissions];
|
|
77
|
+
resolve(res);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
RCT_EXPORT_METHOD(checkRecordingPermissions : (RCTPromiseResolveBlock)resolve
|
|
81
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
82
|
+
{
|
|
83
|
+
NSString* res = [self.audioSessionManager checkRecordingPermissions];
|
|
84
|
+
resolve(res);
|
|
85
|
+
}
|
|
86
|
+
|
|
72
87
|
- (NSArray<NSString *> *)supportedEvents
|
|
73
88
|
{
|
|
74
89
|
return @[
|
|
@@ -12,6 +12,7 @@ typedef struct objc_object NativeAudioRecorder;
|
|
|
12
12
|
namespace audioapi {
|
|
13
13
|
|
|
14
14
|
class AudioBus;
|
|
15
|
+
class CircularAudioArray;
|
|
15
16
|
|
|
16
17
|
class IOSAudioRecorder : public AudioRecorder {
|
|
17
18
|
public:
|
|
@@ -32,9 +33,9 @@ class IOSAudioRecorder : public AudioRecorder {
|
|
|
32
33
|
NativeAudioRecorder *audioRecorder_;
|
|
33
34
|
std::atomic<bool> isRunning_;
|
|
34
35
|
|
|
35
|
-
std::shared_ptr<
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
std::shared_ptr<CircularAudioArray> circularBuffer_;
|
|
37
|
+
|
|
38
|
+
void sendRemainingData();
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
} // namespace audioapi
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include <audioapi/ios/core/IOSAudioRecorder.h>
|
|
6
6
|
#include <audioapi/utils/AudioArray.h>
|
|
7
7
|
#include <audioapi/utils/AudioBus.h>
|
|
8
|
+
#include <audioapi/utils/CircularAudioArray.h>
|
|
8
9
|
|
|
9
10
|
namespace audioapi {
|
|
10
11
|
|
|
@@ -16,59 +17,20 @@ IOSAudioRecorder::IOSAudioRecorder(
|
|
|
16
17
|
const std::function<void(std::shared_ptr<AudioBus>, int, double)> &onAudioReady)
|
|
17
18
|
: AudioRecorder(sampleRate, bufferLength, onError, onStatusChange, onAudioReady)
|
|
18
19
|
{
|
|
19
|
-
circularBuffer_ = std::make_shared<
|
|
20
|
+
circularBuffer_ = std::make_shared<CircularAudioArray>(std::max(2 * bufferLength, 2048));
|
|
20
21
|
|
|
21
22
|
AudioReceiverBlock audioReceiverBlock = ^(const AudioBufferList *inputBuffer, int numFrames, AVAudioTime *when) {
|
|
22
23
|
if (isRunning_.load()) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
auto
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
}
|
|
24
|
+
auto *inputChannel = static_cast<float *>(inputBuffer->mBuffers[0].mData);
|
|
25
|
+
circularBuffer_->push_back(inputChannel, numFrames);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
while (circularBuffer_->getNumberOfAvailableFrames() >= bufferLength_) {
|
|
29
|
+
auto bus = std::make_shared<AudioBus>(bufferLength_, 1, sampleRate_);
|
|
30
|
+
auto *outputChannel = bus->getChannel(0)->getData();
|
|
31
|
+
|
|
32
|
+
circularBuffer_->pop_front(outputChannel, bufferLength_);
|
|
33
|
+
onAudioReady_(bus, bufferLength_, [when sampleTime] / [when sampleRate]);
|
|
72
34
|
}
|
|
73
35
|
};
|
|
74
36
|
|
|
@@ -103,6 +65,18 @@ void IOSAudioRecorder::stop()
|
|
|
103
65
|
|
|
104
66
|
isRunning_.store(false);
|
|
105
67
|
[audioRecorder_ stop];
|
|
68
|
+
|
|
69
|
+
sendRemainingData();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
void IOSAudioRecorder::sendRemainingData()
|
|
73
|
+
{
|
|
74
|
+
auto bus = std::make_shared<AudioBus>(circularBuffer_->getNumberOfAvailableFrames(), 1, sampleRate_);
|
|
75
|
+
auto *outputChannel = bus->getChannel(0)->getData();
|
|
76
|
+
auto availableFrames = circularBuffer_->getNumberOfAvailableFrames();
|
|
77
|
+
|
|
78
|
+
circularBuffer_->pop_front(outputChannel, circularBuffer_->getNumberOfAvailableFrames());
|
|
79
|
+
onAudioReady_(bus, availableFrames, 0);
|
|
106
80
|
}
|
|
107
81
|
|
|
108
82
|
} // namespace audioapi
|
|
@@ -20,5 +20,7 @@
|
|
|
20
20
|
- (NSNumber *)getDevicePreferredSampleRate;
|
|
21
21
|
- (void)setAudioSessionOptions:(NSString *)category mode:(NSString *)mode options:(NSArray *)options;
|
|
22
22
|
- (bool)setActive:(bool)active;
|
|
23
|
+
- (NSString *)requestRecordingPermissions;
|
|
24
|
+
- (NSString *)checkRecordingPermissions;
|
|
23
25
|
|
|
24
26
|
@end
|
|
@@ -192,4 +192,39 @@ static AudioSessionManager *_sharedInstance = nil;
|
|
|
192
192
|
return true;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
- (NSString *)requestRecordingPermissions
|
|
196
|
+
{
|
|
197
|
+
[self.audioSession requestRecordPermission:^(BOOL granted) {}];
|
|
198
|
+
return [self checkRecordingPermissions];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
- (NSString *)checkRecordingPermissions
|
|
202
|
+
{
|
|
203
|
+
if (@available(iOS 17, *)) {
|
|
204
|
+
NSInteger res = [[AVAudioApplication sharedInstance] recordPermission];
|
|
205
|
+
switch (res) {
|
|
206
|
+
case AVAudioApplicationRecordPermissionUndetermined:
|
|
207
|
+
return @"Undetermined";
|
|
208
|
+
case AVAudioApplicationRecordPermissionGranted:
|
|
209
|
+
return @"Granted";
|
|
210
|
+
case AVAudioApplicationRecordPermissionDenied:
|
|
211
|
+
return @"Denied";
|
|
212
|
+
default:
|
|
213
|
+
return @"Undetermined";
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
NSInteger res = [self.audioSession recordPermission];
|
|
217
|
+
switch (res) {
|
|
218
|
+
case AVAudioSessionRecordPermissionUndetermined:
|
|
219
|
+
return @"Undetermined";
|
|
220
|
+
case AVAudioSessionRecordPermissionGranted:
|
|
221
|
+
return @"Granted";
|
|
222
|
+
case AVAudioSessionRecordPermissionDenied:
|
|
223
|
+
return @"Denied";
|
|
224
|
+
default:
|
|
225
|
+
return @"Undetermined";
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
195
230
|
@end
|
|
@@ -31,6 +31,12 @@ const AudioManagerModule = exports.AudioManagerModule = {
|
|
|
31
31
|
},
|
|
32
32
|
observeVolumeChanges(enabled) {
|
|
33
33
|
NativeAudioManagerModule.observeVolumeChanges(enabled);
|
|
34
|
+
},
|
|
35
|
+
requestRecordingPermissions() {
|
|
36
|
+
return NativeAudioManagerModule.requestRecordingPermissions();
|
|
37
|
+
},
|
|
38
|
+
checkRecordingPermissions() {
|
|
39
|
+
return NativeAudioManagerModule.checkRecordingPermissions();
|
|
34
40
|
}
|
|
35
41
|
};
|
|
36
42
|
//# sourceMappingURL=NativeAudioManagerModule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","NativeAudioManagerModule","NativeModules","AudioManagerModule","eventEmitter","exports","Platform","OS","NativeEventEmitter","Error","setLockScreenInfo","info","resetLockScreenInfo","enableRemoteCommand","name","enabled","setAudioSessionOptions","category","mode","options","getDevicePreferredSampleRate","observeAudioInterruptions","observeVolumeChanges"],"sourceRoot":"../../../src","sources":["specs/NativeAudioManagerModule.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;
|
|
1
|
+
{"version":3,"names":["_reactNative","require","NativeAudioManagerModule","NativeModules","AudioManagerModule","eventEmitter","exports","Platform","OS","NativeEventEmitter","Error","setLockScreenInfo","info","resetLockScreenInfo","enableRemoteCommand","name","enabled","setAudioSessionOptions","category","mode","options","getDevicePreferredSampleRate","observeAudioInterruptions","observeVolumeChanges","requestRecordingPermissions","checkRecordingPermissions"],"sourceRoot":"../../../src","sources":["specs/NativeAudioManagerModule.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAGA,MAAMC,wBAAwB,GAAGC,0BAAa,CAACC,kBAAkB;AACjE,MAAMC,YAAY,GAAAC,OAAA,CAAAD,YAAA,GAChBE,qBAAQ,CAACC,EAAE,KAAK,SAAS,GACrB,IAAIC,+BAAkB,CAAC,CAAC,GACxB,IAAIA,+BAAkB,CAACN,0BAAa,CAACC,kBAAkB,CAAC;AAE9D,IAAI,CAACF,wBAAwB,IAAI,CAACG,YAAY,EAAE;EAC9C,MAAM,IAAIK,KAAK,CACb,iFACF,CAAC;AACH;AAEA,MAAMN,kBAAkB,GAAAE,OAAA,CAAAF,kBAAA,GAAG;EACzBO,iBAAiBA,CAACC,IAEjB,EAAQ;IACPV,wBAAwB,CAACS,iBAAiB,CAACC,IAAI,CAAC;EAClD,CAAC;EACDC,mBAAmBA,CAAA,EAAS;IAC1BX,wBAAwB,CAACW,mBAAmB,CAAC,CAAC;EAChD,CAAC;EACDC,mBAAmBA,CAACC,IAAY,EAAEC,OAAgB,EAAQ;IACxDd,wBAAwB,CAACY,mBAAmB,CAACC,IAAI,EAAEC,OAAO,CAAC;EAC7D,CAAC;EACDC,sBAAsBA,CACpBC,QAAgB,EAChBC,IAAY,EACZC,OAAsB,EAChB;IACNlB,wBAAwB,CAACe,sBAAsB,CAACC,QAAQ,EAAEC,IAAI,EAAEC,OAAO,CAAC;EAC1E,CAAC;EACDC,4BAA4BA,CAAA,EAAW;IACrC,OAAOnB,wBAAwB,CAACmB,4BAA4B,CAAC,CAAC;EAChE,CAAC;EACDC,yBAAyBA,CAACN,OAAgB,EAAQ;IAChDd,wBAAwB,CAACoB,yBAAyB,CAACN,OAAO,CAAC;EAC7D,CAAC;EACDO,oBAAoBA,CAACP,OAAgB,EAAQ;IAC3Cd,wBAAwB,CAACqB,oBAAoB,CAACP,OAAO,CAAC;EACxD,CAAC;EACDQ,2BAA2BA,CAAA,EAA8B;IACvD,OAAOtB,wBAAwB,CAACsB,2BAA2B,CAAC,CAAC;EAC/D,CAAC;EAEDC,yBAAyBA,CAAA,EAA8B;IACrD,OAAOvB,wBAAwB,CAACuB,yBAAyB,CAAC,CAAC;EAC7D;AACF,CAAC","ignoreList":[]}
|
|
@@ -47,6 +47,12 @@ class AudioManager {
|
|
|
47
47
|
}
|
|
48
48
|
return subscription;
|
|
49
49
|
}
|
|
50
|
+
async requestRecordingPermissions() {
|
|
51
|
+
return _specs.AudioManagerModule.requestRecordingPermissions();
|
|
52
|
+
}
|
|
53
|
+
async checkRecordingPermissions() {
|
|
54
|
+
return _specs.AudioManagerModule.checkRecordingPermissions();
|
|
55
|
+
}
|
|
50
56
|
}
|
|
51
57
|
var _default = exports.default = new AudioManager();
|
|
52
58
|
//# sourceMappingURL=AudioManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_specs","require","AudioManager","setLockScreenInfo","info","AudioManagerModule","resetLockScreenInfo","setAudioSessionOptions","options","iosCategory","iosMode","iosOptions","getDevicePreferredSampleRate","observeAudioInterruptions","enabled","observeVolumeChanges","enableRemoteCommand","name","enableRemoteEvent","callback","subscription","eventEmitter","addListener","console","error","_default","exports","default"],"sourceRoot":"../../../src","sources":["system/AudioManager.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"names":["_specs","require","AudioManager","setLockScreenInfo","info","AudioManagerModule","resetLockScreenInfo","setAudioSessionOptions","options","iosCategory","iosMode","iosOptions","getDevicePreferredSampleRate","observeAudioInterruptions","enabled","observeVolumeChanges","enableRemoteCommand","name","enableRemoteEvent","callback","subscription","eventEmitter","addListener","console","error","requestRecordingPermissions","checkRecordingPermissions","_default","exports","default"],"sourceRoot":"../../../src","sources":["system/AudioManager.ts"],"mappings":";;;;;;AAQA,IAAAA,MAAA,GAAAC,OAAA;AAGA,MAAMC,YAAY,CAAC;EACjBC,iBAAiBA,CAACC,IAAoB,EAAE;IACtCC,yBAAkB,CAACF,iBAAiB,CAACC,IAAI,CAAC;EAC5C;EAEAE,mBAAmBA,CAAA,EAAG;IACpBD,yBAAkB,CAACC,mBAAmB,CAAC,CAAC;EAC1C;EAEAC,sBAAsBA,CAACC,OAAuB,EAAE;IAC9CH,yBAAkB,CAACE,sBAAsB,CACvCC,OAAO,CAACC,WAAW,IAAI,EAAE,EACzBD,OAAO,CAACE,OAAO,IAAI,EAAE,EACrBF,OAAO,CAACG,UAAU,IAAI,EACxB,CAAC;EACH;EAEAC,4BAA4BA,CAAA,EAAW;IACrC,OAAOP,yBAAkB,CAACO,4BAA4B,CAAC,CAAC;EAC1D;EAEAC,yBAAyBA,CAACC,OAAgB,EAAE;IAC1CT,yBAAkB,CAACQ,yBAAyB,CAACC,OAAO,CAAC;EACvD;EAEAC,oBAAoBA,CAACD,OAAgB,EAAE;IACrCT,yBAAkB,CAACU,oBAAoB,CAACD,OAAO,CAAC;EAClD;EAEAE,mBAAmBA,CAAiCC,IAAU,EAAQ;IACpEZ,yBAAkB,CAACW,mBAAmB,CAACC,IAAI,EAAE,IAAI,CAAC;EACpD;EAEAC,iBAAiBA,CACfD,IAAU,EACVE,QAAoC,EACR;IAC5B,IAAIC,YAAY,GAAG,IAAI;IACvB,IAAI,CAACD,QAAQ,EAAE;MACb,OAAO,IAAI;IACb;IACA,QAAQF,IAAI;MACV,KAAK,cAAc;QACjBG,YAAY,GAAGC,mBAAY,CAACC,WAAW,CAAC,gBAAgB,EAAEH,QAAQ,CAAC;QACnE;MAEF,KAAK,aAAa;QAChBC,YAAY,GAAGC,mBAAY,CAACC,WAAW,CAAC,eAAe,EAAEH,QAAQ,CAAC;QAClE;MAEF,KAAK,cAAc;QACjBC,YAAY,GAAGC,mBAAY,CAACC,WAAW,CAAC,gBAAgB,EAAEH,QAAQ,CAAC;QACnE;MAEF;QACEI,OAAO,CAACC,KAAK,CAAC,mCAAmC,EAAEP,IAAI,CAAC;IAC5D;IACA,OAAOG,YAAY;EACrB;EAEA,MAAMK,2BAA2BA,CAAA,EAA8B;IAC7D,OAAOpB,yBAAkB,CAACoB,2BAA2B,CAAC,CAAC;EACzD;EAEA,MAAMC,yBAAyBA,CAAA,EAA8B;IAC3D,OAAOrB,yBAAkB,CAACqB,yBAAyB,CAAC,CAAC;EACvD;AACF;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAEc,IAAI3B,YAAY,CAAC,CAAC","ignoreList":[]}
|
|
@@ -27,6 +27,12 @@ const AudioManagerModule = {
|
|
|
27
27
|
},
|
|
28
28
|
observeVolumeChanges(enabled) {
|
|
29
29
|
NativeAudioManagerModule.observeVolumeChanges(enabled);
|
|
30
|
+
},
|
|
31
|
+
requestRecordingPermissions() {
|
|
32
|
+
return NativeAudioManagerModule.requestRecordingPermissions();
|
|
33
|
+
},
|
|
34
|
+
checkRecordingPermissions() {
|
|
35
|
+
return NativeAudioManagerModule.checkRecordingPermissions();
|
|
30
36
|
}
|
|
31
37
|
};
|
|
32
38
|
export { eventEmitter, AudioManagerModule };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","NativeEventEmitter","Platform","NativeAudioManagerModule","AudioManagerModule","eventEmitter","OS","Error","setLockScreenInfo","info","resetLockScreenInfo","enableRemoteCommand","name","enabled","setAudioSessionOptions","category","mode","options","getDevicePreferredSampleRate","observeAudioInterruptions","observeVolumeChanges"],"sourceRoot":"../../../src","sources":["specs/NativeAudioManagerModule.ts"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,kBAAkB,EAAEC,QAAQ,QAAQ,cAAc;
|
|
1
|
+
{"version":3,"names":["NativeModules","NativeEventEmitter","Platform","NativeAudioManagerModule","AudioManagerModule","eventEmitter","OS","Error","setLockScreenInfo","info","resetLockScreenInfo","enableRemoteCommand","name","enabled","setAudioSessionOptions","category","mode","options","getDevicePreferredSampleRate","observeAudioInterruptions","observeVolumeChanges","requestRecordingPermissions","checkRecordingPermissions"],"sourceRoot":"../../../src","sources":["specs/NativeAudioManagerModule.ts"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,kBAAkB,EAAEC,QAAQ,QAAQ,cAAc;AAG1E,MAAMC,wBAAwB,GAAGH,aAAa,CAACI,kBAAkB;AACjE,MAAMC,YAAY,GAChBH,QAAQ,CAACI,EAAE,KAAK,SAAS,GACrB,IAAIL,kBAAkB,CAAC,CAAC,GACxB,IAAIA,kBAAkB,CAACD,aAAa,CAACI,kBAAkB,CAAC;AAE9D,IAAI,CAACD,wBAAwB,IAAI,CAACE,YAAY,EAAE;EAC9C,MAAM,IAAIE,KAAK,CACb,iFACF,CAAC;AACH;AAEA,MAAMH,kBAAkB,GAAG;EACzBI,iBAAiBA,CAACC,IAEjB,EAAQ;IACPN,wBAAwB,CAACK,iBAAiB,CAACC,IAAI,CAAC;EAClD,CAAC;EACDC,mBAAmBA,CAAA,EAAS;IAC1BP,wBAAwB,CAACO,mBAAmB,CAAC,CAAC;EAChD,CAAC;EACDC,mBAAmBA,CAACC,IAAY,EAAEC,OAAgB,EAAQ;IACxDV,wBAAwB,CAACQ,mBAAmB,CAACC,IAAI,EAAEC,OAAO,CAAC;EAC7D,CAAC;EACDC,sBAAsBA,CACpBC,QAAgB,EAChBC,IAAY,EACZC,OAAsB,EAChB;IACNd,wBAAwB,CAACW,sBAAsB,CAACC,QAAQ,EAAEC,IAAI,EAAEC,OAAO,CAAC;EAC1E,CAAC;EACDC,4BAA4BA,CAAA,EAAW;IACrC,OAAOf,wBAAwB,CAACe,4BAA4B,CAAC,CAAC;EAChE,CAAC;EACDC,yBAAyBA,CAACN,OAAgB,EAAQ;IAChDV,wBAAwB,CAACgB,yBAAyB,CAACN,OAAO,CAAC;EAC7D,CAAC;EACDO,oBAAoBA,CAACP,OAAgB,EAAQ;IAC3CV,wBAAwB,CAACiB,oBAAoB,CAACP,OAAO,CAAC;EACxD,CAAC;EACDQ,2BAA2BA,CAAA,EAA8B;IACvD,OAAOlB,wBAAwB,CAACkB,2BAA2B,CAAC,CAAC;EAC/D,CAAC;EAEDC,yBAAyBA,CAAA,EAA8B;IACrD,OAAOnB,wBAAwB,CAACmB,yBAAyB,CAAC,CAAC;EAC7D;AACF,CAAC;AAED,SAASjB,YAAY,EAAED,kBAAkB","ignoreList":[]}
|
|
@@ -43,6 +43,12 @@ class AudioManager {
|
|
|
43
43
|
}
|
|
44
44
|
return subscription;
|
|
45
45
|
}
|
|
46
|
+
async requestRecordingPermissions() {
|
|
47
|
+
return AudioManagerModule.requestRecordingPermissions();
|
|
48
|
+
}
|
|
49
|
+
async checkRecordingPermissions() {
|
|
50
|
+
return AudioManagerModule.checkRecordingPermissions();
|
|
51
|
+
}
|
|
46
52
|
}
|
|
47
53
|
export default new AudioManager();
|
|
48
54
|
//# sourceMappingURL=AudioManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["AudioManagerModule","eventEmitter","AudioManager","setLockScreenInfo","info","resetLockScreenInfo","setAudioSessionOptions","options","iosCategory","iosMode","iosOptions","getDevicePreferredSampleRate","observeAudioInterruptions","enabled","observeVolumeChanges","enableRemoteCommand","name","enableRemoteEvent","callback","subscription","addListener","console","error"],"sourceRoot":"../../../src","sources":["system/AudioManager.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"names":["AudioManagerModule","eventEmitter","AudioManager","setLockScreenInfo","info","resetLockScreenInfo","setAudioSessionOptions","options","iosCategory","iosMode","iosOptions","getDevicePreferredSampleRate","observeAudioInterruptions","enabled","observeVolumeChanges","enableRemoteCommand","name","enableRemoteEvent","callback","subscription","addListener","console","error","requestRecordingPermissions","checkRecordingPermissions"],"sourceRoot":"../../../src","sources":["system/AudioManager.ts"],"mappings":";;AAQA,SAASA,kBAAkB,EAAEC,YAAY,QAAQ,mBAAU;AAG3D,MAAMC,YAAY,CAAC;EACjBC,iBAAiBA,CAACC,IAAoB,EAAE;IACtCJ,kBAAkB,CAACG,iBAAiB,CAACC,IAAI,CAAC;EAC5C;EAEAC,mBAAmBA,CAAA,EAAG;IACpBL,kBAAkB,CAACK,mBAAmB,CAAC,CAAC;EAC1C;EAEAC,sBAAsBA,CAACC,OAAuB,EAAE;IAC9CP,kBAAkB,CAACM,sBAAsB,CACvCC,OAAO,CAACC,WAAW,IAAI,EAAE,EACzBD,OAAO,CAACE,OAAO,IAAI,EAAE,EACrBF,OAAO,CAACG,UAAU,IAAI,EACxB,CAAC;EACH;EAEAC,4BAA4BA,CAAA,EAAW;IACrC,OAAOX,kBAAkB,CAACW,4BAA4B,CAAC,CAAC;EAC1D;EAEAC,yBAAyBA,CAACC,OAAgB,EAAE;IAC1Cb,kBAAkB,CAACY,yBAAyB,CAACC,OAAO,CAAC;EACvD;EAEAC,oBAAoBA,CAACD,OAAgB,EAAE;IACrCb,kBAAkB,CAACc,oBAAoB,CAACD,OAAO,CAAC;EAClD;EAEAE,mBAAmBA,CAAiCC,IAAU,EAAQ;IACpEhB,kBAAkB,CAACe,mBAAmB,CAACC,IAAI,EAAE,IAAI,CAAC;EACpD;EAEAC,iBAAiBA,CACfD,IAAU,EACVE,QAAoC,EACR;IAC5B,IAAIC,YAAY,GAAG,IAAI;IACvB,IAAI,CAACD,QAAQ,EAAE;MACb,OAAO,IAAI;IACb;IACA,QAAQF,IAAI;MACV,KAAK,cAAc;QACjBG,YAAY,GAAGlB,YAAY,CAACmB,WAAW,CAAC,gBAAgB,EAAEF,QAAQ,CAAC;QACnE;MAEF,KAAK,aAAa;QAChBC,YAAY,GAAGlB,YAAY,CAACmB,WAAW,CAAC,eAAe,EAAEF,QAAQ,CAAC;QAClE;MAEF,KAAK,cAAc;QACjBC,YAAY,GAAGlB,YAAY,CAACmB,WAAW,CAAC,gBAAgB,EAAEF,QAAQ,CAAC;QACnE;MAEF;QACEG,OAAO,CAACC,KAAK,CAAC,mCAAmC,EAAEN,IAAI,CAAC;IAC5D;IACA,OAAOG,YAAY;EACrB;EAEA,MAAMI,2BAA2BA,CAAA,EAA8B;IAC7D,OAAOvB,kBAAkB,CAACuB,2BAA2B,CAAC,CAAC;EACzD;EAEA,MAAMC,yBAAyBA,CAAA,EAA8B;IAC3D,OAAOxB,kBAAkB,CAACwB,yBAAyB,CAAC,CAAC;EACvD;AACF;AAEA,eAAe,IAAItB,YAAY,CAAC,CAAC","ignoreList":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NativeEventEmitter } from 'react-native';
|
|
2
|
+
import { PermissionStatus } from '../system/types';
|
|
2
3
|
declare const eventEmitter: NativeEventEmitter;
|
|
3
4
|
declare const AudioManagerModule: {
|
|
4
5
|
setLockScreenInfo(info: {
|
|
@@ -10,6 +11,8 @@ declare const AudioManagerModule: {
|
|
|
10
11
|
getDevicePreferredSampleRate(): number;
|
|
11
12
|
observeAudioInterruptions(enabled: boolean): void;
|
|
12
13
|
observeVolumeChanges(enabled: boolean): void;
|
|
14
|
+
requestRecordingPermissions(): Promise<PermissionStatus>;
|
|
15
|
+
checkRecordingPermissions(): Promise<PermissionStatus>;
|
|
13
16
|
};
|
|
14
17
|
export { eventEmitter, AudioManagerModule };
|
|
15
18
|
//# sourceMappingURL=NativeAudioManagerModule.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeAudioManagerModule.d.ts","sourceRoot":"","sources":["../../../src/specs/NativeAudioManagerModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,kBAAkB,EAAY,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeAudioManagerModule.d.ts","sourceRoot":"","sources":["../../../src/specs/NativeAudioManagerModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,kBAAkB,EAAY,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,QAAA,MAAM,YAAY,oBAG4C,CAAC;AAQ/D,QAAA,MAAM,kBAAkB;;;QAGlB,IAAI;2BAGe,IAAI;8BAGD,MAAM,WAAW,OAAO,GAAG,IAAI;qCAI7C,MAAM,QACV,MAAM,WACH,MAAM,MAAM,CAAC,GACrB,IAAI;oCAGyB,MAAM;uCAGH,OAAO,GAAG,IAAI;kCAGnB,OAAO,GAAG,IAAI;mCAGb,QAAQ,gBAAgB,CAAC;iCAI3B,QAAQ,gBAAgB,CAAC;CAGvD,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SessionOptions, LockScreenInfo, RemoteEventName, RemoteEventCallback, RemoteCommandName } from './types';
|
|
1
|
+
import { SessionOptions, LockScreenInfo, RemoteEventName, RemoteEventCallback, RemoteCommandName, PermissionStatus } from './types';
|
|
2
2
|
import { EmitterSubscription } from 'react-native';
|
|
3
3
|
declare class AudioManager {
|
|
4
4
|
setLockScreenInfo(info: LockScreenInfo): void;
|
|
@@ -9,6 +9,8 @@ declare class AudioManager {
|
|
|
9
9
|
observeVolumeChanges(enabled: boolean): void;
|
|
10
10
|
enableRemoteCommand<Name extends RemoteCommandName>(name: Name): void;
|
|
11
11
|
enableRemoteEvent<Name extends RemoteEventName>(name: Name, callback?: RemoteEventCallback<Name>): EmitterSubscription | null;
|
|
12
|
+
requestRecordingPermissions(): Promise<PermissionStatus>;
|
|
13
|
+
checkRecordingPermissions(): Promise<PermissionStatus>;
|
|
12
14
|
}
|
|
13
15
|
declare const _default: AudioManager;
|
|
14
16
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioManager.d.ts","sourceRoot":"","sources":["../../../src/system/AudioManager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"AudioManager.d.ts","sourceRoot":"","sources":["../../../src/system/AudioManager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,cAAM,YAAY;IAChB,iBAAiB,CAAC,IAAI,EAAE,cAAc;IAItC,mBAAmB;IAInB,sBAAsB,CAAC,OAAO,EAAE,cAAc;IAQ9C,4BAA4B,IAAI,MAAM;IAItC,yBAAyB,CAAC,OAAO,EAAE,OAAO;IAI1C,oBAAoB,CAAC,OAAO,EAAE,OAAO;IAIrC,mBAAmB,CAAC,IAAI,SAAS,iBAAiB,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAIrE,iBAAiB,CAAC,IAAI,SAAS,eAAe,EAC5C,IAAI,EAAE,IAAI,EACV,QAAQ,CAAC,EAAE,mBAAmB,CAAC,IAAI,CAAC,GACnC,mBAAmB,GAAG,IAAI;IAwBvB,2BAA2B,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAIxD,yBAAyB,IAAI,OAAO,CAAC,gBAAgB,CAAC;CAG7D;;AAED,wBAAkC"}
|
|
@@ -55,5 +55,6 @@ interface RemoteEvents {
|
|
|
55
55
|
export type RemoteCommandName = keyof RemoteCommands;
|
|
56
56
|
export type RemoteEventName = keyof RemoteEvents;
|
|
57
57
|
export type RemoteEventCallback<Name extends RemoteEventName> = (event: RemoteEvents[Name]) => void;
|
|
58
|
+
export type PermissionStatus = 'Undetermined' | 'Denied' | 'Granted';
|
|
58
59
|
export {};
|
|
59
60
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/system/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,SAAS,GACT,UAAU,GACV,YAAY,GACZ,aAAa,GACb,eAAe,CAAC;AAEpB,MAAM,MAAM,OAAO,GACf,SAAS,GACT,UAAU,GACV,WAAW,GACX,WAAW,GACX,aAAa,GACb,aAAa,GACb,aAAa,GACb,eAAe,GACf,gBAAgB,CAAC;AAErB,MAAM,MAAM,SAAS,GACjB,YAAY,GACZ,cAAc,GACd,eAAe,GACf,gBAAgB,GAChB,kBAAkB,GAClB,oBAAoB,GACpB,qCAAqC,GACrC,sCAAsC,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,cAAc,CAAC;AAE1D,UAAU,kBAAkB;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CACtD;AAED,MAAM,WAAW,cAAe,SAAQ,kBAAkB;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,eAAe;CAAG;AAE5B,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,uBAAuB;IAC/B,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,sBAAsB;IAC9B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,eAAe,CAAC;IACtB,eAAe,EAAE,eAAe,CAAC;IACjC,kBAAkB,EAAE,eAAe,CAAC;IACpC,SAAS,EAAE,eAAe,CAAC;IAC3B,aAAa,EAAE,eAAe,CAAC;IAC/B,WAAW,EAAE,eAAe,CAAC;IAC7B,YAAY,EAAE,eAAe,CAAC;IAC9B,WAAW,EAAE,eAAe,CAAC;IAC7B,YAAY,EAAE,eAAe,CAAC;IAC9B,sBAAsB,EAAE,eAAe,CAAC;CACzC;AAED,UAAU,YAAY;IACpB,YAAY,EAAE,sBAAsB,CAAC;IACrC,YAAY,EAAE,uBAAuB,CAAC;IACtC,WAAW,EAAE,sBAAsB,CAAC;CACrC;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,cAAc,CAAC;AACrD,MAAM,MAAM,eAAe,GAAG,MAAM,YAAY,CAAC;AACjD,MAAM,MAAM,mBAAmB,CAAC,IAAI,SAAS,eAAe,IAAI,CAC9D,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,KACtB,IAAI,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/system/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,SAAS,GACT,UAAU,GACV,YAAY,GACZ,aAAa,GACb,eAAe,CAAC;AAEpB,MAAM,MAAM,OAAO,GACf,SAAS,GACT,UAAU,GACV,WAAW,GACX,WAAW,GACX,aAAa,GACb,aAAa,GACb,aAAa,GACb,eAAe,GACf,gBAAgB,CAAC;AAErB,MAAM,MAAM,SAAS,GACjB,YAAY,GACZ,cAAc,GACd,eAAe,GACf,gBAAgB,GAChB,kBAAkB,GAClB,oBAAoB,GACpB,qCAAqC,GACrC,sCAAsC,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,cAAc,CAAC;AAE1D,UAAU,kBAAkB;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CACtD;AAED,MAAM,WAAW,cAAe,SAAQ,kBAAkB;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,eAAe;CAAG;AAE5B,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,uBAAuB;IAC/B,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,sBAAsB;IAC9B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,eAAe,CAAC;IACtB,eAAe,EAAE,eAAe,CAAC;IACjC,kBAAkB,EAAE,eAAe,CAAC;IACpC,SAAS,EAAE,eAAe,CAAC;IAC3B,aAAa,EAAE,eAAe,CAAC;IAC/B,WAAW,EAAE,eAAe,CAAC;IAC7B,YAAY,EAAE,eAAe,CAAC;IAC9B,WAAW,EAAE,eAAe,CAAC;IAC7B,YAAY,EAAE,eAAe,CAAC;IAC9B,sBAAsB,EAAE,eAAe,CAAC;CACzC;AAED,UAAU,YAAY;IACpB,YAAY,EAAE,sBAAsB,CAAC;IACrC,YAAY,EAAE,uBAAuB,CAAC;IACtC,WAAW,EAAE,sBAAsB,CAAC;CACrC;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,cAAc,CAAC;AACrD,MAAM,MAAM,eAAe,GAAG,MAAM,YAAY,CAAC;AACjD,MAAM,MAAM,mBAAmB,CAAC,IAAI,SAAS,eAAe,IAAI,CAC9D,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,KACtB,IAAI,CAAC;AAEV,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-audio-api",
|
|
3
|
-
"version": "0.6.0-rc.
|
|
3
|
+
"version": "0.6.0-rc.5",
|
|
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"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
|
|
2
|
+
import { PermissionStatus } from '../system/types';
|
|
2
3
|
|
|
3
4
|
const NativeAudioManagerModule = NativeModules.AudioManagerModule;
|
|
4
5
|
const eventEmitter =
|
|
@@ -40,6 +41,13 @@ const AudioManagerModule = {
|
|
|
40
41
|
observeVolumeChanges(enabled: boolean): void {
|
|
41
42
|
NativeAudioManagerModule.observeVolumeChanges(enabled);
|
|
42
43
|
},
|
|
44
|
+
requestRecordingPermissions(): Promise<PermissionStatus> {
|
|
45
|
+
return NativeAudioManagerModule.requestRecordingPermissions();
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
checkRecordingPermissions(): Promise<PermissionStatus> {
|
|
49
|
+
return NativeAudioManagerModule.checkRecordingPermissions();
|
|
50
|
+
},
|
|
43
51
|
};
|
|
44
52
|
|
|
45
53
|
export { eventEmitter, AudioManagerModule };
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
RemoteEventName,
|
|
5
5
|
RemoteEventCallback,
|
|
6
6
|
RemoteCommandName,
|
|
7
|
+
PermissionStatus,
|
|
7
8
|
} from './types';
|
|
8
9
|
import { AudioManagerModule, eventEmitter } from '../specs';
|
|
9
10
|
import { EmitterSubscription } from 'react-native';
|
|
@@ -67,6 +68,14 @@ class AudioManager {
|
|
|
67
68
|
}
|
|
68
69
|
return subscription;
|
|
69
70
|
}
|
|
71
|
+
|
|
72
|
+
async requestRecordingPermissions(): Promise<PermissionStatus> {
|
|
73
|
+
return AudioManagerModule.requestRecordingPermissions();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async checkRecordingPermissions(): Promise<PermissionStatus> {
|
|
77
|
+
return AudioManagerModule.checkRecordingPermissions();
|
|
78
|
+
}
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
export default new AudioManager();
|
package/src/system/types.ts
CHANGED