react-native-audio-api 0.11.0-nightly-95f9c99-20251215 → 0.11.0-nightly-dd83923-20251216

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 (138) hide show
  1. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +382 -39
  2. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +45 -18
  3. package/android/src/main/cpp/audioapi/android/core/NativeAudioRecorder.hpp +9 -9
  4. package/android/src/main/cpp/audioapi/android/core/utils/AndroidFileWriterBackend.h +33 -0
  5. package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +170 -0
  6. package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h +46 -0
  7. package/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp +0 -1
  8. package/android/src/main/cpp/audioapi/android/core/utils/FileOptions.cpp +83 -0
  9. package/android/src/main/cpp/audioapi/android/core/utils/FileOptions.h +22 -0
  10. package/android/src/main/cpp/audioapi/android/core/utils/MiniaudioImplementation.cpp +8 -0
  11. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.cpp +493 -0
  12. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.h +70 -0
  13. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/ptrs.hpp +56 -0
  14. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/utils.cpp +114 -0
  15. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/utils.h +34 -0
  16. package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.cpp +296 -0
  17. package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.h +40 -0
  18. package/android/src/main/cpp/audioapi/android/system/NativeFileInfo.hpp +32 -0
  19. package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +2 -0
  20. package/android/src/main/java/com/swmansion/audioapi/system/AudioFocusListener.kt +7 -3
  21. package/android/src/main/java/com/swmansion/audioapi/system/CentralizedForegroundService.kt +1 -0
  22. package/android/src/main/java/com/swmansion/audioapi/system/NativeFileInfo.kt +18 -0
  23. package/android/src/main/java/com/swmansion/audioapi/system/notification/PlaybackNotification.kt +1 -0
  24. package/android/src/main/java/com/swmansion/audioapi/system/notification/RecordingNotificationReceiver.kt +2 -0
  25. package/android/src/oldarch/NativeAudioAPIModuleSpec.java +100 -80
  26. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +3 -11
  27. package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +145 -16
  28. package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.h +21 -6
  29. package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +43 -60
  30. package/common/cpp/audioapi/core/inputs/AudioRecorder.h +53 -33
  31. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +42 -14
  32. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +12 -9
  33. package/common/cpp/audioapi/core/utils/AudioFileWriter.cpp +41 -0
  34. package/common/cpp/audioapi/core/utils/AudioFileWriter.h +44 -0
  35. package/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp +101 -0
  36. package/common/cpp/audioapi/core/utils/AudioRecorderCallback.h +52 -0
  37. package/common/cpp/audioapi/utils/AudioFileProperties.cpp +92 -0
  38. package/common/cpp/audioapi/utils/AudioFileProperties.h +76 -0
  39. package/common/cpp/audioapi/utils/Result.hpp +323 -0
  40. package/common/cpp/audioapi/utils/UnitConversion.h +9 -0
  41. package/ios/audioapi/ios/AudioAPIModule.mm +9 -14
  42. package/ios/audioapi/ios/core/IOSAudioPlayer.h +1 -1
  43. package/ios/audioapi/ios/core/IOSAudioPlayer.mm +7 -6
  44. package/ios/audioapi/ios/core/IOSAudioRecorder.h +39 -13
  45. package/ios/audioapi/ios/core/IOSAudioRecorder.mm +302 -26
  46. package/ios/audioapi/ios/core/NativeAudioPlayer.m +7 -11
  47. package/ios/audioapi/ios/core/NativeAudioRecorder.h +8 -9
  48. package/ios/audioapi/ios/core/NativeAudioRecorder.m +70 -76
  49. package/ios/audioapi/ios/core/utils/AudioDecoder.mm +1 -0
  50. package/ios/audioapi/ios/core/utils/FileOptions.h +33 -0
  51. package/ios/audioapi/ios/core/utils/FileOptions.mm +195 -0
  52. package/ios/audioapi/ios/core/utils/IOSFileWriter.h +53 -0
  53. package/ios/audioapi/ios/core/utils/IOSFileWriter.mm +239 -0
  54. package/ios/audioapi/ios/core/utils/IOSRecorderCallback.h +47 -0
  55. package/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +185 -0
  56. package/ios/audioapi/ios/system/AudioEngine.h +21 -16
  57. package/ios/audioapi/ios/system/AudioEngine.mm +138 -130
  58. package/ios/audioapi/ios/system/AudioSessionManager.h +19 -9
  59. package/ios/audioapi/ios/system/AudioSessionManager.mm +250 -215
  60. package/ios/audioapi/ios/system/NotificationManager.mm +24 -42
  61. package/lib/commonjs/api.js +82 -109
  62. package/lib/commonjs/api.js.map +1 -1
  63. package/lib/commonjs/core/AudioRecorder.js +159 -13
  64. package/lib/commonjs/core/AudioRecorder.js.map +1 -1
  65. package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
  66. package/lib/commonjs/system/notification/PlaybackNotificationManager.js +17 -14
  67. package/lib/commonjs/system/notification/PlaybackNotificationManager.js.map +1 -1
  68. package/lib/commonjs/system/notification/RecordingNotificationManager.js +22 -19
  69. package/lib/commonjs/system/notification/RecordingNotificationManager.js.map +1 -1
  70. package/lib/commonjs/system/notification/SimpleNotificationManager.js +16 -13
  71. package/lib/commonjs/system/notification/SimpleNotificationManager.js.map +1 -1
  72. package/lib/commonjs/types.js +39 -0
  73. package/lib/commonjs/types.js.map +1 -1
  74. package/lib/commonjs/utils/filePresets.js +43 -0
  75. package/lib/commonjs/utils/filePresets.js.map +1 -0
  76. package/lib/commonjs/web-system/notification/PlaybackNotificationManager.js +6 -3
  77. package/lib/commonjs/web-system/notification/PlaybackNotificationManager.js.map +1 -1
  78. package/lib/commonjs/web-system/notification/RecordingNotificationManager.js +6 -3
  79. package/lib/commonjs/web-system/notification/RecordingNotificationManager.js.map +1 -1
  80. package/lib/module/api.js +5 -4
  81. package/lib/module/api.js.map +1 -1
  82. package/lib/module/core/AudioRecorder.js +159 -13
  83. package/lib/module/core/AudioRecorder.js.map +1 -1
  84. package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
  85. package/lib/module/system/notification/PlaybackNotificationManager.js +17 -14
  86. package/lib/module/system/notification/PlaybackNotificationManager.js.map +1 -1
  87. package/lib/module/system/notification/RecordingNotificationManager.js +22 -19
  88. package/lib/module/system/notification/RecordingNotificationManager.js.map +1 -1
  89. package/lib/module/system/notification/SimpleNotificationManager.js +16 -13
  90. package/lib/module/system/notification/SimpleNotificationManager.js.map +1 -1
  91. package/lib/module/types.js +38 -1
  92. package/lib/module/types.js.map +1 -1
  93. package/lib/module/utils/filePresets.js +39 -0
  94. package/lib/module/utils/filePresets.js.map +1 -0
  95. package/lib/module/web-system/notification/PlaybackNotificationManager.js +6 -3
  96. package/lib/module/web-system/notification/PlaybackNotificationManager.js.map +1 -1
  97. package/lib/module/web-system/notification/RecordingNotificationManager.js +6 -3
  98. package/lib/module/web-system/notification/RecordingNotificationManager.js.map +1 -1
  99. package/lib/typescript/api.d.ts +5 -4
  100. package/lib/typescript/api.d.ts.map +1 -1
  101. package/lib/typescript/core/AudioRecorder.d.ts +69 -7
  102. package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
  103. package/lib/typescript/events/types.d.ts +36 -2
  104. package/lib/typescript/events/types.d.ts.map +1 -1
  105. package/lib/typescript/interfaces.d.ts +24 -4
  106. package/lib/typescript/interfaces.d.ts.map +1 -1
  107. package/lib/typescript/specs/NativeAudioAPIModule.d.ts +1 -1
  108. package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
  109. package/lib/typescript/system/notification/PlaybackNotificationManager.d.ts +4 -3
  110. package/lib/typescript/system/notification/PlaybackNotificationManager.d.ts.map +1 -1
  111. package/lib/typescript/system/notification/RecordingNotificationManager.d.ts +4 -3
  112. package/lib/typescript/system/notification/RecordingNotificationManager.d.ts.map +1 -1
  113. package/lib/typescript/system/notification/SimpleNotificationManager.d.ts +3 -2
  114. package/lib/typescript/system/notification/SimpleNotificationManager.d.ts.map +1 -1
  115. package/lib/typescript/system/notification/types.d.ts.map +1 -1
  116. package/lib/typescript/types.d.ts +79 -3
  117. package/lib/typescript/types.d.ts.map +1 -1
  118. package/lib/typescript/utils/filePresets.d.ts +9 -0
  119. package/lib/typescript/utils/filePresets.d.ts.map +1 -0
  120. package/lib/typescript/web-system/notification/PlaybackNotificationManager.d.ts +4 -3
  121. package/lib/typescript/web-system/notification/PlaybackNotificationManager.d.ts.map +1 -1
  122. package/lib/typescript/web-system/notification/RecordingNotificationManager.d.ts +4 -3
  123. package/lib/typescript/web-system/notification/RecordingNotificationManager.d.ts.map +1 -1
  124. package/package.json +4 -4
  125. package/src/AudioAPIModule/globals.d.ts +1 -2
  126. package/src/api.ts +8 -29
  127. package/src/core/AudioRecorder.ts +195 -23
  128. package/src/events/types.ts +40 -2
  129. package/src/interfaces.ts +34 -5
  130. package/src/specs/NativeAudioAPIModule.ts +2 -2
  131. package/src/system/notification/PlaybackNotificationManager.ts +20 -16
  132. package/src/system/notification/RecordingNotificationManager.ts +26 -21
  133. package/src/system/notification/SimpleNotificationManager.ts +18 -13
  134. package/src/system/notification/types.ts +1 -0
  135. package/src/types.ts +89 -3
  136. package/src/utils/filePresets.ts +47 -0
  137. package/src/web-system/notification/PlaybackNotificationManager.ts +9 -5
  138. package/src/web-system/notification/RecordingNotificationManager.ts +9 -5
