react-native-audio-api 0.6.0 → 0.6.1-rc.10

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 (159) hide show
  1. package/README.md +6 -11
  2. package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +13 -8
  3. package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +3 -2
  4. package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +27 -10
  5. package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +12 -3
  6. package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +2 -2
  7. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +4 -6
  8. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +1 -1
  9. package/android/src/main/res/drawable/skip_backward_10.xml +9 -0
  10. package/android/src/main/res/drawable/skip_forward_10.xml +9 -0
  11. package/android/src/oldarch/NativeAudioAPIModuleSpec.java +68 -64
  12. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +2 -1
  13. package/common/cpp/audioapi/HostObjects/AudioBufferQueueSourceNodeHostObject.h +94 -0
  14. package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +7 -7
  15. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +9 -0
  16. package/common/cpp/audioapi/core/AudioContext.cpp +29 -4
  17. package/common/cpp/audioapi/core/AudioContext.h +2 -1
  18. package/common/cpp/audioapi/core/BaseAudioContext.cpp +12 -0
  19. package/common/cpp/audioapi/core/BaseAudioContext.h +4 -3
  20. package/common/cpp/audioapi/core/sources/AudioBuffer.h +1 -0
  21. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +236 -0
  22. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +72 -0
  23. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +1 -1
  24. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +11 -3
  25. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +3 -4
  26. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +2 -1
  27. package/ios/audioapi/ios/AudioAPIModule.mm +28 -15
  28. package/ios/audioapi/ios/core/IOSAudioPlayer.h +3 -2
  29. package/ios/audioapi/ios/core/IOSAudioPlayer.mm +21 -10
  30. package/ios/audioapi/ios/core/NativeAudioPlayer.h +4 -0
  31. package/ios/audioapi/ios/core/NativeAudioPlayer.m +15 -0
  32. package/ios/audioapi/ios/system/AudioEngine.h +1 -0
  33. package/ios/audioapi/ios/system/AudioEngine.mm +11 -1
  34. package/ios/audioapi/ios/system/AudioSessionManager.mm +1 -1
  35. package/ios/audioapi/ios/system/LockScreenManager.mm +13 -1
  36. package/ios/audioapi/ios/system/NotificationManager.mm +1 -1
  37. package/lib/commonjs/api.js +7 -0
  38. package/lib/commonjs/api.js.map +1 -1
  39. package/lib/commonjs/core/AudioBufferQueueSourceNode.js +46 -0
  40. package/lib/commonjs/core/AudioBufferQueueSourceNode.js.map +1 -0
  41. package/lib/commonjs/core/AudioContext.js +2 -2
  42. package/lib/commonjs/core/AudioContext.js.map +1 -1
  43. package/lib/commonjs/core/AudioNode.js +5 -1
  44. package/lib/commonjs/core/AudioNode.js.map +1 -1
  45. package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
  46. package/lib/commonjs/core/BaseAudioContext.js +4 -0
  47. package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
  48. package/lib/commonjs/hooks/useSytemVolume.js +1 -1
  49. package/lib/commonjs/hooks/useSytemVolume.js.map +1 -1
  50. package/lib/commonjs/plugin/withAudioAPI.js +15 -14
  51. package/lib/commonjs/plugin/withAudioAPI.js.map +1 -1
  52. package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
  53. package/lib/commonjs/system/AudioManager.js +12 -10
  54. package/lib/commonjs/system/AudioManager.js.map +1 -1
  55. package/lib/commonjs/web-core/AudioBufferSourceNode.js +4 -4
  56. package/lib/commonjs/web-core/AudioBufferSourceNode.js.map +1 -1
  57. package/lib/commonjs/web-core/AudioContext.js +5 -3
  58. package/lib/commonjs/web-core/AudioContext.js.map +1 -1
  59. package/lib/commonjs/web-core/AudioNode.js +8 -2
  60. package/lib/commonjs/web-core/AudioNode.js.map +1 -1
  61. package/lib/commonjs/web-core/AudioParam.js +2 -1
  62. package/lib/commonjs/web-core/AudioParam.js.map +1 -1
  63. package/lib/commonjs/web-core/BiquadFilterNode.js +4 -4
  64. package/lib/commonjs/web-core/BiquadFilterNode.js.map +1 -1
  65. package/lib/commonjs/web-core/GainNode.js +1 -1
  66. package/lib/commonjs/web-core/GainNode.js.map +1 -1
  67. package/lib/commonjs/web-core/OscillatorNode.js +2 -2
  68. package/lib/commonjs/web-core/OscillatorNode.js.map +1 -1
  69. package/lib/commonjs/web-core/StereoPannerNode.js +1 -1
  70. package/lib/commonjs/web-core/StereoPannerNode.js.map +1 -1
  71. package/lib/module/api.js +1 -0
  72. package/lib/module/api.js.map +1 -1
  73. package/lib/module/core/AudioBufferQueueSourceNode.js +40 -0
  74. package/lib/module/core/AudioBufferQueueSourceNode.js.map +1 -0
  75. package/lib/module/core/AudioContext.js +2 -2
  76. package/lib/module/core/AudioContext.js.map +1 -1
  77. package/lib/module/core/AudioNode.js +5 -1
  78. package/lib/module/core/AudioNode.js.map +1 -1
  79. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
  80. package/lib/module/core/BaseAudioContext.js +4 -0
  81. package/lib/module/core/BaseAudioContext.js.map +1 -1
  82. package/lib/module/hooks/useSytemVolume.js +1 -1
  83. package/lib/module/hooks/useSytemVolume.js.map +1 -1
  84. package/lib/module/plugin/withAudioAPI.js +15 -14
  85. package/lib/module/plugin/withAudioAPI.js.map +1 -1
  86. package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
  87. package/lib/module/system/AudioManager.js +12 -10
  88. package/lib/module/system/AudioManager.js.map +1 -1
  89. package/lib/module/web-core/AudioBufferSourceNode.js +4 -4
  90. package/lib/module/web-core/AudioBufferSourceNode.js.map +1 -1
  91. package/lib/module/web-core/AudioContext.js +5 -3
  92. package/lib/module/web-core/AudioContext.js.map +1 -1
  93. package/lib/module/web-core/AudioNode.js +7 -2
  94. package/lib/module/web-core/AudioNode.js.map +1 -1
  95. package/lib/module/web-core/AudioParam.js +2 -1
  96. package/lib/module/web-core/AudioParam.js.map +1 -1
  97. package/lib/module/web-core/BiquadFilterNode.js +4 -4
  98. package/lib/module/web-core/BiquadFilterNode.js.map +1 -1
  99. package/lib/module/web-core/GainNode.js +1 -1
  100. package/lib/module/web-core/GainNode.js.map +1 -1
  101. package/lib/module/web-core/OscillatorNode.js +2 -2
  102. package/lib/module/web-core/OscillatorNode.js.map +1 -1
  103. package/lib/module/web-core/StereoPannerNode.js +1 -1
  104. package/lib/module/web-core/StereoPannerNode.js.map +1 -1
  105. package/lib/typescript/api.d.ts +2 -1
  106. package/lib/typescript/api.d.ts.map +1 -1
  107. package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts +16 -0
  108. package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts.map +1 -0
  109. package/lib/typescript/core/AudioContext.d.ts.map +1 -1
  110. package/lib/typescript/core/AudioNode.d.ts +1 -1
  111. package/lib/typescript/core/AudioNode.d.ts.map +1 -1
  112. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +4 -3
  113. package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -1
  114. package/lib/typescript/core/BaseAudioContext.d.ts +2 -0
  115. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  116. package/lib/typescript/events/types.d.ts +21 -8
  117. package/lib/typescript/events/types.d.ts.map +1 -1
  118. package/lib/typescript/hooks/useSytemVolume.d.ts.map +1 -1
  119. package/lib/typescript/interfaces.d.ts +9 -0
  120. package/lib/typescript/interfaces.d.ts.map +1 -1
  121. package/lib/typescript/plugin/withAudioAPI.d.ts +7 -6
  122. package/lib/typescript/plugin/withAudioAPI.d.ts.map +1 -1
  123. package/lib/typescript/specs/NativeAudioAPIModule.d.ts +3 -2
  124. package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
  125. package/lib/typescript/system/AudioManager.d.ts +6 -4
  126. package/lib/typescript/system/AudioManager.d.ts.map +1 -1
  127. package/lib/typescript/types.d.ts +2 -1
  128. package/lib/typescript/types.d.ts.map +1 -1
  129. package/lib/typescript/web-core/AudioBufferSourceNode.d.ts.map +1 -1
  130. package/lib/typescript/web-core/AudioContext.d.ts +1 -1
  131. package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
  132. package/lib/typescript/web-core/AudioNode.d.ts +2 -1
  133. package/lib/typescript/web-core/AudioNode.d.ts.map +1 -1
  134. package/lib/typescript/web-core/AudioParam.d.ts +4 -2
  135. package/lib/typescript/web-core/AudioParam.d.ts.map +1 -1
  136. package/package.json +2 -1
  137. package/src/api.ts +5 -1
  138. package/src/core/AudioBufferQueueSourceNode.ts +71 -0
  139. package/src/core/AudioContext.ts +7 -2
  140. package/src/core/AudioNode.ts +6 -2
  141. package/src/core/AudioScheduledSourceNode.ts +3 -3
  142. package/src/core/BaseAudioContext.ts +8 -0
  143. package/src/events/types.ts +33 -8
  144. package/src/hooks/useSytemVolume.ts +6 -3
  145. package/src/interfaces.ts +18 -0
  146. package/src/plugin/withAudioAPI.ts +36 -29
  147. package/src/specs/NativeAudioAPIModule.ts +14 -6
  148. package/src/system/AudioManager.ts +21 -16
  149. package/src/types.ts +2 -1
  150. package/src/web-core/AudioBufferSourceNode.tsx +9 -4
  151. package/src/web-core/AudioContext.tsx +7 -3
  152. package/src/web-core/AudioNode.tsx +10 -3
  153. package/src/web-core/AudioParam.tsx +5 -2
  154. package/src/web-core/BiquadFilterNode.tsx +4 -4
  155. package/src/web-core/GainNode.tsx +1 -1
  156. package/src/web-core/OscillatorNode.tsx +2 -2
  157. package/src/web-core/StereoPannerNode.tsx +1 -1
  158. package/android/src/main/res/drawable/skip_backward_5.xml +0 -9
  159. package/android/src/main/res/drawable/skip_forward_5.xml +0 -9
