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.
Files changed (38) hide show
  1. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +77 -29
  2. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +17 -4
  3. package/android/src/main/cpp/audioapi/android/core/utils/AndroidFileWriterBackend.h +6 -2
  4. package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +187 -0
  5. package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h +57 -0
  6. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.cpp +22 -24
  7. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.h +3 -2
  8. package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.cpp +40 -8
  9. package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.h +3 -2
  10. package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +24 -7
  11. package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.h +3 -0
  12. package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +16 -115
  13. package/common/cpp/audioapi/core/inputs/AudioRecorder.h +35 -32
  14. package/ios/audioapi/ios/core/IOSAudioFileOptions.h +1 -0
  15. package/ios/audioapi/ios/core/IOSAudioFileOptions.mm +5 -0
  16. package/ios/audioapi/ios/core/IOSAudioFileWriter.h +16 -3
  17. package/ios/audioapi/ios/core/IOSAudioFileWriter.mm +86 -50
  18. package/ios/audioapi/ios/core/IOSAudioRecorder.h +11 -2
  19. package/ios/audioapi/ios/core/IOSAudioRecorder.mm +76 -31
  20. package/ios/audioapi/ios/core/IOSRecorderCallback.h +57 -0
  21. package/ios/audioapi/ios/core/IOSRecorderCallback.mm +189 -0
  22. package/ios/audioapi/ios/core/NativeAudioRecorder.h +2 -3
  23. package/ios/audioapi/ios/core/NativeAudioRecorder.m +26 -0
  24. package/ios/audioapi/ios/core/utils/AudioDecoder.mm +1 -0
  25. package/lib/commonjs/core/AudioRecorder.js +14 -1
  26. package/lib/commonjs/core/AudioRecorder.js.map +1 -1
  27. package/lib/module/core/AudioRecorder.js +14 -1
  28. package/lib/module/core/AudioRecorder.js.map +1 -1
  29. package/lib/typescript/core/AudioRecorder.d.ts +6 -3
  30. package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
  31. package/lib/typescript/interfaces.d.ts +5 -3
  32. package/lib/typescript/interfaces.d.ts.map +1 -1
  33. package/lib/typescript/types.d.ts +5 -0
  34. package/lib/typescript/types.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/core/AudioRecorder.ts +27 -10
  37. package/src/interfaces.ts +6 -2
  38. package/src/types.ts +6 -0
@@ -1,6 +1,7 @@
1
1
  #include <android/log.h>
2
2
  #include <audioapi/android/core/AndroidAudioRecorder.h>
3
3
  #include <audioapi/android/core/utils/AndroidFileWriterBackend.h>
4
+ #include <audioapi/android/core/utils/AndroidRecorderCallback.h>
4
5
  #include <audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.h>
5
6
  #include <audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.h>
6
7
  #include <audioapi/core/sources/RecorderAdapterNode.h>
@@ -30,7 +31,6 @@ AndroidAudioRecorder::AndroidAudioRecorder(
30
31
  streamSampleRate_ = mStream_->getSampleRate();
31
32
  streamChannelCount_ = mStream_->getChannelCount();
32
33
  streamMaxBufferSizeInFrames_ = mStream_->getBufferSizeInFrames();
33
-
34
34
  nativeAudioRecorder_ = jni::make_global(NativeAudioRecorder::create());
35
35
  }
36
36
 
@@ -44,9 +44,9 @@ AndroidAudioRecorder::~AndroidAudioRecorder() {
44
44
  }
45
45
  }
46
46
 