@@ -10,83 +10,103 @@
10
10
  * @nolint
11
11
  */
12
12
 
13
- package com.swmansion.audioapi;
14
-
15
- import com.facebook.proguard.annotations.DoNotStrip;
16
- import com.facebook.react.bridge.Promise;
17
- import com.facebook.react.bridge.ReactApplicationContext;
18
- import com.facebook.react.bridge.ReactContextBaseJavaModule;
19
- import com.facebook.react.bridge.ReactMethod;
20
- import com.facebook.react.bridge.ReadableArray;
21
- import com.facebook.react.bridge.ReadableMap;
22
- import com.facebook.react.turbomodule.core.interfaces.TurboModule;
23
- import javax.annotation.Nonnull;
24
-
25
- public abstract class NativeAudioAPIModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
26
- public static final String NAME = "AudioAPIModule";
27
-
28
- public NativeAudioAPIModuleSpec(ReactApplicationContext reactContext) {
29
- super(reactContext);
30
- }
31
-
32
- @Override
33
- public @Nonnull String getName() {
34
- return NAME;
35
- }
36
-
37
- @ReactMethod(isBlockingSynchronousMethod = true)
38
- @DoNotStrip
39
- public abstract boolean install();
40
-
41
- @ReactMethod(isBlockingSynchronousMethod = true)
42
- @DoNotStrip
43
- public abstract double getDevicePreferredSampleRate();
44
-
45
- @ReactMethod
46
- @DoNotStrip
47
- public abstract void setAudioSessionActivity(boolean enabled, Promise promise);
48
-
49
- @ReactMethod
50
- @DoNotStrip
51
- public abstract void setAudioSessionOptions(String category, String mode, ReadableArray options, boolean allowHaptics);
52
-
53
- @ReactMethod
54
- @DoNotStrip
55
- public abstract void disableSessionManagement();
56
-
57
- @ReactMethod
58
- @DoNotStrip
59
- public abstract void setLockScreenInfo(ReadableMap info);
60
-
61
- @ReactMethod
62
- @DoNotStrip
63
- public abstract void resetLockScreenInfo();
64
-
65
- @ReactMethod
66
- @DoNotStrip
67
- public abstract void enableRemoteCommand(String name, boolean enabled);
68
-
69
- @ReactMethod
70
- @DoNotStrip
71
- public abstract void observeAudioInterruptions(boolean enabled);
72
-
73
- @ReactMethod
74
- @DoNotStrip
75
- public abstract void activelyReclaimSession(boolean enabled);
76
-
77
- @ReactMethod
78
- @DoNotStrip
79
- public abstract void observeVolumeChanges(boolean enabled);
80
-
81
- @ReactMethod
82
- @DoNotStrip
83
- public abstract void requestRecordingPermissions(Promise promise);
84
-
85
- @ReactMethod
86
- @DoNotStrip
87
- public abstract void checkRecordingPermissions(Promise promise);
88
-
89
- @ReactMethod
90
- @DoNotStrip
91
- public abstract void getDevicesInfo(Promise promise);
92
- }
13
+ package com.swmansion.audioapi;
14
+
15
+ import com.facebook.proguard.annotations.DoNotStrip;
16
+ import com.facebook.react.bridge.Promise;
17
+ import com.facebook.react.bridge.ReactApplicationContext;
18
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
19
+ import com.facebook.react.bridge.ReactMethod;
20
+ import com.facebook.react.bridge.ReadableArray;
21
+ import com.facebook.react.bridge.ReadableMap;
22
+ import com.facebook.react.turbomodule.core.interfaces.TurboModule;
23
+ import javax.annotation.Nonnull;
24
+
25
+ public abstract class NativeAudioAPIModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
26
+ public static final String NAME = "AudioAPIModule";
27
+
28
+ public NativeAudioAPIModuleSpec(ReactApplicationContext reactContext) {
29
+ super(reactContext);
30
+ }
31
+
32
+ @Override
33
+ public @Nonnull String getName() {
34
+ return NAME;
35
+ }
36
+
37
+ @ReactMethod(isBlockingSynchronousMethod = true)
38
+ @DoNotStrip
39
+ public abstract boolean install();
40
+
41
+ @ReactMethod(isBlockingSynchronousMethod = true)
42
+ @DoNotStrip
43
+ public abstract double getDevicePreferredSampleRate();
44
+
45
+ @ReactMethod
46
+ @DoNotStrip
47
+ public abstract void setAudioSessionActivity(boolean enabled, Promise promise);
48
+
49
+ @ReactMethod
50
+ @DoNotStrip
51
+ public abstract void setAudioSessionOptions(String category, String mode, ReadableArray options, boolean allowHaptics);
52
+
53
+ @ReactMethod
54
+ @DoNotStrip
55
+ public abstract void disableSessionManagement();
56
+
57
+ @ReactMethod
58
+ @DoNotStrip
59
+ public abstract void observeAudioInterruptions(boolean enabled);
60
+
61
+ @ReactMethod
62
+ @DoNotStrip
63
+ public abstract void activelyReclaimSession(boolean enabled);
64
+
65
+ @ReactMethod
66
+ @DoNotStrip
67
+ public abstract void observeVolumeChanges(boolean enabled);
68
+
69
+ @ReactMethod
70
+ @DoNotStrip
71
+ public abstract void requestRecordingPermissions(Promise promise);
72
+
73
+ @ReactMethod
74
+ @DoNotStrip
75
+ public abstract void checkRecordingPermissions(Promise promise);
76
+
77
+ @ReactMethod
78
+ @DoNotStrip
79
+ public abstract void requestNotificationPermissions(Promise promise);
80
+
81
+ @ReactMethod
82
+ @DoNotStrip
83
+ public abstract void checkNotificationPermissions(Promise promise);
84
+
85
+ @ReactMethod
86
+ @DoNotStrip
87
+ public abstract void getDevicesInfo(Promise promise);
88
+
89
+ @ReactMethod
90
+ @DoNotStrip
91
+ public abstract void registerNotification(String type, String key, Promise promise);
92
+
93
+ @ReactMethod
94
+ @DoNotStrip
95
+ public abstract void showNotification(String key, ReadableMap options, Promise promise);
96
+
97
+ @ReactMethod
98
+ @DoNotStrip
99
+ public abstract void updateNotification(String key, ReadableMap options, Promise promise);
100
+
101
+ @ReactMethod
102
+ @DoNotStrip
103
+ public abstract void hideNotification(String key, Promise promise);
104
+
105
+ @ReactMethod
106
+ @DoNotStrip
107
+ public abstract void unregisterNotification(String key, Promise promise);
108
+
109
+ @ReactMethod
110
+ @DoNotStrip
111
+ public abstract void isNotificationActive(String key, Promise promise);
112
+ }
@@ -16,6 +16,7 @@
16
16
  #include <audioapi/core/utils/worklets/SafeIncludes.h>