package/README.md CHANGED
@@ -34,17 +34,12 @@ check out the [Getting Started](https://docs.swmansion.com/react-native-audio-ap
34
34
  Ability to modify playback speed without affecting pitch of the sound
35
35
  <br />
36
36
 
37
- - <sub>![Coming in 0.6.0](https://img.shields.io/badge/Coming_in-0.6.0-blue)</sub> **System configuration** 🛠️ <br />
38
- Full control of system audio settings, remote controls, lock screen integration and most importantly configurable background modes
39
- <br />
40
-
41
- - **Microphone support** 🎙️ <br />
42
- Grab audio data from device microphone or connected device, connect it to the audio graph or stream through the internet
43
- <br />
44
-
45
- - **Connect audio param** 🤞 <br />
46
- Ability to connect Audio nodes to audio params, which will allow for powerful and efficient modulation of audio parameters, creating effects like tremolo, vibrato or complex envelope followers.
47
- <br />
37
+ - <sub>[![Released in 0.6.0](https://img.shields.io/badge/Released_in-0.6.0-green)](https://github.com/software-mansion/react-native-audio-api/releases/tag/0.6.0)</sub> <br/> **System configuration** 🛠️ <br />
38
+ Full control of system audio settings, remote controls, lock screen integration and most importantly configurable background modes <br />
39
+ <br /> **Microphone support** 🎙️ <br />
40
+ Grab audio data from device microphone or connected device, connect it to the audio graph or stream through the internet <br />
41
+ <br /> **Connect audio param** 🤞 <br />
42
+ Ability to connect Audio nodes to audio params, which will allow for powerful and efficient modulation of audio parameters, creating effects like tremolo, vibrato or complex envelope followers. <br />
48
43
 
49
44
  - **JS Audio Worklets** 🐎 <br />
50
45
  Ability to run JS functions connected to the audio graph running on audio thread allowing for full customization of what happens to the audio signal.
@@ -33,25 +33,30 @@ void AudioPlayer::start() {
33
33
  }
34
34
  }
35
35
 
36
+ void AudioPlayer::stop() {
37
+ if (mStream_) {
38
+ mStream_->requestStop();
39
+ }
40
+ }
41
+
36
42
  void AudioPlayer::resume() {
37
43
  if (mStream_) {
38
44
  mStream_->requestStart();
39
45
  }
40
46
  }
41
47
 
42
- void AudioPlayer::stop() {
43
- isInitialized_ = false;
44
-
48
+ void AudioPlayer::suspend() {
45
49
  if (mStream_) {
46
- mStream_->requestStop();
47
- mStream_->close();
48
- mStream_.reset();
50
+ mStream_->requestPause();
49
51
  }
50
52
  }
51
53
 
52
- void AudioPlayer::pause() {
54
+ void AudioPlayer::cleanup() {
55
+ isInitialized_ = false;
56
+
53
57
  if (mStream_) {
54
- mStream_->requestPause();
58
+ mStream_->close();
59
+ mStream_.reset();
55
60
  }
56
61
  }
57
62
 
@@ -19,9 +19,10 @@ class AudioPlayer : public AudioStreamDataCallback {
19
19
  float sampleRate);
20
20
 
21
21
  void start();
22
- void resume();
23
22
  void stop();
24
- void pause();
23
+ void resume();
24
+ void suspend();
25
+ void cleanup();
25
26
 
26
27
  DataCallbackResult onAudioReady(
27
28
  AudioStream *oboeStream,
@@ -53,14 +53,37 @@ class AudioAPIModule(
53
53
  return true
54
54
  }
55
55
 
56
+ @Synchronized
57
+ override fun getDevicePreferredSampleRate(): Double = MediaSessionManager.getDevicePreferredSampleRate()
58
+
59
+ @Synchronized
60
+ override fun setAudioSessionActivity(
61
+ enabled: Boolean,
62
+ promise: Promise?,
63
+ ) {
64
+ // noting to do here
65
+ }
66
+
67
+ @Synchronized
68
+ override fun setAudioSessionOptions(
69
+ category: String?,
70
+ mode: String?,
71
+ options: ReadableArray?,
72
+ ) {
73
+ // noting to do here
74
+ }
75
+
76
+ @Synchronized
56
77
  override fun setLockScreenInfo(info: ReadableMap?) {
57
78
  MediaSessionManager.setLockScreenInfo(info)
58
79
  }
59
80
 
81
+ @Synchronized
60
82
  override fun resetLockScreenInfo() {
61
83
  MediaSessionManager.resetLockScreenInfo()
62
84
  }
63
85
 
86
+ @Synchronized
64
87
  override fun enableRemoteCommand(
65
88
  name: String?,
66
89
  enabled: Boolean,
@@ -68,29 +91,23 @@ class AudioAPIModule(
68
91
  MediaSessionManager.enableRemoteCommand(name!!, enabled)
69
92
  }
70
93
 
71
- override fun setAudioSessionOptions(
72
- category: String?,
73
- mode: String?,
74
- options: ReadableArray?,
75
- ) {
76
- // noting to do here
77
- }
78
-
79
- override fun getDevicePreferredSampleRate(): Double = MediaSessionManager.getDevicePreferredSampleRate()
80
-
94
+ @Synchronized
81
95
  override fun observeAudioInterruptions(enabled: Boolean) {
82
96
  MediaSessionManager.observeAudioInterruptions(enabled)
83
97
  }
84
98
 
99
+ @Synchronized
85
100
  override fun observeVolumeChanges(enabled: Boolean) {
86
101
  MediaSessionManager.observeVolumeChanges(enabled)
87
102
  }
88
103
 
104
+ @Synchronized
89
105
  override fun requestRecordingPermissions(promise: Promise?) {
90
106
  val res = MediaSessionManager.requestRecordingPermissions(currentActivity)
91
107
  promise!!.resolve(res)
92
108
  }
93
109
 
110
+ @Synchronized
94
111
  override fun checkRecordingPermissions(promise: Promise?) {
95
112
  val res = MediaSessionManager.checkRecordingPermissions()
96
113
  promise!!.resolve(res)
@@ -35,7 +35,7 @@ class LockScreenManager(
35
35
  private var artist: String? = null
36
36
  private var album: String? = null
37
37
  private var description: String? = null
38
- private var duration: Long = 0
38
+ private var duration: Long = 0L
39
39
  private var speed: Float = 1.0F
40
40
  private var elapsedTime: Long = 0L
41
41
  private var artwork: String? = null
@@ -142,9 +142,13 @@ class LockScreenManager(
142
142
  state.playbackSpeed
143
143
  }
144
144
 
145
+ if (isPlaying && speed == 0F) {
146
+ speed = 1F
147
+ }
148
+
145
149
  elapsedTime =
146
150
  if (info.hasKey("elapsedTime")) {
147
- info.getDouble("elapsedTime").toLong()
151
+ (info.getDouble("elapsedTime") * 1000).toLong()
148
152
  } else {
149
153
  state.position
150
154
  }
@@ -250,7 +254,7 @@ class LockScreenManager(
250
254
  return bitmap
251
255
  }
252
256
 
253
- fun updatePlaybackState(playbackState: Int) {
257
+ private fun updatePlaybackState(playbackState: Int) {
254
258
  isPlaying = playbackState == PlaybackStateCompat.STATE_PLAYING
255
259
 
256
260
  pb.setState(playbackState, elapsedTime, speed)
@@ -285,6 +289,11 @@ class LockScreenManager(
285
289
  if (hasControl(PlaybackStateCompat.ACTION_REWIND)) {
286
290
  controlCount += 1
287
291
  }
292
+
293
+ if (hasControl(PlaybackStateCompat.ACTION_SEEK_TO)) {
294
+ controlCount += 1
295
+ }
296
+
288
297
  val actions = IntArray(controlCount)
289
298
  for (i in actions.indices) {
290
299
  actions[i] = i
@@ -154,7 +154,7 @@ class MediaNotificationManager(
154
154
 
155
155
  skipForward =
156
156
  createAction(
157
- "skip_forward_5",
157
+ "skip_forward_10",
158
158
  "Skip Forward",
159
159
  mask,
160
160
  PlaybackStateCompat.ACTION_FAST_FORWARD,
@@ -163,7 +163,7 @@ class MediaNotificationManager(
163
163
 
164
164
  skipBackward =
165
165
  createAction(
166
- "skip_backward_5",
166
+ "skip_backward_10",
167
167
  "Skip Backward",
168
168
  mask,
169
169
  PlaybackStateCompat.ACTION_REWIND,
@@ -3,7 +3,6 @@ package com.swmansion.audioapi.system
3
3
  import android.content.Intent
4
4
  import android.os.Build
5
5
  import android.support.v4.media.session.MediaSessionCompat
6
- import android.support.v4.media.session.PlaybackStateCompat
7
6
  import androidx.core.app.NotificationManagerCompat
8
7
  import com.swmansion.audioapi.AudioAPIModule
9
8
  import java.lang.ref.WeakReference
@@ -11,15 +10,12 @@ import java.util.HashMap
11
10
 
12
11
  class MediaSessionCallback(
13
12
  private val audioAPIModule: WeakReference<AudioAPIModule>,
14
- private val lockScreenManager: WeakReference<LockScreenManager>,
15
13
  ) : MediaSessionCompat.Callback() {
16
14
  override fun onPlay() {
17
- lockScreenManager.get()?.updatePlaybackState(PlaybackStateCompat.STATE_PLAYING)
18
15
  audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remotePlay", mapOf())
19
16
  }
20
17
 
21
18
  override fun onPause() {
22
- lockScreenManager.get()?.updatePlaybackState(PlaybackStateCompat.STATE_PAUSED)
23
19
  audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remotePause", mapOf())
24
20
  }
25
21
 
@@ -44,11 +40,13 @@ class MediaSessionCallback(
44
40
  }
45
41
 
46
42
  override fun onFastForward() {
47
- audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteSkipForward", mapOf())
43
+ val body = HashMap<String, Any>().apply { put("value", 10) }
44
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteSkipForward", body)
48
45
  }
49
46
 
50
47
  override fun onRewind() {
51
- audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteSkipBackward", mapOf())
48
+ val body = HashMap<String, Any>().apply { put("value", 10) }
49
+ audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteSkipBackward", body)
52
50
  }
53
51
 
54
52
  override fun onSeekTo(pos: Long) {
@@ -81,7 +81,7 @@ object MediaSessionManager {
81
81
  this.lockScreenManager = LockScreenManager(this.reactContext, WeakReference(this.mediaSession), WeakReference(mediaNotificationManager))
82
82
  this.mediaReceiver =
83
83
  MediaReceiver(this.reactContext, WeakReference(this.mediaSession), WeakReference(mediaNotificationManager), this.audioAPIModule)
84
- this.mediaSession.setCallback(MediaSessionCallback(this.audioAPIModule, WeakReference(this.lockScreenManager)))
84
+ this.mediaSession.setCallback(MediaSessionCallback(this.audioAPIModule))
85
85
 
86
86
  val filter = IntentFilter()
87
87
  filter.addAction(MediaNotificationManager.REMOVE_NOTIFICATION)
@@ -0,0 +1,9 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="24dp"
3
+ android:height="24dp"
4
+ android:viewportWidth="24.0"
5
+ android:viewportHeight="24.0">
6
+ <path
7
+ android:fillColor="#FFFFFFFF"
8
+ android:pathData="M12,5L12,1L7,6l5,5L12,7c3.3,0 6,2.7 6,6s-2.7,6 -6,6 -6,-2.7 -6,-6L4,13c0,4.4 3.6,8 8,8s8,-3.6 8,-8 -3.6,-8 -8,-8zM10.9,16L10,16v-3.3L9,13v-0.7l1.8,-0.6h0.1L10.9,16zM15.2,14.2c0,0.3 0,0.6 -0.1,0.8l-0.3,0.6s-0.3,0.3 -0.5,0.3 -0.4,0.1 -0.6,0.1 -0.4,0 -0.6,-0.1 -0.3,-0.2 -0.5,-0.3 -0.2,-0.3 -0.3,-0.6 -0.1,-0.5 -0.1,-0.8v-0.7c0,-0.3 0,-0.6 0.1,-0.8l0.3,-0.6s0.3,-0.3 0.5,-0.3 0.4,-0.1 0.6,-0.1 0.4,0 0.6,0.1c0.2,0.1 0.3,0.2 0.5,0.3s0.2,0.3 0.3,0.6 0.1,0.5 0.1,0.8v0.7zM14.3,13.4v-0.5s-0.1,-0.2 -0.1,-0.3 -0.1,-0.1 -0.2,-0.2 -0.2,-0.1 -0.3,-0.1 -0.2,0 -0.3,0.1l-0.2,0.2s-0.1,0.2 -0.1,0.3v2s0.1,0.2 0.1,0.3 0.1,0.1 0.2,0.2 0.2,0.1 0.3,0.1 0.2,0 0.3,-0.1l0.2,-0.2s0.1,-0.2 0.1,-0.3v-1.5z"/>
9
+ </vector>
@@ -0,0 +1,9 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="24dp"
3
+ android:height="24dp"
4
+ android:viewportWidth="24.0"
5
+ android:viewportHeight="24.0">
6
+ <path
7
+ android:fillColor="#FFFFFFFF"
8
+ android:pathData="M4,13c0,4.4 3.6,8 8,8s8,-3.6 8,-8h-2c0,3.3 -2.7,6 -6,6s-6,-2.7 -6,-6 2.7,-6 6,-6v4l5,-5 -5,-5v4c-4.4,0 -8,3.6 -8,8zM10.8,16L10,16v-3.3L9,13v-0.7l1.8,-0.6h0.1L10.9,16zM15.1,14.2c0,0.3 0,0.6 -0.1,0.8l-0.3,0.6s-0.3,0.3 -0.5,0.3 -0.4,0.1 -0.6,0.1 -0.4,0 -0.6,-0.1 -0.3,-0.2 -0.5,-0.3 -0.2,-0.3 -0.3,-0.6 -0.1,-0.5 -0.1,-0.8v-0.7c0,-0.3 0,-0.6 0.1,-0.8l0.3,-0.6s0.3,-0.3 0.5,-0.3 0.4,-0.1 0.6,-0.1 0.4,0 0.6,0.1 0.3,0.2 0.5,0.3 0.2,0.3 0.3,0.6 0.1,0.5 0.1,0.8v0.7zM14.3,13.4v-0.5s-0.1,-0.2 -0.1,-0.3 -0.1,-0.1 -0.2,-0.2 -0.2,-0.1 -0.3,-0.1 -0.2,0 -0.3,0.1l-0.2,0.2s-0.1,0.2 -0.1,0.3v2s0.1,0.2 0.1,0.3 0.1,0.1 0.2,0.2 0.2,0.1 0.3,0.1 0.2,0 0.3,-0.1l0.2,-0.2s0.1,-0.2 0.1,-0.3v-1.5z"/>
9
+ </vector>
@@ -10,67 +10,71 @@
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
42
- @DoNotStrip
43
- public abstract void setLockScreenInfo(ReadableMap info);
44
-
45
- @ReactMethod
46
- @DoNotStrip
47
- public abstract void resetLockScreenInfo();
48
-
49
- @ReactMethod
50
- @DoNotStrip
51
- public abstract void enableRemoteCommand(String name, boolean enabled);
52
-
53
- @ReactMethod
54
- @DoNotStrip
55
- public abstract void setAudioSessionOptions(String category, String mode, ReadableArray options);
56
-
57
- @ReactMethod(isBlockingSynchronousMethod = true)
58
- @DoNotStrip
59
- public abstract double getDevicePreferredSampleRate();
60
-
61
- @ReactMethod
62
- @DoNotStrip
63
- public abstract void observeAudioInterruptions(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
- }
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);
52
+
53
+ @ReactMethod
54
+ @DoNotStrip
55
+ public abstract void setLockScreenInfo(ReadableMap info);
56
+
57
+ @ReactMethod
58
+ @DoNotStrip
59
+ public abstract void resetLockScreenInfo();
60
+
61
+ @ReactMethod
62
+ @DoNotStrip
63
+ public abstract void enableRemoteCommand(String name, boolean enabled);
64
+
65
+ @ReactMethod
66
+ @DoNotStrip
67
+ public abstract void observeAudioInterruptions(boolean enabled);
68
+
69
+ @ReactMethod
70
+ @DoNotStrip
71
+ public abstract void observeVolumeChanges(boolean enabled);
72
+
73
+ @ReactMethod
74
+ @DoNotStrip
75
+ public abstract void requestRecordingPermissions(Promise promise);
76
+
77
+ @ReactMethod
78
+ @DoNotStrip
79
+ public abstract void checkRecordingPermissions(Promise promise);
80
+ }
@@ -45,7 +45,8 @@ class AudioAPIModuleInstaller {
45
45
  size_t count) -> jsi::Value {
46
46
  std::shared_ptr<AudioContext> audioContext;
47
47
  auto sampleRate = static_cast<float>(args[0].getNumber());
48
- audioContext = std::make_shared<AudioContext>(sampleRate, audioEventHandlerRegistry);
48
+ auto initSuspended = args[1].getBool();
49
+ audioContext = std::make_shared<AudioContext>(sampleRate, initSuspended, audioEventHandlerRegistry);
49
50
 
50
51
  auto audioContextHostObject = std::make_shared<AudioContextHostObject>(
51
52
  audioContext, &runtime, jsCallInvoker);
@@ -0,0 +1,94 @@
1
+ #pragma once
2
+
3
+ #include <audioapi/HostObjects/AudioBufferHostObject.h>
4
+ #include <audioapi/core/sources/AudioBufferQueueSourceNode.h>
5
+ #include <audioapi/HostObjects/AudioParamHostObject.h>
6
+ #include <audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h>
7
+
8
+ #include <memory>
9
+ #include <vector>
10
+
11
+ namespace audioapi {
12
+ using namespace facebook;
13
+
14
+ class AudioBufferQueueSourceNodeHostObject
15
+ : public AudioScheduledSourceNodeHostObject {
16
+ public:
17
+ explicit AudioBufferQueueSourceNodeHostObject(
18
+ const std::shared_ptr<AudioBufferQueueSourceNode> &node)
19
+ : AudioScheduledSourceNodeHostObject(node) {
20
+ addGetters(
21
+ JSI_EXPORT_PROPERTY_GETTER(AudioBufferQueueSourceNodeHostObject, detune),
22
+ JSI_EXPORT_PROPERTY_GETTER(AudioBufferQueueSourceNodeHostObject, playbackRate));
23
+
24
+ addSetters(
25
+ JSI_EXPORT_PROPERTY_SETTER(AudioBufferQueueSourceNodeHostObject, onPositionChanged),
26
+ JSI_EXPORT_PROPERTY_SETTER(AudioBufferQueueSourceNodeHostObject, onPositionChangedInterval));
27
+
28
+ // start method is overridden in this class
29
+ functions_->erase("start");
30
+
31
+ addFunctions(
32
+ JSI_EXPORT_FUNCTION(AudioBufferQueueSourceNodeHostObject, start),
33
+ JSI_EXPORT_FUNCTION(AudioBufferQueueSourceNodeHostObject, enqueueBuffer));
34
+ }
35
+
36
+ JSI_PROPERTY_GETTER(detune) {
37
+ auto audioBufferSourceNode =
38
+ std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
39
+ auto detune = audioBufferSourceNode->getDetuneParam();
40
+ auto detuneHostObject = std::make_shared<AudioParamHostObject>(detune);
41
+ return jsi::Object::createFromHostObject(runtime, detuneHostObject);
42
+ }
43
+
44
+ JSI_PROPERTY_GETTER(playbackRate) {
45
+ auto audioBufferSourceNode =
46
+ std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
47
+ auto playbackRate = audioBufferSourceNode->getPlaybackRateParam();
48
+ auto playbackRateHostObject =
49
+ std::make_shared<AudioParamHostObject>(playbackRate);
50
+ return jsi::Object::createFromHostObject(runtime, playbackRateHostObject);
51
+ }
52
+
53
+ JSI_PROPERTY_SETTER(onPositionChanged) {
54
+ auto audioBufferQueueSourceNode =
55
+ std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
56
+
57
+ audioBufferQueueSourceNode->setOnPositionChangedCallbackId(std::stoull(value.getString(runtime).utf8(runtime)));
58
+ }
59
+
60
+ JSI_PROPERTY_SETTER(onPositionChangedInterval) {
61
+ auto audioBufferQueueSourceNode =
62
+ std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
63
+
64
+ audioBufferQueueSourceNode->setOnPositionChangedInterval(value.getNumber());
65
+ }
66
+
67
+ JSI_HOST_FUNCTION(start) {
68
+ auto when = args[0].getNumber();
69
+ auto offset = args[1].getNumber();
70
+
71
+ auto audioBufferQueueSourceNode =
72
+ std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
73
+
74
+ audioBufferQueueSourceNode->start(when, offset);
75
+
76
+ return jsi::Value::undefined();
77
+ }
78
+
79
+ JSI_HOST_FUNCTION(enqueueBuffer) {
80
+ auto audioBufferQueueSourceNode =
81
+ std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
82
+
83
+ auto audioBufferHostObject =
84
+ args[0].getObject(runtime).asHostObject<AudioBufferHostObject>(runtime);
85
+ int bufferId = args[1].asNumber();
86
+ auto isLastBuffer = args[2].asBool();
87
+
88
+ audioBufferQueueSourceNode->enqueueBuffer(audioBufferHostObject->audioBuffer_, bufferId, isLastBuffer);
89
+
90
+ return jsi::Value::undefined();
91
+ }
92
+ };
93
+
94
+ } // namespace audioapi
@@ -46,12 +46,12 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
46
46
  auto result = audioContext->resume();
47
47
 
48
48
  if (!result) {
49
- promise->reject("Failed to resume audio context, because it is already closed.");
50
- return;
49
+ promise->reject("Failed to resume audio context because it is already closed.");
50
+ return;
51
51
  }
52
52
 
53
- promise->resolve([](jsi::Runtime &runtime) {
54
- return jsi::Value::undefined();
53
+ promise->resolve([result](jsi::Runtime &runtime) {
54
+ return jsi::Value(result);
55
55
  });
56
56
  }).detach();
57
57
  });
@@ -66,12 +66,12 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
66
66
  auto result = audioContext->suspend();
67
67
 
68
68
  if (!result) {
69
- promise->reject("Failed to resume audio context, because it is already closed.");
69
+ promise->reject("Failed to suspend audio context because it is already closed.");
70
70
  return;
71
71
  }
72
72
 
73
- promise->resolve([](jsi::Runtime &runtime) {
74
- return jsi::Value::undefined();
73
+ promise->resolve([result](jsi::Runtime &runtime) {
74
+ return jsi::Value(result);
75
75
  });
76
76
  }).detach();
77
77
  });
@@ -4,6 +4,7 @@
4
4
  #include <audioapi/jsi/JsiPromise.h>
5
5
  #include <audioapi/HostObjects/AudioBufferHostObject.h>
6
6
  #include <audioapi/HostObjects/AudioBufferSourceNodeHostObject.h>
7
+ #include <audioapi/HostObjects/AudioBufferQueueSourceNodeHostObject.h>
7
8
  #include <audioapi/HostObjects/AudioDestinationNodeHostObject.h>
8
9
  #include <audioapi/core/BaseAudioContext.h>
9
10
  #include <audioapi/HostObjects/BiquadFilterNodeHostObject.h>
@@ -43,6 +44,7 @@ class BaseAudioContextHostObject : public JsiHostObject {
43
44
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createStereoPanner),
44
45
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBiquadFilter),
45
46
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBufferSource),
47
+ JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBufferQueueSource),
46
48
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBuffer),
47
49
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createPeriodicWave),
48
50
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createAnalyser),
@@ -103,6 +105,13 @@ class BaseAudioContextHostObject : public JsiHostObject {
103
105
  return jsi::Object::createFromHostObject(runtime, bufferSourceHostObject);
104
106
  }
105
107
 
108
+ JSI_HOST_FUNCTION(createBufferQueueSource) {
109
+ auto bufferSource = context_->createBufferQueueSource();
110
+ auto bufferStreamSourceHostObject =
111
+ std::make_shared<AudioBufferQueueSourceNodeHostObject>(bufferSource);
112
+ return jsi::Object::createFromHostObject(runtime, bufferStreamSourceHostObject);
113
+ }
114
+
106
115
  JSI_HOST_FUNCTION(createBuffer) {
107
116
  auto numberOfChannels = static_cast<int>(args[0].getNumber());
108
117
  auto length = static_cast<size_t>(args[1].getNumber());
@@ -12,6 +12,7 @@
12
12
  namespace audioapi {
13
13
  AudioContext::AudioContext(
14
14
  float sampleRate,
15
+ bool initSuspended,
15
16
  const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry)
16
17
  : BaseAudioContext(audioEventHandlerRegistry) {
17
18
  #ifdef ANDROID
@@ -24,8 +25,16 @@ AudioContext::AudioContext(
24
25
  sampleRate_ = sampleRate;
25
26
  audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate);
26
27
 
27
- state_ = ContextState::RUNNING;
28
+ if (initSuspended) {
29
+ playerHasBeenStarted_ = false;
30
+ state_ = ContextState::SUSPENDED;
31
+
32
+ return;
33
+ }
34
+
35
+ playerHasBeenStarted_ = true;
28
36
  audioPlayer_->start();
37
+ state_ = ContextState::RUNNING;
29
38
  }
30
39
 
31
40
  AudioContext::~AudioContext() {
@@ -36,8 +45,9 @@ AudioContext::~AudioContext() {
36
45
 
37
46
  void AudioContext::close() {
38
47
  state_ = ContextState::CLOSED;
39
- audioPlayer_->stop();
40
48
 
49
+ audioPlayer_->stop();
50
+ audioPlayer_->cleanup();
41
51
  nodeManager_->cleanup();
42
52
  }
43
53
 
@@ -46,8 +56,18 @@ bool AudioContext::resume() {
46
56
  return false;
47
57
  }
48
58
 
59
+ if (isRunning()) {
60
+ return true;
61
+ }
62
+
63
+ if (!playerHasBeenStarted_) {
64
+ playerHasBeenStarted_ = true;
65
+ audioPlayer_->start();
66
+ } else {
67
+ audioPlayer_->resume();
68
+ }
69
+
49
70
  state_ = ContextState::RUNNING;
50
- audioPlayer_->resume();
51
71
  return true;
52
72
  }
53
73
 
@@ -56,8 +76,13 @@ bool AudioContext::suspend() {
56
76
  return false;
57
77
  }
58
78
 
79
+ if (isSuspended()) {
80
+ return true;
81
+ }
82
+
83
+ audioPlayer_->suspend();
84
+
59
85
  state_ = ContextState::SUSPENDED;
60
- audioPlayer_->pause();
61
86
  return true;
62
87
  }
63
88