47
- void AndroidAudioRecorder::start() {
47
+ std::string AndroidAudioRecorder::start() {
48
48
  if (isRecording()) {
49
- return;
49
+ return filePath_;
50
50
  }
51
51
 
52
52
  if (!mStream_ || !nativeAudioRecorder_) {
@@ -54,16 +54,18 @@ void AndroidAudioRecorder::start() {
54
54
  ANDROID_LOG_ERROR,
55
55
  "AndroidAudioRecorder",
56
56
  "Audio stream is not initialized.\n");
57
- return;
57
+ return filePath_;
58
58
  }
59
59
 
60
60
  if (usesFileOutput()) {
61
- fileWriter_->openFile(
61
+ filePath_ = fileWriter_->openFile(
62
62
  streamSampleRate_, streamChannelCount_, streamMaxBufferSizeInFrames_);
63
63
  }
64
64
 
65
65
  if (usesCallback()) {
66
66
  // TODO: create circular buffer and converter?
67
+ callback_->prepare(
68
+ streamSampleRate_, streamChannelCount_, streamMaxBufferSizeInFrames_);
67
69
  }
68
70
 
69
71
  if (isConnected()) {
@@ -72,12 +74,18 @@ void AndroidAudioRecorder::start() {
72
74
 
73
75
  nativeAudioRecorder_->start();
74
76
  mStream_->requestStart();
75
- isRunning_.store(true);
77
+ state_.store(RecorderState::Recording);
78
+
79
+ return filePath_;
76
80
  }
77
81
 
78
- std::string AndroidAudioRecorder::stop() {
82
+ std::tuple<std::string, double, double> AndroidAudioRecorder::stop() {
83
+ std::string filePath = filePath_;
84
+ double outputFileSize = 0.0;
85
+ double outputDuration = 0.0;
86
+
79
87
  if (!isRecording()) {
80
- return "";
88
+ return {filePath_, 0.0, 0.0};
81
89
  }
82
90
 
83
91
  if (!mStream_ || !nativeAudioRecorder_) {
@@ -85,20 +93,25 @@ std::string AndroidAudioRecorder::stop() {
85
93
  ANDROID_LOG_ERROR,
86
94
  "AndroidAudioRecorder",
87
95
  "Audio stream is not initialized.\n");
88
- return "";
96
+ return {filePath_, 0.0, 0.0};
89
97
  }
90
98
 
91
99
  nativeAudioRecorder_->stop();
92
100
  mStream_->requestStop();
93
- isRunning_.store(false);
94
-
95
- // TODO: sendRemainingData() ?
101
+ state_.store(RecorderState::Idle);
96
102
 
97
103
  if (usesFileOutput()) {
98
- return fileWriter_->closeFile();
104
+ auto [size, duration] = fileWriter_->closeFile();
105
+ outputFileSize = size;
106
+ outputDuration = duration;
107
+ }
108
+
109
+ if (usesCallback()) {
110
+ callback_->cleanup();
99
111
  }
100
112
 
101
- return "";
113
+ filePath_ = "";
114
+ return {filePath, outputFileSize, outputDuration};
102
115
  }
103
116
 
104
117
  void AndroidAudioRecorder::enableFileOutput(
@@ -125,33 +138,68 @@ void AndroidAudioRecorder::disableFileOutput() {
125
138
  fileWriter_ = nullptr;
126
139
  }
127
140
 
128
- void AndroidAudioRecorder::pause() {}
141
+ void AndroidAudioRecorder::pause() {
142
+ if (!isRecording()) {
143
+ return;
144
+ }
145
+
146
+ mStream_->pause(0);
147
+ state_.store(RecorderState::Paused);
148
+ }
129
149
 
130
- void AndroidAudioRecorder::resume() {}
150
+ void AndroidAudioRecorder::resume() {
151
+ if (!isPaused()) {
152
+ return;
153
+ }
154
+
155
+ mStream_->start(0);
156
+ state_.store(RecorderState::Recording);
157
+ }
158
+
159
+ void AndroidAudioRecorder::setOnAudioReadyCallback(
160
+ float sampleRate,
161
+ size_t bufferLength,
162
+ size_t channelCount,
163
+ uint64_t callbackId) {
164
+ callback_ = std::make_shared<AndroidRecorderCallback>(
165
+ audioEventHandlerRegistry_,
166
+ sampleRate,
167
+ bufferLength,
168
+ channelCount,
169
+ callbackId);
170
+ callbackOutputEnabled_.store(true);
171
+ }
172
+
173
+ void AndroidAudioRecorder::clearOnAudioReadyCallback() {
174
+ callbackOutputEnabled_.store(false);
175
+ callback_ = nullptr;
176
+ }
131
177
 
132
178
  DataCallbackResult AndroidAudioRecorder::onAudioReady(
133
179
  oboe::AudioStream *oboeStream,
134
180
  void *audioData,
135
181
  int32_t numFrames) {
182
+ if (isPaused()) {
183
+ return DataCallbackResult::Continue;
184
+ }
185
+
136
186
  if (usesFileOutput()) {
137
187
  fileWriter_->writeAudioData(audioData, numFrames);
138
188
  }
139
189
 
190
+ if (usesCallback()) {
191
+ callback_->receiveAudioData(audioData, numFrames);
192
+ }
193
+
140
194
  return DataCallbackResult::Continue;
141
195
  }
142
196
 
143
- } // namespace audioapi
144
-
145
- // if (isRunning_.load()) {
146
- // auto *inputChannel = static_cast<float *>(audioData);
147
- // writeToBuffers(inputChannel, numFrames);
148
- // }
149
-
150
- // while (circularBuffer_->getNumberOfAvailableFrames() >= bufferLength_) {
151
- // auto bus = std::make_shared<AudioBus>(bufferLength_, 1, sampleRate_);
152
- // auto *outputChannel = bus->getChannel(0)->getData();
197
+ double AndroidAudioRecorder::getCurrentDuration() const {
198
+ if (usesFileOutput()) {
199
+ return fileWriter_->getCurrentDuration();
200
+ }
153
201
 
154
- // circularBuffer_->pop_front(outputChannel, bufferLength_);
202
+ return 0.0;
203
+ }
155
204
 
156
- // invokeOnAudioReadyCallback(bus, bufferLength_);
157
- // }
205
+ } // namespace audioapi
@@ -6,6 +6,7 @@
6
6
  #include <functional>
7
7
  #include <memory>
8
8
  #include <string>
9
+ #include <tuple>
9
10
 
10
11
  #include <audioapi/android/core/NativeAudioRecorder.hpp>
11
12
 
@@ -15,6 +16,7 @@ using namespace oboe;
15
16
 
16
17
  class AudioBus;
17
18
  class CircularAudioArray;
19
+ class AndroidRecorderCallback;
18
20
  class AndroidFileWriterBackend;
19
21
  class AudioEventHandlerRegistry;
20
22
 
@@ -23,8 +25,8 @@ class AndroidAudioRecorder : public AudioStreamDataCallback, public AudioRecorde
23
25
  explicit AndroidAudioRecorder(const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry);
24
26
  ~AndroidAudioRecorder() override;
25
27
 
26
- void start() override;
27
- std::string stop() override;
28
+ std::string start() override;
29
+ std::tuple<std::string, double, double> stop() override;
28
30
 
29
31
  void enableFileOutput(
30
32
  float sampleRate,
@@ -37,18 +39,29 @@ class AndroidAudioRecorder : public AudioStreamDataCallback, public AudioRecorde
37
39
  void pause() override;
38
40
  void resume() override;
39
41
 
42
+ void setOnAudioReadyCallback(float sampleRate, size_t bufferLength, size_t channelCount, uint64_t callbackId)
43
+ override;
44
+ void clearOnAudioReadyCallback() override;
45
+
46
+ double getCurrentDuration() const override;
47
+
40
48
  DataCallbackResult onAudioReady(
41
49
  AudioStream *oboeStream,
42
50
  void *audioData,
43
51
  int32_t numFrames) override;
44
52
 
45
53
  private:
46
- std::shared_ptr<AndroidFileWriterBackend> fileWriter_;
54
+ std::string filePath_;
47
55
  std::shared_ptr<AudioStream> mStream_;
48
- facebook::jni::global_ref<NativeAudioRecorder> nativeAudioRecorder_;
56
+
57
+ std::shared_ptr<AndroidFileWriterBackend> fileWriter_;
58
+ std::shared_ptr<AndroidRecorderCallback> callback_;
59
+
49
60
  int32_t streamSampleRate_;
50
61
  int32_t streamChannelCount_;
51
62
  int32_t streamMaxBufferSizeInFrames_;
63
+
64
+ facebook::jni::global_ref<NativeAudioRecorder> nativeAudioRecorder_;
52
65
  };
53
66
 
54
67
  } // namespace audioapi
@@ -1,5 +1,6 @@
1
1
  #pragma once
2
2
 
3
+ #include <tuple>
3
4
  #include <string>
4
5
  #include <memory>
5
6
 
@@ -15,15 +16,18 @@ class AndroidFileWriterBackend {
15
16
 
16
17
  virtual ~AndroidFileWriterBackend() = default;
17
18
 
18
- virtual void openFile(int32_t streamSampleRate, int32_t streamChannelCount, int32_t streamMaxBufferSize) = 0;
19
- virtual std::string closeFile() = 0;
19
+ virtual std::string openFile(int32_t streamSampleRate, int32_t streamChannelCount, int32_t streamMaxBufferSize) = 0;
20
+ virtual std::tuple<double, double> closeFile() = 0;
20
21
 
21
22
  virtual bool writeAudioData(void *data, int numFrames) = 0;
22
23
 
23
24
  std::string getFilePath() const { return filePath_; }
24
25
 
26
+ double getCurrentDuration() const { return static_cast<double>(framesWritten_.load()) / streamSampleRate_; }
27
+
25
28
  protected:
26
29
  std::string filePath_{""};
30
+ std::atomic<size_t> framesWritten_{0};
27
31
 
28
32
  int32_t streamSampleRate_{0};
29
33
  int32_t streamChannelCount_{0};
@@ -0,0 +1,187 @@
1
+ #include <android/log.h>
2
+ #include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
3
+ #include <audioapi/android/core/utils/AndroidRecorderCallback.h>
4
+ #include <audioapi/events/AudioEventHandlerRegistry.h>
5
+ #include <audioapi/libs/miniaudio/miniaudio.h>
6
+ #include <audioapi/utils/AudioArray.h>
7
+ #include <audioapi/utils/AudioBus.h>
8
+ #include <audioapi/utils/CircularAudioArray.h>
9
+
10
+ #include <memory>
11
+
12
+ namespace audioapi {
13
+
14
+ AndroidRecorderCallback::AndroidRecorderCallback(
15
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry,
16
+ float sampleRate,
17
+ size_t bufferLength,
18
+ size_t channelCount,
19
+ uint64_t callbackId)
20
+ : sampleRate_(sampleRate),
21
+ bufferLength_(bufferLength),
22
+ channelCount_(channelCount),
23
+ callbackId_(callbackId),
24
+ audioEventHandlerRegistry_(audioEventHandlerRegistry) {
25
+ ringBufferSize_ = std::max((int)bufferLength * 2, 8192);
26
+ circularBus_.resize(channelCount_);
27
+
28
+ for (size_t i = 0; i < channelCount_; ++i) {
29
+ auto busArray = std::make_shared<CircularAudioArray>(ringBufferSize_);
30
+ circularBus_[i] = busArray;
31
+ }
32
+ }
33
+
34
+ AndroidRecorderCallback::~AndroidRecorderCallback() {
35
+ for (size_t i = 0; i < circularBus_.size(); ++i) {
36
+ circularBus_[i].reset();
37
+ }
38
+ }
39
+
40
+ void AndroidRecorderCallback::prepare(
41
+ int32_t streamSampleRate,
42
+ int32_t streamChannelCount,
43
+ size_t maxInputBufferLength) {
44
+ ma_result result;
45
+
46
+ streamSampleRate_ = streamSampleRate;
47
+ streamChannelCount_ = streamChannelCount;
48
+ maxInputBufferLength_ = maxInputBufferLength;
49
+
50
+ ma_data_converter_config converterConfig = ma_data_converter_config_init(
51
+ ma_format_f32,
52
+ ma_format_f32,
53
+ streamChannelCount_,
54
+ channelCount_,
55
+ streamSampleRate_,
56
+ static_cast<int32_t>(sampleRate_));
57
+
58
+ converter_ = std::make_unique<ma_data_converter>();
59
+ result = ma_data_converter_init(&converterConfig, NULL, converter_.get());
60
+
61
+ if (result != MA_SUCCESS) {
62
+ __android_log_print(
63
+ ANDROID_LOG_ERROR,
64
+ "AndroidRecorderCallback",
65
+ "Failed to initialize miniaudio data converter");
66
+ return;
67
+ }
68
+
69
+ ma_data_converter_get_expected_output_frame_count(
70
+ converter_.get(), maxInputBufferLength_, &processingBufferLength_);
71
+
72
+ processingBufferLength_ =
73
+ std::max(processingBufferLength_, (ma_uint64)maxInputBufferLength_);
74
+
75
+ deinterleavingArray_ = std::make_shared<AudioArray>(processingBufferLength_);
76
+ processingBuffer_ = ma_malloc(
77
+ processingBufferLength_ * channelCount_ *
78
+ ma_get_bytes_per_sample(ma_format_f32),
79
+ NULL);
80
+ }
81
+
82
+ void AndroidRecorderCallback::cleanup() {
83
+ if (converter_ != nullptr) {
84
+ ma_data_converter_uninit(converter_.get(), NULL);
85
+ converter_.reset();
86
+ }
87
+
88
+ if (processingBuffer_ != nullptr) {
89
+ ma_free(processingBuffer_, NULL);
90
+ processingBuffer_ = nullptr;
91
+ processingBufferLength_ = 0;
92
+ }
93
+
94
+ for (size_t i = 0; i < circularBus_.size(); ++i) {
95
+ circularBus_[i].reset();
96
+ }
97
+ }
98
+
99
+ void AndroidRecorderCallback::receiveAudioData(void *data, int numFrames) {
100
+ ma_uint64 inputFrameCount = numFrames;
101
+ ma_uint64 outputFrameCount = 0;
102
+
103
+ if ((float)streamSampleRate_ == sampleRate_ ||
104
+ streamChannelCount_ == channelCount_) {
105
+ deinterleaveAndWriteAudioData(data, numFrames);
106
+ emitAudioData();
107
+ return;
108
+ }
109
+
110
+ ma_data_converter_get_expected_output_frame_count(
111
+ converter_.get(), inputFrameCount, &outputFrameCount);
112
+
113
+ ma_data_converter_process_pcm_frames(
114
+ converter_.get(),
115
+ data,
116
+ &inputFrameCount,
117
+ processingBuffer_,
118
+ &outputFrameCount);
119
+
120
+ deinterleaveAndWriteAudioData(
121
+ processingBuffer_, static_cast<int>(outputFrameCount));
122
+ emitAudioData();
123
+ }
124
+
125
+ void AndroidRecorderCallback::deinterleaveAndWriteAudioData(
126
+ void *data,
127
+ int numFrames) {
128
+ auto *inputData = static_cast<float *>(data);
129
+
130
+ for (size_t channel = 0; channel < channelCount_; ++channel) {
131
+ float *channelData = deinterleavingArray_->getData();
132
+
133
+ for (int frame = 0; frame < numFrames; ++frame) {
134
+ channelData[frame] = inputData[frame * streamChannelCount_ + channel];
135
+ }
136
+
137
+ circularBus_[channel]->push_back(channelData, numFrames);
138
+ }
139
+ }
140
+
141
+ void AndroidRecorderCallback::emitAudioData() {
142
+ while (circularBus_[0]->getNumberOfAvailableFrames() >= bufferLength_) {
143
+ auto bus =
144
+ std::make_shared<AudioBus>(bufferLength_, channelCount_, sampleRate_);
145
+
146
+ for (int i = 0; i < channelCount_; ++i) {
147
+ auto *outputChannel = bus->getChannel(i)->getData();
148
+ circularBus_[i]->pop_front(outputChannel, bufferLength_);
149
+ }
150
+
151
+ invokeCallback(bus, (int)bufferLength_);
152
+ }
153
+ }
154
+
155
+ void AndroidRecorderCallback::invokeCallback(
156
+ const std::shared_ptr<AudioBus> &bus,
157
+ int numFrames) {
158
+ auto audioBuffer = std::make_shared<AudioBuffer>(bus);
159
+ auto audioBufferHostObject =
160
+ std::make_shared<AudioBufferHostObject>(audioBuffer);
161
+
162
+ std::unordered_map<std::string, EventValue> eventPayload = {};
163
+ eventPayload.insert({"buffer", audioBufferHostObject});
164
+ eventPayload.insert({"numFrames", numFrames});
165
+
166
+ if (audioEventHandlerRegistry_) {
167
+ audioEventHandlerRegistry_->invokeHandlerWithEventBody(
168
+ "audioReady", callbackId_, eventPayload);
169
+ }
170
+ }
171
+
172
+ void AndroidRecorderCallback::sendRemainingData() {
173
+ auto numberOfFrames = circularBus_[0]->getNumberOfAvailableFrames();
174
+ auto bus = std::make_shared<AudioBus>(
175
+ circularBus_[0]->getNumberOfAvailableFrames(),
176
+ channelCount_,
177
+ sampleRate_);
178
+
179
+ for (int i = 0; i < channelCount_; ++i) {
180
+ auto *outputChannel = bus->getChannel(i)->getData();
181
+ circularBus_[i]->pop_front(outputChannel, numberOfFrames);
182
+ }
183
+
184
+ invokeCallback(bus, (int)numberOfFrames);
185
+ }
186
+
187
+ } // namespace audioapi
@@ -0,0 +1,57 @@
1
+ #pragma once
2
+
3
+
4
+ #include <audioapi/libs/miniaudio/miniaudio.h>
5
+ #include <memory>
6
+ #include <vector>
7
+
8
+ namespace audioapi {
9
+
10
+ class AudioBus;
11
+ class AudioArray;
12
+ class CircularAudioArray;
13
+ class AudioEventHandlerRegistry;
14
+
15
+ class AndroidRecorderCallback {
16
+ public:
17
+ AndroidRecorderCallback(
18
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry,
19
+ float sampleRate,
20
+ size_t bufferLength,
21
+ size_t channelCount,
22
+ uint64_t callbackId);
23
+ ~AndroidRecorderCallback();
24
+
25
+ void prepare(int32_t streamSampleRate, int32_t streamChannelCount, size_t maxInputBufferLength);
26
+ void cleanup();
27
+
28
+ void receiveAudioData(void *data, int numFrames);
29
+ void emitAudioData();
30
+
31
+ void invokeCallback(const std::shared_ptr<AudioBus> &bus, int numFrames);
32
+ void sendRemainingData();
33
+
34
+ private:
35
+ int32_t streamSampleRate_;
36
+ int32_t streamChannelCount_;
37
+ size_t maxInputBufferLength_;
38
+
39
+ float sampleRate_;
40
+ size_t bufferLength_;
41
+ size_t channelCount_;
42
+ uint64_t callbackId_;
43
+ size_t ringBufferSize_;
44
+
45
+ ma_uint64 processingBufferLength_{0};
46
+ void *processingBuffer_{nullptr};
47
+
48
+ std::unique_ptr<ma_data_converter> converter_{nullptr};
49
+
50
+ std::shared_ptr<AudioEventHandlerRegistry> audioEventHandlerRegistry_;
51
+ std::vector<std::shared_ptr<CircularAudioArray>> circularBus_;
52
+ std::shared_ptr<AudioArray> deinterleavingArray_;
53
+
54
+ void deinterleaveAndWriteAudioData(void *data, int numFrames);
55
+ };
56
+
57
+ } // namespace audioapi
@@ -1,13 +1,16 @@
1
1
  #include <android/log.h>
2
2
  #include <cmath>
3
+
3
4
  extern "C" {
4
- #include <libavutil/log.h>
5
+ #include <libavformat/avio.h>
5
6
  }
6
7
 
7
8
  #include <audioapi/android/core/utils/AndroidFileWriterBackend.h>
8
9
  #include <audioapi/android/core/utils/ffmpegBackend/FFmpegAudioFileOptions.h>
9
10
  #include <audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.h>
10
11
 
12
+ constexpr double BYTES_TO_MB = 1024.0 * 1024.0;
13
+
11
14
  namespace audioapi {
12
15
 
13
16
  FFmpegAudioFileWriter::FFmpegAudioFileWriter(
@@ -20,16 +23,6 @@ FFmpegAudioFileWriter::FFmpegAudioFileWriter(
20
23
  channelCount,
21
24
  bitRate,
22
25
  androidFlags) {
23
- av_log_set_level(AV_LOG_DEBUG);
24
-
25
- av_log_set_callback([](void *, int level, const char *fmt, va_list vl) {
26
- if (level > av_log_get_level())
27
- return;
28
- char msg[1024];
29
- vsnprintf(msg, sizeof(msg), fmt, vl);
30
- __android_log_print(ANDROID_LOG_INFO, "FFmpeg", "%s", msg);
31
- });
32
-
33
26
  fileOptions_ = std::make_shared<FFmpegAudioFileOptions>(
34
27
  sampleRate, channelCount, bitRate, androidFlags);
35
28
  }
@@ -39,7 +32,7 @@ FFmpegAudioFileWriter::~FFmpegAudioFileWriter() {
39
32
  fileOptions_.reset();
40
33
  }
41
34
 
42
- void FFmpegAudioFileWriter::openFile(
35
+ std::string FFmpegAudioFileWriter::openFile(
43
36
  int32_t streamSampleRate,
44
37
  int32_t streamChannelCount,
45
38
  int32_t streamMaxBufferSize) {
@@ -48,6 +41,7 @@ void FFmpegAudioFileWriter::openFile(
48
41
  streamSampleRate_ = streamSampleRate;
49
42
  streamChannelCount_ = streamChannelCount;
50
43
  streamMaxBufferSize_ = streamMaxBufferSize;
44
+ framesWritten_.store(0);
51
45
  nextPts_ = 0;
52
46
 
53
47
  const AVCodec *codec = fileOptions_->getCodec();
@@ -64,7 +58,7 @@ void FFmpegAudioFileWriter::openFile(
64
58
  "FFmpegFileWriter",
65
59
  "Failed to allocate FFmpeg format context for file: %s",
66
60
  filePath_.c_str());
67
- return;
61
+ return "";
68
62
  }
69
63
 
70
64
  formatCtx_ = AVFormatContextPtr(rawFormatCtx);
@@ -77,7 +71,7 @@ void FFmpegAudioFileWriter::openFile(
77
71
  ANDROID_LOG_ERROR,
78
72
  "FFmpegFileWriter",
79
73
  "Failed to allocate FFmpeg codec context for file");
80
- return;
74
+ return "";
81
75
  }
82
76
 
83
77
  AVDictionary *codecOptions = nullptr;
@@ -104,7 +98,7 @@ void FFmpegAudioFileWriter::openFile(
104
98
  "FFmpegFileWriter",
105
99
  "Failed to open FFmpeg codec for file");
106
100
  av_dict_free(&codecOptions);
107
- return;
101
+ return "";
108
102
  }
109
103
 
110
104
  av_dict_free(&codecOptions);
@@ -115,7 +109,7 @@ void FFmpegAudioFileWriter::openFile(
115
109
  ANDROID_LOG_ERROR,
116
110
  "FFmpegFileWriter",
117
111
  "Failed to copy codec parameters to stream for file");
118
- return;
112
+ return "";
119
113
  }
120
114
 
121
115
  if (!(formatCtx_->oformat->flags & AVFMT_NOFILE)) {
@@ -125,7 +119,7 @@ void FFmpegAudioFileWriter::openFile(
125
119
  "FFmpegFileWriter",
126
120
  "Failed to open output file: %s",
127
121
  filePath_.c_str());
128
- return;
122
+ return "";
129
123
  }
130
124
  }
131
125
 
@@ -138,7 +132,7 @@ void FFmpegAudioFileWriter::openFile(
138
132
  "FFmpegFileWriter",
139
133
  "Failed to write header to file: %s",
140
134
  filePath_.c_str());
141
- return;
135
+ return "";
142
136
  }
143
137
 
144
138
  frame_ = AVFramePtr(av_frame_alloc());
@@ -171,7 +165,7 @@ void FFmpegAudioFileWriter::openFile(
171
165
  "FFmpegFileWriter",
172
166
  "Failed to initialize resampler for file: %s",
173
167
  filePath_.c_str());
174
- return;
168
+ return "";
175
169
  }
176
170
 
177
171
  int contextFrameRatio = 2;
@@ -198,11 +192,13 @@ void FFmpegAudioFileWriter::openFile(
198
192
  fifoSize);
199
193
 
200
194
  isFileOpen_.store(true);
195
+
196
+ return filePath_;
201
197
  }
202
198
 
203
- std::string FFmpegAudioFileWriter::closeFile() {
199
+ std::tuple<double, double> FFmpegAudioFileWriter::closeFile() {
204
200
  if (!isFileOpen()) {
205
- return "";
201
+ return {0.0, 0.0};
206
202
  }
207
203
 
208
204
  isFileOpen_.store(false);
@@ -273,6 +269,9 @@ std::string FFmpegAudioFileWriter::closeFile() {
273
269
  filePath_.c_str());
274
270
  }
275
271
 
272
+ double fileSizeInMB = avio_size(formatCtx_->pb) / BYTES_TO_MB;
273
+ double durationInSeconds = getCurrentDuration();
274
+
276
275
  if (formatCtx_ && formatCtx_->pb) {
277
276
  avio_closep(&formatCtx_->pb);
278
277
  }
@@ -284,10 +283,8 @@ std::string FFmpegAudioFileWriter::closeFile() {
284
283
  formatCtx_.reset();
285
284
  audioFifo_.reset();
286
285
 
287
- std::string closedFilePath = filePath_;
288
286
  filePath_ = "";
289
-
290
- return closedFilePath;
287
+ return {fileSizeInMB, durationInSeconds};
291
288
  }
292
289
 
293
290
  bool FFmpegAudioFileWriter::writeAudioData(void *data, int numFrames) {
@@ -409,6 +406,7 @@ bool FFmpegAudioFileWriter::writeAudioData(void *data, int numFrames) {
409
406
  av_frame_unref(frame_.get());
410
407
  }
411
408
 
409
+ framesWritten_.fetch_add(numFrames);
412
410
  return true;
413
411
  }
414
412
 
@@ -13,6 +13,7 @@ extern "C" {
13
13
 
14
14
  #include <string>
15
15
  #include <memory>
16
+ #include <tuple>
16
17
 
17
18
  namespace audioapi {
18
19
 
@@ -82,8 +83,8 @@ class FFmpegAudioFileWriter : public AndroidFileWriterBackend {
82
83
  size_t androidFlags);
83
84
  ~FFmpegAudioFileWriter() override;
84
85
 
85
- void openFile(int32_t streamSampleRate, int32_t streamChannelCount, int32_t streamMaxBufferSize) override;
86
- std::string closeFile() override;
86
+ std::string openFile(int32_t streamSampleRate, int32_t streamChannelCount, int32_t streamMaxBufferSize) override;
87
+ std::tuple<double, double> closeFile() override;
87
88
 
88
89
  bool writeAudioData(void *data, int numFrames) override;
89
90