17
17
 
18
18
  #include <memory>
19
+ #include <string>
19
20
  #include <vector>
20
21
 
21
22
  namespace audioapi {
@@ -137,19 +138,10 @@ class AudioAPIModuleInstaller {
137
138
  const jsi::Value &thisValue,
138
139
  const jsi::Value *args,
139
140
  size_t count) -> jsi::Value {
140
- auto options = args[0].getObject(runtime);
141
-
142
- auto sampleRate =
143
- static_cast<float>(options.getProperty(runtime, "sampleRate").getNumber());
144
- auto bufferLength =
145
- static_cast<int>(options.getProperty(runtime, "bufferLengthInSamples").getNumber());
146
-
147
- auto audioRecorderHostObject = std::make_shared<AudioRecorderHostObject>(
148
- audioEventHandlerRegistry, sampleRate, bufferLength);
141
+ auto audioRecorderHostObject =
142
+ std::make_shared<AudioRecorderHostObject>(audioEventHandlerRegistry);
149
143
 
150
144
  auto jsiObject = jsi::Object::createFromHostObject(runtime, audioRecorderHostObject);
151
- jsiObject.setExternalMemoryPressure(
152
- runtime, sizeof(float) * bufferLength); // rough estimate of underlying buffer
153
145
 
154
146
  return jsiObject;
155
147
  });
