react-native-audio-api 0.11.0-alpha.0 → 0.11.0-alpha.1
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/AndroidAudioRecorder.cpp +77 -29
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +17 -4
- package/android/src/main/cpp/audioapi/android/core/utils/AndroidFileWriterBackend.h +6 -2
- package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +187 -0
- package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h +57 -0
- package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.cpp +22 -24
- package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.h +3 -2
- package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.cpp +40 -8
- package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.h +3 -2
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +24 -7
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.h +3 -0
- package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +16 -115
- package/common/cpp/audioapi/core/inputs/AudioRecorder.h +35 -32
- package/ios/audioapi/ios/core/IOSAudioFileOptions.h +1 -0
- package/ios/audioapi/ios/core/IOSAudioFileOptions.mm +5 -0
- package/ios/audioapi/ios/core/IOSAudioFileWriter.h +16 -3
- package/ios/audioapi/ios/core/IOSAudioFileWriter.mm +86 -50
- package/ios/audioapi/ios/core/IOSAudioRecorder.h +11 -2
- package/ios/audioapi/ios/core/IOSAudioRecorder.mm +76 -31
- package/ios/audioapi/ios/core/IOSRecorderCallback.h +57 -0
- package/ios/audioapi/ios/core/IOSRecorderCallback.mm +189 -0
- package/ios/audioapi/ios/core/NativeAudioRecorder.h +2 -3
- package/ios/audioapi/ios/core/NativeAudioRecorder.m +26 -0
- package/ios/audioapi/ios/core/utils/AudioDecoder.mm +1 -0
- package/lib/commonjs/core/AudioRecorder.js +14 -1
- package/lib/commonjs/core/AudioRecorder.js.map +1 -1
- package/lib/module/core/AudioRecorder.js +14 -1
- package/lib/module/core/AudioRecorder.js.map +1 -1
- package/lib/typescript/core/AudioRecorder.d.ts +6 -3
- package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +5 -3
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +5 -0
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/AudioRecorder.ts +27 -10
- package/src/interfaces.ts +6 -2
- package/src/types.ts +6 -0
package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.cpp
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
#include <audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.h>
|
|
5
5
|
#include <audioapi/libs/miniaudio/miniaudio.h>
|
|
6
6
|
|
|
7
|
+
constexpr double BYTES_TO_MB = 1024.0 * 1024.0;
|
|
8
|
+
|
|
7
9
|
namespace audioapi {
|
|
8
10
|
|
|
9
11
|
MiniAudioFileWriter::MiniAudioFileWriter(
|
|
@@ -41,7 +43,7 @@ MiniAudioFileWriter::~MiniAudioFileWriter() {
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
std::string MiniAudioFileWriter::openFile(
|
|
45
47
|
int32_t streamSampleRate,
|
|
46
48
|
int32_t streamChannelCount,
|
|
47
49
|
int32_t streamMaxBufferSize) {
|
|
@@ -58,21 +60,23 @@ void MiniAudioFileWriter::openFile(
|
|
|
58
60
|
success = initializeConverterIfNeeded();
|
|
59
61
|
|
|
60
62
|
if (!success) {
|
|
61
|
-
return;
|
|
63
|
+
return "";
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
success = initializeEncoder();
|
|
65
67
|
|
|
66
68
|
if (!success) {
|
|
67
|
-
return;
|
|
69
|
+
return "";
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
isFileOpen_.store(true);
|
|
73
|
+
|
|
74
|
+
return filePath_;
|
|
71
75
|
}
|
|
72
76
|
|
|
73
|
-
std::
|
|
77
|
+
std::tuple<double, double> MiniAudioFileWriter::closeFile() {
|
|
74
78
|
if (!isFileOpen()) {
|
|
75
|
-
return
|
|
79
|
+
return {0.0, 0.0};
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
isFileOpen_.store(false);
|
|
@@ -93,10 +97,36 @@ std::string MiniAudioFileWriter::closeFile() {
|
|
|
93
97
|
processingBufferLength_ = 0;
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
// Retrieve duration and file size
|
|
101
|
+
std::string filePath = filePath_;
|
|
102
|
+
double durationInSeconds = 0.0;
|
|
103
|
+
double fileSizeInMB = 0.0;
|
|
104
|
+
|
|
105
|
+
ma_decoder decoder;
|
|
106
|
+
|
|
107
|
+
if (ma_decoder_init_file(filePath_.c_str(), NULL, &decoder) == MA_SUCCESS) {
|
|
108
|
+
ma_uint64 frameCount = 0;
|
|
98
109
|
|
|
99
|
-
|
|
110
|
+
if (ma_decoder_get_length_in_pcm_frames(&decoder, &frameCount) ==
|
|
111
|
+
MA_SUCCESS) {
|
|
112
|
+
durationInSeconds =
|
|
113
|
+
static_cast<double>(frameCount) / decoder.outputSampleRate;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
ma_decoder_uninit(&decoder);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
FILE *file = fopen(filePath_.c_str(), "rb");
|
|
120
|
+
|
|
121
|
+
if (file != nullptr) {
|
|
122
|
+
fseek(file, 0, SEEK_END);
|
|
123
|
+
long fileSizeInBytes = ftell(file);
|
|
124
|
+
fclose(file);
|
|
125
|
+
fileSizeInMB = static_cast<double>(fileSizeInBytes) / BYTES_TO_MB;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
filePath_ = "";
|
|
129
|
+
return {fileSizeInMB, durationInSeconds};
|
|
100
130
|
}
|
|
101
131
|
|
|
102
132
|
bool MiniAudioFileWriter::writeAudioData(void *data, int numFrames) {
|
|
@@ -126,6 +156,7 @@ bool MiniAudioFileWriter::writeAudioData(void *data, int numFrames) {
|
|
|
126
156
|
filePath_.c_str());
|
|
127
157
|
}
|
|
128
158
|
|
|
159
|
+
framesWritten_.fetch_add(numFrames);
|
|
129
160
|
return result == MA_SUCCESS;
|
|
130
161
|
}
|
|
131
162
|
|
|
@@ -142,6 +173,7 @@ bool MiniAudioFileWriter::writeAudioData(void *data, int numFrames) {
|
|
|
142
173
|
filePath_.c_str());
|
|
143
174
|
}
|
|
144
175
|
|
|
176
|
+
framesWritten_.fetch_add(numFrames);
|
|
145
177
|
return result == MA_SUCCESS;
|
|
146
178
|
}
|
|
147
179
|
|
package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.h
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
#include <string>
|
|
7
7
|
#include <memory>
|
|
8
|
+
#include <tuple>
|
|
8
9
|
|
|
9
10
|
namespace audioapi {
|
|
10
11
|
|
|
@@ -19,8 +20,8 @@ class MiniAudioFileWriter : public AndroidFileWriterBackend {
|
|
|
19
20
|
size_t androidFlags);
|
|
20
21
|
~MiniAudioFileWriter() override;
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
std::
|
|
23
|
+
std::string openFile(int32_t streamSampleRate, int32_t streamChannelCount, int32_t streamMaxBufferSize) override;
|
|
24
|
+
std::tuple<double, double> closeFile() override;
|
|
24
25
|
|
|
25
26
|
bool writeAudioData(void *data, int numFrames) override;
|
|
26
27
|
|
|
@@ -35,25 +35,36 @@ AudioRecorderHostObject::AudioRecorderHostObject(
|
|
|
35
35
|
JSI_EXPORT_FUNCTION(AudioRecorderHostObject, connect),
|
|
36
36
|
JSI_EXPORT_FUNCTION(AudioRecorderHostObject, disconnect),
|
|
37
37
|
JSI_EXPORT_FUNCTION(AudioRecorderHostObject, setOnAudioReady),
|
|
38
|
-
JSI_EXPORT_FUNCTION(AudioRecorderHostObject, clearOnAudioReady)
|
|
38
|
+
JSI_EXPORT_FUNCTION(AudioRecorderHostObject, clearOnAudioReady),
|
|
39
|
+
JSI_EXPORT_FUNCTION(AudioRecorderHostObject, getCurrentDuration));
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, start) {
|
|
42
|
-
audioRecorder_->start();
|
|
43
|
+
std::string filePath = audioRecorder_->start();
|
|
43
44
|
|
|
44
|
-
return jsi::Value::
|
|
45
|
+
return jsi::Value(runtime, jsi::String::createFromUtf8(runtime, filePath));
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, stop) {
|
|
48
|
-
|
|
49
|
+
auto [path, size, duration] = audioRecorder_->stop();
|
|
50
|
+
auto result = jsi::Object(runtime);
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
result.setProperty(
|
|
53
|
+
runtime, "path", jsi::String::createFromUtf8(runtime, path));
|
|
54
|
+
result.setProperty(runtime, "size", size);
|
|
55
|
+
result.setProperty(runtime, "duration", duration);
|
|
56
|
+
|
|
57
|
+
return result;
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, isRecording) {
|
|
54
61
|
return jsi::Value(audioRecorder_->isRecording());
|
|
55
62
|
}
|
|
56
63
|
|
|
64
|
+
JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, isPaused) {
|
|
65
|
+
return jsi::Value(audioRecorder_->isPaused());
|
|
66
|
+
}
|
|
67
|
+
|
|
57
68
|
JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, enableFileOutput) {
|
|
58
69
|
auto options = args[0].getObject(runtime);
|
|
59
70
|
|
|
@@ -115,8 +126,9 @@ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, setOnAudioReady) {
|
|
|
115
126
|
options.getProperty(runtime, "bufferLength").getNumber());
|
|
116
127
|
auto channelCount = static_cast<size_t>(
|
|
117
128
|
options.getProperty(runtime, "channelCount").getNumber());
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
uint64_t callbackId = std::stoull(options.getProperty(runtime, "callbackId")
|
|
130
|
+
.getString(runtime)
|
|
131
|
+
.utf8(runtime));
|
|
120
132
|
|
|
121
133
|
audioRecorder_->setOnAudioReadyCallback(
|
|
122
134
|
sampleRate, bufferLength, channelCount, callbackId);
|
|
@@ -128,4 +140,9 @@ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, clearOnAudioReady) {
|
|
|
128
140
|
return jsi::Value::undefined();
|
|
129
141
|
}
|
|
130
142
|
|
|
143
|
+
JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, getCurrentDuration) {
|
|
144
|
+
double duration = audioRecorder_->getCurrentDuration();
|
|
145
|
+
return jsi::Value(duration);
|
|
146
|
+
}
|
|
147
|
+
|
|
131
148
|
} // namespace audioapi
|
|
@@ -22,6 +22,7 @@ class AudioRecorderHostObject : public JsiHostObject {
|
|
|
22
22
|
JSI_HOST_FUNCTION_DECL(start);
|
|
23
23
|
JSI_HOST_FUNCTION_DECL(stop);
|
|
24
24
|
JSI_HOST_FUNCTION_DECL(isRecording);
|
|
25
|
+
JSI_HOST_FUNCTION_DECL(isPaused);
|
|
25
26
|
|
|
26
27
|
JSI_HOST_FUNCTION_DECL(enableFileOutput);
|
|
27
28
|
JSI_HOST_FUNCTION_DECL(disableFileOutput);
|
|
@@ -35,6 +36,8 @@ class AudioRecorderHostObject : public JsiHostObject {
|
|
|
35
36
|
JSI_HOST_FUNCTION_DECL(setOnAudioReady);
|
|
36
37
|
JSI_HOST_FUNCTION_DECL(clearOnAudioReady);
|
|
37
38
|
|
|
39
|
+
JSI_HOST_FUNCTION_DECL(getCurrentDuration);
|
|
40
|
+
|
|
38
41
|
private:
|
|
39
42
|
std::shared_ptr<AudioRecorder> audioRecorder_;
|
|
40
43
|
};
|
|
@@ -1,112 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
AudioRecorder::AudioRecorder(
|
|
12
|
-
const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry)
|
|
13
|
-
: audioEventHandlerRegistry_(audioEventHandlerRegistry) {
|
|
14
|
-
isRunning_.store(false);
|
|
15
|
-
fileOutputEnabled_.store(false);
|
|
16
|
-
callbackOutputEnabled_.store(false);
|
|
17
|
-
isConnected_.store(false);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
bool AudioRecorder::isRecording() {
|
|
21
|
-
return isRunning_.load();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
void AudioRecorder::connect(const std::shared_ptr<RecorderAdapterNode> &node) {
|
|
25
|
-
// node->init();
|
|
26
|
-
// adapterNodeLock_.lock();
|
|
27
|
-
// adapterNode_ = node;
|
|
28
|
-
// adapterNodeLock_.unlock();
|
|
29
|
-
// isConnected_.store(true);
|
|
30
|
-
// node->init(ringBufferSize_);
|
|
31
|
-
// adapterNodeLock_.lock();
|
|
32
|
-
// adapterNode_ = node;
|
|
33
|
-
// adapterNodeLock_.unlock();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
void AudioRecorder::disconnect() {
|
|
37
|
-
// adapterNodeLock_.lock();
|
|
38
|
-
// adapterNode_ = nullptr;
|
|
39
|
-
// adapterNodeLock_.unlock();
|
|
40
|
-
// isConnected_.store(false);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
void AudioRecorder::setOnAudioReadyCallback(
|
|
44
|
-
float sampleRate,
|
|
45
|
-
size_t bufferLength,
|
|
46
|
-
size_t channelCount,
|
|
47
|
-
uint64_t callbackId) {
|
|
48
|
-
callbackProperties_.sampleRate = sampleRate;
|
|
49
|
-
callbackProperties_.bufferLength = bufferLength;
|
|
50
|
-
callbackProperties_.channelCount = channelCount;
|
|
51
|
-
callbackProperties_.callbackId = callbackId;
|
|
52
|
-
|
|
53
|
-
callbackOutputEnabled_.store(true);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
void AudioRecorder::clearOnAudioReadyCallback() {
|
|
57
|
-
callbackOutputEnabled_.store(false);
|
|
58
|
-
callbackProperties_ = CallbackProperties{};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
void AudioRecorder::invokeOnAudioReadyCallback(
|
|
62
|
-
const std::shared_ptr<AudioBus> &bus,
|
|
63
|
-
int numFrames) {
|
|
64
|
-
// if (!hasCallback()) {
|
|
65
|
-
// return;
|
|
66
|
-
// }
|
|
67
|
-
|
|
68
|
-
// auto audioBuffer = std::make_shared<AudioBuffer>(bus);
|
|
69
|
-
// auto audioBufferHostObject =
|
|
70
|
-
// std::make_shared<AudioBufferHostObject>(audioBuffer);
|
|
71
|
-
|
|
72
|
-
// std::unordered_map<std::string, EventValue> body = {};
|
|
73
|
-
// body.insert({"buffer", audioBufferHostObject});
|
|
74
|
-
// body.insert({"numFrames", numFrames});
|
|
75
|
-
|
|
76
|
-
// if (audioEventHandlerRegistry_ != nullptr) {
|
|
77
|
-
// audioEventHandlerRegistry_->invokeHandlerWithEventBody(
|
|
78
|
-
// "audioReady", onAudioReadyCallbackId_, body);
|
|
79
|
-
// }
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
void AudioRecorder::sendRemainingCallbackData() {
|
|
83
|
-
// if (!hasCallback()) {
|
|
84
|
-
// return;
|
|
85
|
-
// }
|
|
86
|
-
|
|
87
|
-
// auto bus = std::make_shared<AudioBus>(
|
|
88
|
-
// circularBuffer_->getNumberOfAvailableFrames(), 1, sampleRate_);
|
|
89
|
-
// auto *outputChannel = bus->getChannel(0)->getData();
|
|
90
|
-
// auto availableFrames =
|
|
91
|
-
// static_cast<int>(circularBuffer_->getNumberOfAvailableFrames());
|
|
92
|
-
|
|
93
|
-
// circularBuffer_->pop_front(
|
|
94
|
-
// outputChannel, circularBuffer_->getNumberOfAvailableFrames());
|
|
95
|
-
|
|
96
|
-
// invokeOnAudioReadyCallback(bus, availableFrames);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
bool AudioRecorder::usesCallback() const {
|
|
100
|
-
return callbackOutputEnabled_.load();
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
bool AudioRecorder::usesFileOutput() const {
|
|
104
|
-
return fileOutputEnabled_.load();
|
|
105
|
-
}
|
|
1
|
+
// void AudioRecorder::connect(const std::shared_ptr<RecorderAdapterNode> &node)
|
|
2
|
+
// { node->init(); adapterNodeLock_.lock(); adapterNode_ = node;
|
|
3
|
+
// adapterNodeLock_.unlock();
|
|
4
|
+
// isConnected_.store(true);
|
|
5
|
+
// node->init(ringBufferSize_);
|
|
6
|
+
// adapterNodeLock_.lock();
|
|
7
|
+
// adapterNode_ = node;
|
|
8
|
+
// adapterNodeLock_.unlock();
|
|
9
|
+
// }
|
|
106
10
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
11
|
+
// void AudioRecorder::disconnect() {
|
|
12
|
+
// adapterNodeLock_.lock();
|
|
13
|
+
// adapterNode_ = nullptr;
|
|
14
|
+
// adapterNodeLock_.unlock();
|
|
15
|
+
// isConnected_.store(false);
|
|
16
|
+
// }
|
|
110
17
|
|
|
111
18
|
// AudioRecorder::AudioRecorder(
|
|
112
19
|
// const std::shared_ptr<AudioEventHandlerRegistry>
|
|
@@ -116,7 +23,7 @@ bool AudioRecorder::isConnected() const {
|
|
|
116
23
|
// ringBufferSize_ = std::max(2 * bufferLength, minRingBufferSize);
|
|
117
24
|
|
|
118
25
|
// circularBuffer_ = std::make_shared<CircularAudioArray>(ringBufferSize_);
|
|
119
|
-
//
|
|
26
|
+
// state_.store(RecorderState::Idle);
|
|
120
27
|
// }
|
|
121
28
|
|
|
122
29
|
// void AudioRecorder::writeToBuffers(const float *data, int numFrames) {
|
|
@@ -126,10 +33,4 @@ bool AudioRecorder::isConnected() const {
|
|
|
126
33
|
// }
|
|
127
34
|
// adapterNodeLock_.unlock();
|
|
128
35
|
// }
|
|
129
|
-
|
|
130
|
-
// if (hasCallback()) {
|
|
131
|
-
// circularBuffer_->push_back(data, numFrames);
|
|
132
|
-
// }
|
|
133
36
|
// }
|
|
134
|
-
|
|
135
|
-
} // namespace audioapi
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <atomic>
|
|
5
5
|
#include <mutex>
|
|
6
6
|
#include <string>
|
|
7
|
+
#include <tuple>
|
|
7
8
|
|
|
8
9
|
namespace audioapi {
|
|
9
10
|
|
|
@@ -14,13 +15,13 @@ class AudioEventHandlerRegistry;
|
|
|
14
15
|
|
|
15
16
|
class AudioRecorder {
|
|
16
17
|
public:
|
|
17
|
-
|
|
18
|
+
enum RecorderState { Idle, Recording, Paused };
|
|
19
|
+
explicit AudioRecorder(const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry):
|
|
20
|
+
audioEventHandlerRegistry_(audioEventHandlerRegistry) {}
|
|
18
21
|
virtual ~AudioRecorder() = default;
|
|
19
22
|
|
|
20
|
-
virtual
|
|
21
|
-
virtual std::string stop() = 0;
|
|
22
|
-
|
|
23
|
-
bool isRecording();
|
|
23
|
+
virtual std::string start() = 0;
|
|
24
|
+
virtual std::tuple<std::string, double, double> stop() = 0;
|
|
24
25
|
|
|
25
26
|
virtual void enableFileOutput(
|
|
26
27
|
float sampleRate,
|
|
@@ -33,49 +34,51 @@ class AudioRecorder {
|
|
|
33
34
|
virtual void pause() = 0;
|
|
34
35
|
virtual void resume() = 0;
|
|
35
36
|
|
|
36
|
-
void connect(const std::shared_ptr<RecorderAdapterNode> &node)
|
|
37
|
-
void disconnect()
|
|
37
|
+
void connect(const std::shared_ptr<RecorderAdapterNode> &node) {}
|
|
38
|
+
void disconnect() {}
|
|
38
39
|
|
|
39
|
-
void setOnAudioReadyCallback(
|
|
40
|
+
virtual void setOnAudioReadyCallback(
|
|
40
41
|
float sampleRate,
|
|
41
42
|
size_t bufferLength,
|
|
42
43
|
size_t channelCount,
|
|
43
|
-
uint64_t callbackId);
|
|
44
|
-
void clearOnAudioReadyCallback();
|
|
44
|
+
uint64_t callbackId) = 0;
|
|
45
|
+
virtual void clearOnAudioReadyCallback() = 0;
|
|
46
|
+
|
|
47
|
+
virtual double getCurrentDuration() const = 0;
|
|
48
|
+
|
|
49
|
+
bool usesCallback() const {
|
|
50
|
+
return callbackOutputEnabled_.load();
|
|
51
|
+
}
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
void sendRemainingCallbackData();
|
|
53
|
+
bool usesFileOutput() const {
|
|
54
|
+
return fileOutputEnabled_.load();
|
|
55
|
+
}
|
|
50
56
|
|
|
51
|
-
bool
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
bool isConnected() const {
|
|
58
|
+
return isConnected_.load();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
bool isRecording() const {
|
|
62
|
+
return state_.load() == RecorderState::Recording;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
bool isPaused() const {
|
|
66
|
+
return state_.load() == RecorderState::Paused;
|
|
67
|
+
}
|
|
54
68
|
|
|
55
69
|
protected:
|
|
56
|
-
struct CallbackProperties {
|
|
57
|
-
float sampleRate;
|
|
58
|
-
size_t bufferLength;
|
|
59
|
-
size_t channelCount;
|
|
60
|
-
uint64_t callbackId;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
CallbackProperties callbackProperties_;
|
|
64
70
|
// size_t ringBufferSize_;
|
|
65
71
|
|
|
66
|
-
std::atomic<
|
|
67
|
-
std::atomic<bool> fileOutputEnabled_;
|
|
68
|
-
std::atomic<bool> callbackOutputEnabled_;
|
|
69
|
-
std::atomic<bool> isConnected_;
|
|
72
|
+
std::atomic<RecorderState> state_{ RecorderState::Idle };
|
|
73
|
+
std::atomic<bool> fileOutputEnabled_{false};
|
|
74
|
+
std::atomic<bool> callbackOutputEnabled_{false};
|
|
75
|
+
std::atomic<bool> isConnected_{false};
|
|
70
76
|
// std::shared_ptr<CircularAudioArray> circularBuffer_;
|
|
71
77
|
|
|
72
78
|
mutable std::mutex adapterNodeLock_;
|
|
73
79
|
std::shared_ptr<RecorderAdapterNode> adapterNode_ = nullptr;
|
|
74
80
|
|
|
75
81
|
std::shared_ptr<AudioEventHandlerRegistry> audioEventHandlerRegistry_;
|
|
76
|
-
uint64_t onAudioReadyCallbackId_ = 0;
|
|
77
|
-
|
|
78
|
-
// void writeToBuffers(const float *data, int numFrames);
|
|
79
82
|
};
|
|
80
83
|
|
|
81
84
|
} // namespace audioapi
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
#include <memory>
|
|
4
4
|
#include <string>
|
|
5
|
+
#include <tuple>
|
|
5
6
|
|
|
6
7
|
#ifndef __OBJC__ // when compiled as C++
|
|
7
|
-
typedef struct objc_object AVAudioFile;
|
|
8
8
|
typedef struct objc_object NSURL;
|
|
9
|
+
typedef struct objc_object NSString;
|
|
10
|
+
typedef struct objc_object AVAudioFile;
|
|
11
|
+
typedef struct objc_object AVAudioFormat;
|
|
9
12
|
typedef struct objc_object AudioBufferList;
|
|
13
|
+
typedef struct objc_object AVAudioConverter;
|
|
10
14
|
#endif // __OBJC__
|
|
11
15
|
|
|
12
16
|
namespace audioapi {
|
|
@@ -18,12 +22,18 @@ class IOSAudioFileWriter {
|
|
|
18
22
|
IOSAudioFileWriter(float sampleRate, size_t channelCount, size_t bitRate, size_t iosFlags);
|
|
19
23
|
~IOSAudioFileWriter();
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
std::
|
|
25
|
+
std::string openFile(AVAudioFormat *bufferFormat, size_t maxInputBufferLength);
|
|
26
|
+
std::tuple<double, double> closeFile();
|
|
23
27
|
|
|
24
28
|
bool writeAudioData(const AudioBufferList *audioBufferList, int numFrames);
|
|
25
29
|
|
|
30
|
+
double getCurrentDuration() const;
|
|
31
|
+
|
|
26
32
|
private:
|
|
33
|
+
size_t converterInputBufferSize_;
|
|
34
|
+
size_t converterOutputBufferSize_;
|
|
35
|
+
std::atomic<size_t> framesWritten_{0};
|
|
36
|
+
|
|
27
37
|
NSString *getISODateStringForDirectory();
|
|
28
38
|
NSString *getTimestampForFilename();
|
|
29
39
|
NSURL *getFileURL();
|
|
@@ -33,6 +43,9 @@ class IOSAudioFileWriter {
|
|
|
33
43
|
AVAudioFormat *bufferFormat_;
|
|
34
44
|
AVAudioConverter *converter_;
|
|
35
45
|
NSURL *fileURL_;
|
|
46
|
+
|
|
47
|
+
AVAudioPCMBuffer *converterInputBuffer_;
|
|
48
|
+
AVAudioPCMBuffer *converterOutputBuffer_;
|
|
36
49
|
};
|
|
37
50
|
|
|
38
51
|
} // namespace audioapi
|