@@ -5,6 +5,7 @@
5
5
  #include <audioapi/core/inputs/AudioRecorder.h>
6
6
  #include <audioapi/core/sources/AudioBuffer.h>
7
7
  #include <audioapi/events/AudioEventHandlerRegistry.h>
8
+ #include <audioapi/utils/AudioFileProperties.h>
8
9
  #ifdef ANDROID
9
10
  #include <audioapi/android/core/AndroidAudioRecorder.h>
10
11
  #else
@@ -15,33 +16,121 @@
15
16
  namespace audioapi {
16
17
 
17
18
  AudioRecorderHostObject::AudioRecorderHostObject(
18
- const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry,
19
- float sampleRate,
20
- int bufferLength) {
19
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry) {
21
20
  #ifdef ANDROID
22
- audioRecorder_ =
23
- std::make_shared<AndroidAudioRecorder>(sampleRate, bufferLength, audioEventHandlerRegistry);
21
+ audioRecorder_ = std::make_shared<AndroidAudioRecorder>(audioEventHandlerRegistry);
24
22
  #else
25
- audioRecorder_ =
26
- std::make_shared<IOSAudioRecorder>(sampleRate, bufferLength, audioEventHandlerRegistry);
23
+ audioRecorder_ = std::make_shared<IOSAudioRecorder>(audioEventHandlerRegistry);
27
24
  #endif
28
25
 
29
- addSetters(JSI_EXPORT_PROPERTY_SETTER(AudioRecorderHostObject, onAudioReady));
30
-
31
26
  addFunctions(
32
27
  JSI_EXPORT_FUNCTION(AudioRecorderHostObject, start),
33
28
  JSI_EXPORT_FUNCTION(AudioRecorderHostObject, stop),
29
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, isRecording),
30
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, enableFileOutput),
31
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, disableFileOutput),
32
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, pause),
33
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, resume),
34
34
  JSI_EXPORT_FUNCTION(AudioRecorderHostObject, connect),
35
- JSI_EXPORT_FUNCTION(AudioRecorderHostObject, disconnect));
35
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, disconnect),
36
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, setOnAudioReady),
37
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, clearOnAudioReady),
38
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, setOnError),
39
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, clearOnError),
40
+ JSI_EXPORT_FUNCTION(AudioRecorderHostObject, getCurrentDuration));
41
+ }
42
+
43
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, start) {
44
+ auto result = audioRecorder_->start();
45
+ auto jsResult = jsi::Object(runtime);
46
+
47
+ jsResult.setProperty(
48
+ runtime,
49
+ "status",
50
+ jsi::String::createFromUtf8(runtime, result.is_ok() ? "success" : "error"));
51
+
52
+ if (result.is_ok()) {
53
+ jsResult.setProperty(runtime, "path", jsi::String::createFromUtf8(runtime, result.unwrap()));
54
+ } else {
55
+ jsResult.setProperty(
56
+ runtime, "message", jsi::String::createFromUtf8(runtime, result.unwrap_err()));
57
+ }
58
+
59
+ return jsResult;
60
+ }
61
+
62
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, stop) {
63
+ auto result = audioRecorder_->stop();
64
+ auto jsResult = jsi::Object(runtime);
65
+
66
+ jsResult.setProperty(
67
+ runtime,
68
+ "status",
69
+ jsi::String::createFromUtf8(runtime, result.is_ok() ? "success" : "error"));
70
+
71
+ if (result.is_ok()) {
72
+ auto info = result.unwrap();
73
+
74
+ jsResult.setProperty(runtime, "path", jsi::String::createFromUtf8(runtime, std::get<0>(info)));
75
+ jsResult.setProperty(runtime, "size", std::get<1>(info));
76
+ jsResult.setProperty(runtime, "duration", std::get<2>(info));
77
+ } else {
78
+ jsResult.setProperty(
79
+ runtime, "message", jsi::String::createFromUtf8(runtime, result.unwrap_err()));
80
+ }
81
+
82
+ return jsResult;
83
+ }
84
+
85
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, isRecording) {
86
+ return jsi::Value(audioRecorder_->isRecording());
87
+ }
88
+
89
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, isPaused) {
90
+ return jsi::Value(audioRecorder_->isPaused());
91
+ }
92
+
93
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, enableFileOutput) {
94
+ auto fileProperties = AudioFileProperties::CreateFromJSIValue(runtime, args[0]);
95
+
96
+ auto result = audioRecorder_->enableFileOutput(fileProperties);
97
+ auto jsResult = jsi::Object(runtime);
98
+
99
+ jsResult.setProperty(
100
+ runtime,
101
+ "status",
102
+ jsi::String::createFromUtf8(runtime, result.is_ok() ? "success" : "error"));
103
+
104
+ if (result.is_ok()) {
105
+ jsResult.setProperty(runtime, "path", jsi::String::createFromUtf8(runtime, result.unwrap()));
106
+ } else {
107
+ jsResult.setProperty(
108
+ runtime, "message", jsi::String::createFromUtf8(runtime, result.unwrap_err()));
109
+ }
110
+
111
+ return jsResult;
36
112
  }
37
113
 
38
- JSI_PROPERTY_SETTER_IMPL(AudioRecorderHostObject, onAudioReady) {
39
- audioRecorder_->setOnAudioReadyCallbackId(std::stoull(value.getString(runtime).utf8(runtime)));
114
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, disableFileOutput) {
115
+ audioRecorder_->disableFileOutput();
116
+ return jsi::Value::undefined();
117
+ }
118
+
119
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, pause) {
120
+ audioRecorder_->pause();
121
+
122
+ return jsi::Value::undefined();
123
+ }
124
+
125
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, resume) {
126
+ audioRecorder_->resume();
127
+ return jsi::Value::undefined();
40
128
  }
41
129
 
42
130
  JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, connect) {
43
131
  auto adapterNodeHostObject =
44
132
  args[0].getObject(runtime).getHostObject<RecorderAdapterNodeHostObject>(runtime);
133
+
45
134
  audioRecorder_->connect(
46
135
  std::static_pointer_cast<RecorderAdapterNode>(adapterNodeHostObject->node_));
47
136
  return jsi::Value::undefined();
@@ -49,19 +138,59 @@ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, connect) {
49
138
 
50
139
  JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, disconnect) {
51
140
  audioRecorder_->disconnect();
141
+
52
142
  return jsi::Value::undefined();
53
143
  }
54
144
 
55
- JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, start) {
56
- audioRecorder_->start();
145
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, setOnAudioReady) {
146
+ auto options = args[0].getObject(runtime);
147
+
148
+ auto sampleRate = static_cast<float>(options.getProperty(runtime, "sampleRate").getNumber());
149
+ auto bufferLength = static_cast<size_t>(options.getProperty(runtime, "bufferLength").getNumber());
150
+ auto channelCount = static_cast<int>(options.getProperty(runtime, "channelCount").getNumber());
151
+ uint64_t callbackId =
152
+ std::stoull(options.getProperty(runtime, "callbackId").getString(runtime).utf8(runtime));
57
153
 
154
+ auto result =
155
+ audioRecorder_->setOnAudioReadyCallback(sampleRate, bufferLength, channelCount, callbackId);
156
+ auto jsResult = jsi::Object(runtime);
157
+
158
+ jsResult.setProperty(
159
+ runtime,
160
+ "status",
161
+ jsi::String::createFromUtf8(runtime, result.is_ok() ? "success" : "error"));
162
+
163
+ if (result.is_err()) {
164
+ jsResult.setProperty(
165
+ runtime, "message", jsi::String::createFromUtf8(runtime, result.unwrap_err()));
166
+ }
167
+
168
+ return jsResult;
169
+ }
170
+
171
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, clearOnAudioReady) {
172
+ audioRecorder_->clearOnAudioReadyCallback();
58
173
  return jsi::Value::undefined();
59
174
  }
60
175
 
61
- JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, stop) {
62
- audioRecorder_->stop();
176
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, setOnError) {
177
+ auto options = args[0].getObject(runtime);
63
178
 
179
+ uint64_t callbackId =
180
+ std::stoull(options.getProperty(runtime, "callbackId").getString(runtime).utf8(runtime));
181
+
182
+ audioRecorder_->setOnErrorCallback(callbackId);
183
+ return jsi::Value::undefined();
184
+ }
185
+
186
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, clearOnError) {
187
+ audioRecorder_->clearOnErrorCallback();
64
188
  return jsi::Value::undefined();
65
189
  }
66
190
 
191
+ JSI_HOST_FUNCTION_IMPL(AudioRecorderHostObject, getCurrentDuration) {
192
+ double duration = audioRecorder_->getCurrentDuration();
193
+ return jsi::Value(duration);
194
+ }
195
+
67
196
  } // namespace audioapi
@@ -4,6 +4,7 @@
4
4
 
5
5
  #include <cstdio>
6
6
  #include <memory>
7
+ #include <string>
7
8
  #include <utility>
8
9
  #include <vector>
9
10
 
@@ -16,18 +17,32 @@ class AudioEventHandlerRegistry;
16
17
  class AudioRecorderHostObject : public JsiHostObject {
17
18
  public:
18
19
  explicit AudioRecorderHostObject(
19
- const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry,
20
- float sampleRate,
21
- int bufferLength);
20
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry);
22
21
 
23
- JSI_PROPERTY_SETTER_DECL(onAudioReady);
22
+ JSI_HOST_FUNCTION_DECL(start);
23
+ JSI_HOST_FUNCTION_DECL(stop);
24
+ JSI_HOST_FUNCTION_DECL(isRecording);
25
+ JSI_HOST_FUNCTION_DECL(isPaused);
26
+
27
+ JSI_HOST_FUNCTION_DECL(enableFileOutput);
28
+ JSI_HOST_FUNCTION_DECL(disableFileOutput);
29
+
30
+ JSI_HOST_FUNCTION_DECL(pause);
31
+ JSI_HOST_FUNCTION_DECL(resume);
24
32
 
25
33
  JSI_HOST_FUNCTION_DECL(connect);
26
34
  JSI_HOST_FUNCTION_DECL(disconnect);
27
- JSI_HOST_FUNCTION_DECL(start);
28
- JSI_HOST_FUNCTION_DECL(stop);
35
+
36
+ JSI_HOST_FUNCTION_DECL(setOnAudioReady);
37
+ JSI_HOST_FUNCTION_DECL(clearOnAudioReady);
38
+
39
+ JSI_HOST_FUNCTION_DECL(setOnError);
40
+ JSI_HOST_FUNCTION_DECL(clearOnError);
41
+
42
+ JSI_HOST_FUNCTION_DECL(getCurrentDuration);
29
43
 
30
44
  private:
31
45
  std::shared_ptr<AudioRecorder> audioRecorder_;
32
46
  };
47
+
33
48
  } // namespace audioapi
@@ -1,83 +1,66 @@
1
- #include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
1
+
2
2
  #include <audioapi/core/inputs/AudioRecorder.h>
3
- #include <audioapi/core/sources/AudioBuffer.h>
4
- #include <audioapi/core/sources/RecorderAdapterNode.h>
5
- #include <audioapi/events/AudioEventHandlerRegistry.h>
6
- #include <audioapi/utils/AudioBus.h>
7
- #include <audioapi/utils/CircularAudioArray.h>
8
- #include <audioapi/utils/CircularOverflowableAudioArray.h>
9
- #include <algorithm>
10
- #include <memory>
11
- #include <string>
12
- #include <unordered_map>
3
+ #include <audioapi/core/utils/AudioFileWriter.h>
4
+ #include <audioapi/core/utils/AudioRecorderCallback.h>
13
5
 
14
6
  namespace audioapi {
15
7
 
16
- AudioRecorder::AudioRecorder(
17
- float sampleRate,
18
- int bufferLength,
19
- const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry)
20
- : sampleRate_(sampleRate),
21
- bufferLength_(bufferLength),
22
- audioEventHandlerRegistry_(audioEventHandlerRegistry) {
23
- constexpr int minRingBufferSize = 8192;
24
- ringBufferSize_ = std::max(2 * bufferLength, minRingBufferSize);
25
- circularBuffer_ = std::make_shared<CircularAudioArray>(ringBufferSize_);
26
- isRunning_.store(false);
27
- }
8
+ /// @brief Sets the error callback to be invoked when an error occurs during recording.
9
+ /// This method should be called from the JS thread only.
10
+ /// @param callbackId Identifier for the JS callback to be invoked.
11
+ void AudioRecorder::setOnErrorCallback(uint64_t callbackId) {
12
+ std::scoped_lock lock(callbackMutex_, fileWriterMutex_, errorCallbackMutex_);
13
+
14
+ if (usesFileOutput()) {
15
+ fileWriter_->setOnErrorCallback(callbackId);
16
+ }
17
+
18
+ if (usesCallback()) {
19
+ dataCallback_->setOnErrorCallback(callbackId);
20
+ }
28
21
 
29
- void AudioRecorder::setOnAudioReadyCallbackId(uint64_t callbackId) {
30
- onAudioReadyCallbackId_ = callbackId;
22
+ errorCallbackId_.store(callbackId, std::memory_order_release);
31
23
  }
32
24
 
33
- void AudioRecorder::invokeOnAudioReadyCallback(
34
- const std::shared_ptr<AudioBus> &bus,
35
- int numFrames) {
36
- auto audioBuffer = std::make_shared<AudioBuffer>(bus);
37
- auto audioBufferHostObject = std::make_shared<AudioBufferHostObject>(audioBuffer);
25
+ /// @brief Clears the error callback.
26
+ /// If the recorder is currently active, it will stop invoking the callback immediately.
27
+ /// This method should be called from the JS thread only.
28
+ void AudioRecorder::clearOnErrorCallback() {
29
+ std::scoped_lock lock(callbackMutex_, fileWriterMutex_, errorCallbackMutex_);
38
30
 
39
- std::unordered_map<std::string, EventValue> body = {};
40
- body.insert({"buffer", audioBufferHostObject});
41
- body.insert({"numFrames", numFrames});
31
+ if (usesFileOutput()) {
32
+ fileWriter_->clearOnErrorCallback();
33
+ }
42
34
 
43
- if (audioEventHandlerRegistry_ != nullptr) {
44
- audioEventHandlerRegistry_->invokeHandlerWithEventBody(
45
- "audioReady", onAudioReadyCallbackId_, body);
35
+ if (usesCallback()) {
36
+ dataCallback_->clearOnErrorCallback();
46
37
  }
38
+
39
+ errorCallbackId_.store(0, std::memory_order_release);
47
40
  }
48
41
 
49
- void AudioRecorder::sendRemainingData() {
50
- auto bus =
51
- std::make_shared<AudioBus>(circularBuffer_->getNumberOfAvailableFrames(), 1, sampleRate_);
52
- auto *outputChannel = bus->getChannel(0)->getData();
53
- auto availableFrames = static_cast<int>(circularBuffer_->getNumberOfAvailableFrames());
42
+ /// @brief Gets the current duration of the recorded audio in seconds.
43
+ /// @returns Duration in seconds.
44
+ double AudioRecorder::getCurrentDuration() const {
45
+ double duration = 0.0;
54
46
 
55
- circularBuffer_->pop_front(outputChannel, circularBuffer_->getNumberOfAvailableFrames());
47
+ if (usesFileOutput()) {
48
+ duration = fileWriter_->getCurrentDuration();
49
+ }
56
50
 
57
- invokeOnAudioReadyCallback(bus, availableFrames);
51
+ return duration;
58
52
  }
59
53
 
60
- void AudioRecorder::connect(const std::shared_ptr<RecorderAdapterNode> &node) {
61
- node->init(ringBufferSize_);
62
- adapterNodeLock_.lock();
63
- adapterNode_ = node;
64
- adapterNodeLock_.unlock();
54
+ bool AudioRecorder::usesCallback() const {
55
+ return callbackOutputEnabled_.load(std::memory_order_acquire);
65
56
  }
66
57
 
67
- void AudioRecorder::disconnect() {
68
- adapterNodeLock_.lock();
69
- adapterNode_ = nullptr;
70
- adapterNodeLock_.unlock();
58
+ bool AudioRecorder::usesFileOutput() const {
59
+ return fileOutputEnabled_.load(std::memory_order_acquire);
71
60
  }
72
61
 
73
- void AudioRecorder::writeToBuffers(const float *data, int numFrames) {
74
- if (adapterNodeLock_.try_lock()) {
75
- if (adapterNode_ != nullptr) {
76
- adapterNode_->buff_->write(data, numFrames);
77
- }
78
- adapterNodeLock_.unlock();
79
- }
80
- circularBuffer_->push_back(data, numFrames);
62
+ bool AudioRecorder::isConnected() const {
63
+ return isConnected_.load(std::memory_order_acquire);
81
64
  }
82
65
 
83
66
  } // namespace audioapi