expo-audio 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/audio/AudioModule.kt +33 -20
- package/android/src/main/java/expo/modules/audio/AudioPlayer.kt +20 -4
- package/android/src/main/java/expo/modules/audio/AudioRecorder.kt +4 -3
- package/android/src/main/java/expo/modules/audio/AudioRecords.kt +2 -1
- package/build/Audio.types.d.ts +4 -0
- package/build/Audio.types.d.ts.map +1 -1
- package/build/Audio.types.js.map +1 -1
- package/build/AudioModule.types.d.ts +1 -1
- package/build/AudioModule.types.js.map +1 -1
- package/build/ExpoAudio.d.ts.map +1 -1
- package/build/ExpoAudio.js +7 -1
- package/build/ExpoAudio.js.map +1 -1
- package/build/utils/options.d.ts +1 -0
- package/build/utils/options.d.ts.map +1 -1
- package/build/utils/options.js +1 -0
- package/build/utils/options.js.map +1 -1
- package/ios/AudioModule.swift +4 -4
- package/ios/AudioPlayer.swift +38 -10
- package/ios/AudioRecorder.swift +3 -0
- package/ios/AudioRecords.swift +1 -0
- package/ios/AudioTapProcessor.h +2 -2
- package/ios/AudioTapProcessor.m +10 -10
- package/package.json +2 -2
- package/src/Audio.types.ts +4 -0
- package/src/AudioModule.types.ts +1 -1
- package/src/ExpoAudio.ts +8 -1
- package/src/utils/options.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,12 +10,21 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 0.3.2 — 2025-01-08
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Expose `isMeteringEnabled` to `JS`. ([#33713](https://github.com/expo/expo/pull/33713) by [@alanjhughes](https://github.com/alanjhughes))
|
|
18
|
+
- On `Android`, allow player to accept a `null` audio source. ([#33854](https://github.com/expo/expo/pull/33854) by [@alanjhughes](https://github.com/alanjhughes))
|
|
19
|
+
- Override the `replace` method on the `AudioPlayer` so the source can be parsed correctly. ([#33708](https://github.com/expo/expo/pull/33708) by [@alanjhughes](https://github.com/alanjhughes))
|
|
20
|
+
|
|
13
21
|
## 0.3.1 — 2024-12-16
|
|
14
22
|
|
|
15
23
|
### 🐛 Bug fixes
|
|
16
24
|
|
|
17
25
|
- Update docs and API so all units of time are returned as seconds, not milliseconds. ([#33320](https://github.com/expo/expo/pull/33320) by [@alanjhughes](https://github.com/alanjhughes))
|
|
18
26
|
- Fix `AudioSource` to accept numbers for loading local assets. ([#33676](https://github.com/expo/expo/pull/33676) by [@alanjhughes](https://github.com/alanjhughes))
|
|
27
|
+
- Expose `isMeteringEnabled` to `JS`. ([#33713](https://github.com/expo/expo/pull/33713) by [@alanjhughes](https://github.com/alanjhughes))
|
|
19
28
|
|
|
20
29
|
## 0.3.0 — 2024-12-02
|
|
21
30
|
|
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'expo.modules.audio'
|
|
4
|
-
version = '0.3.
|
|
4
|
+
version = '0.3.2'
|
|
5
5
|
|
|
6
6
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
7
|
apply from: expoModulesCorePlugin
|
|
@@ -14,7 +14,7 @@ android {
|
|
|
14
14
|
namespace "expo.modules.audio"
|
|
15
15
|
defaultConfig {
|
|
16
16
|
versionCode 1
|
|
17
|
-
versionName "0.3.
|
|
17
|
+
versionName "0.3.2"
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
compileOptions {
|
|
@@ -218,13 +218,13 @@ class AudioModule : Module() {
|
|
|
218
218
|
|
|
219
219
|
Property("currentTime") { ref ->
|
|
220
220
|
runOnMain {
|
|
221
|
-
ref.
|
|
221
|
+
ref.currentTime
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
Property("duration") { ref ->
|
|
226
226
|
runOnMain {
|
|
227
|
-
ref.
|
|
227
|
+
ref.duration
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
230
|
|
|
@@ -239,7 +239,7 @@ class AudioModule : Module() {
|
|
|
239
239
|
ref.player.volume
|
|
240
240
|
}
|
|
241
241
|
}.set { ref, volume: Float ->
|
|
242
|
-
|
|
242
|
+
runOnMain {
|
|
243
243
|
ref.player.volume = volume
|
|
244
244
|
}
|
|
245
245
|
}
|
|
@@ -249,32 +249,40 @@ class AudioModule : Module() {
|
|
|
249
249
|
Log.e(TAG, "Audio has been disabled. Re-enable to start playing")
|
|
250
250
|
return@Function
|
|
251
251
|
}
|
|
252
|
-
|
|
252
|
+
runOnMain {
|
|
253
253
|
ref.player.play()
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
Function("pause") { ref: AudioPlayer ->
|
|
258
|
-
|
|
258
|
+
runOnMain {
|
|
259
259
|
ref.player.pause()
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
Function("replace") { ref: AudioPlayer, source: AudioSource ->
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
264
|
+
runOnMain {
|
|
265
|
+
if (ref.player.availableCommands.contains(Player.COMMAND_CHANGE_MEDIA_ITEMS)) {
|
|
266
|
+
val mediaSource = createMediaItem(source)
|
|
267
|
+
val wasPlaying = ref.player.isPlaying
|
|
268
|
+
mediaSource?.let {
|
|
269
|
+
ref.player.replaceMediaItem(0, it.mediaItem)
|
|
270
|
+
if (wasPlaying) {
|
|
271
|
+
ref.player.play()
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
267
275
|
}
|
|
268
276
|
}
|
|
269
277
|
|
|
270
278
|
Function("setAudioSamplingEnabled") { ref: AudioPlayer, enabled: Boolean ->
|
|
271
|
-
|
|
279
|
+
runOnMain {
|
|
272
280
|
ref.setSamplingEnabled(enabled)
|
|
273
281
|
}
|
|
274
282
|
}
|
|
275
283
|
|
|
276
284
|
AsyncFunction("seekTo") { ref: AudioPlayer, seekTime: Double ->
|
|
277
|
-
ref.player.seekTo(seekTime.toLong())
|
|
285
|
+
ref.player.seekTo((seekTime * 1000L).toLong())
|
|
278
286
|
}.runOnQueue(Queues.MAIN)
|
|
279
287
|
|
|
280
288
|
Function("setPlaybackRate") { ref: AudioPlayer, rate: Float ->
|
|
@@ -355,25 +363,30 @@ class AudioModule : Module() {
|
|
|
355
363
|
}
|
|
356
364
|
}
|
|
357
365
|
|
|
358
|
-
private fun createMediaItem(source: AudioSource?): MediaSource {
|
|
359
|
-
val
|
|
360
|
-
|
|
366
|
+
private fun createMediaItem(source: AudioSource?): MediaSource? = source?.let {
|
|
367
|
+
val factory = createDataSourceFactory(it)
|
|
368
|
+
it.uri?.let { uri ->
|
|
369
|
+
val item = MediaItem.fromUri(uri)
|
|
370
|
+
buildMediaSourceFactory(factory, item)
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
private fun createDataSourceFactory(audioSource: AudioSource): DataSource.Factory {
|
|
375
|
+
val isLocal = Util.isLocalFileUri(Uri.parse(audioSource.uri))
|
|
376
|
+
return if (isLocal) {
|
|
361
377
|
DefaultDataSource.Factory(context)
|
|
362
378
|
} else {
|
|
363
379
|
OkHttpDataSource.Factory(httpClient).apply {
|
|
364
|
-
|
|
365
|
-
setDefaultRequestProperties(
|
|
380
|
+
audioSource.headers?.let { headers ->
|
|
381
|
+
setDefaultRequestProperties(headers)
|
|
366
382
|
}
|
|
367
383
|
DefaultDataSource.Factory(context, this)
|
|
368
384
|
}
|
|
369
385
|
}
|
|
370
|
-
|
|
371
|
-
val item = MediaItem.fromUri(source?.uri ?: "")
|
|
372
|
-
return buildMediaSourceFactory(factory, item)
|
|
373
386
|
}
|
|
374
387
|
|
|
375
388
|
private fun updatePlaySoundThroughEarpiece(playThroughEarpiece: Boolean) {
|
|
376
|
-
audioManager.
|
|
389
|
+
audioManager.mode = if (playThroughEarpiece) AudioManager.MODE_IN_COMMUNICATION else AudioManager.MODE_NORMAL
|
|
377
390
|
audioManager.setSpeakerphoneOn(!playThroughEarpiece)
|
|
378
391
|
}
|
|
379
392
|
|
|
@@ -384,7 +397,7 @@ class AudioModule : Module() {
|
|
|
384
397
|
mediaItem: MediaItem
|
|
385
398
|
): MediaSource {
|
|
386
399
|
val uri = mediaItem.localConfiguration?.uri
|
|
387
|
-
val newFactory = when (val type = retrieveStreamType(
|
|
400
|
+
val newFactory = when (val type = uri?.let { retrieveStreamType(it) }) {
|
|
388
401
|
CONTENT_TYPE_SS -> SsMediaSource.Factory(factory)
|
|
389
402
|
CONTENT_TYPE_DASH -> DashMediaSource.Factory(factory)
|
|
390
403
|
CONTENT_TYPE_HLS -> HlsMediaSource.Factory(factory)
|
|
@@ -7,7 +7,10 @@ import android.media.audiofx.Visualizer
|
|
|
7
7
|
import android.util.Log
|
|
8
8
|
import androidx.core.content.ContextCompat
|
|
9
9
|
import androidx.media3.common.AudioAttributes
|
|
10
|
+
import androidx.media3.common.C
|
|
11
|
+
import androidx.media3.common.MediaItem
|
|
10
12
|
import androidx.media3.common.Player
|
|
13
|
+
import androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED
|
|
11
14
|
import androidx.media3.common.util.UnstableApi
|
|
12
15
|
import androidx.media3.exoplayer.ExoPlayer
|
|
13
16
|
import androidx.media3.exoplayer.source.MediaSource
|
|
@@ -29,14 +32,16 @@ private const val AUDIO_SAMPLE_UPDATE = "audioSampleUpdate"
|
|
|
29
32
|
class AudioPlayer(
|
|
30
33
|
context: Context,
|
|
31
34
|
appContext: AppContext,
|
|
32
|
-
source: MediaSource
|
|
35
|
+
source: MediaSource?,
|
|
33
36
|
updateInterval: Double
|
|
34
37
|
) : SharedRef<ExoPlayer>(
|
|
35
38
|
ExoPlayer.Builder(context)
|
|
36
39
|
.setLooper(context.mainLooper)
|
|
37
40
|
.build()
|
|
38
41
|
.apply {
|
|
39
|
-
|
|
42
|
+
source?.let {
|
|
43
|
+
setMediaSource(it)
|
|
44
|
+
}
|
|
40
45
|
setAudioAttributes(AudioAttributes.DEFAULT, true)
|
|
41
46
|
prepare()
|
|
42
47
|
},
|
|
@@ -51,6 +56,9 @@ class AudioPlayer(
|
|
|
51
56
|
private var samplingEnabled = false
|
|
52
57
|
private var visualizer: Visualizer? = null
|
|
53
58
|
|
|
59
|
+
val currentTime get() = player.currentPosition / 1000
|
|
60
|
+
val duration get() = if (player.duration != C.TIME_UNSET) player.duration / 1000 else 0
|
|
61
|
+
|
|
54
62
|
init {
|
|
55
63
|
addPlayerListeners()
|
|
56
64
|
player.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
|
@@ -81,6 +89,14 @@ class AudioPlayer(
|
|
|
81
89
|
sendPlayerUpdate(mapOf("status" to playbackStateToString(playbackState)))
|
|
82
90
|
}
|
|
83
91
|
}
|
|
92
|
+
|
|
93
|
+
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
|
94
|
+
if (reason == MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED) {
|
|
95
|
+
playerScope.launch {
|
|
96
|
+
sendPlayerUpdate()
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
84
100
|
})
|
|
85
101
|
}
|
|
86
102
|
|
|
@@ -107,12 +123,12 @@ class AudioPlayer(
|
|
|
107
123
|
|
|
108
124
|
return mapOf(
|
|
109
125
|
"id" to id,
|
|
110
|
-
"currentTime" to
|
|
126
|
+
"currentTime" to currentTime,
|
|
111
127
|
"playbackState" to playbackStateToString(player.playbackState),
|
|
112
128
|
"timeControlStatus" to if (player.isPlaying) "playing" else "paused",
|
|
113
129
|
"reasonForWaitingToPlay" to null,
|
|
114
130
|
"mute" to isMuted,
|
|
115
|
-
"duration" to
|
|
131
|
+
"duration" to duration,
|
|
116
132
|
"playing" to player.isPlaying,
|
|
117
133
|
"loop" to isLooping,
|
|
118
134
|
"isLoaded" to if (player.playbackState == Player.STATE_ENDED) true else isLoaded,
|
|
@@ -28,7 +28,7 @@ class AudioRecorder(
|
|
|
28
28
|
MediaRecorder.OnErrorListener,
|
|
29
29
|
MediaRecorder.OnInfoListener {
|
|
30
30
|
private var filePath: String? = null
|
|
31
|
-
private var meteringEnabled =
|
|
31
|
+
private var meteringEnabled = options.isMeteringEnabled
|
|
32
32
|
private var durationAlreadyRecorded = 0L
|
|
33
33
|
private var isPrepared = false
|
|
34
34
|
private var shouldCreateRecorder = false
|
|
@@ -148,7 +148,8 @@ class AudioRecorder(
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
override fun
|
|
151
|
+
override fun sharedObjectDidRelease() {
|
|
152
|
+
super.sharedObjectDidRelease()
|
|
152
153
|
recorder.release()
|
|
153
154
|
}
|
|
154
155
|
|
|
@@ -215,7 +216,7 @@ class AudioRecorder(
|
|
|
215
216
|
// getRoutedDevice() is the most reliable way to return the actual mic input, however it
|
|
216
217
|
// only returns a valid device when actively recording, and may throw otherwise.
|
|
217
218
|
// https://developer.android.com/reference/android/media/MediaRecorder#getRoutedDevice()
|
|
218
|
-
deviceInfo = recorder.
|
|
219
|
+
deviceInfo = recorder.routedDevice
|
|
219
220
|
} catch (e: java.lang.Exception) {
|
|
220
221
|
// no-op
|
|
221
222
|
}
|
|
@@ -32,7 +32,8 @@ data class RecordingOptions(
|
|
|
32
32
|
@Field val bitRate: Double?,
|
|
33
33
|
@Field val outputFormat: AndroidOutputFormat?,
|
|
34
34
|
@Field val audioEncoder: AndroidAudioEncoder?,
|
|
35
|
-
@Field val maxFileSize: Int
|
|
35
|
+
@Field val maxFileSize: Int?,
|
|
36
|
+
@Field val isMeteringEnabled: Boolean = false
|
|
36
37
|
) : Record
|
|
37
38
|
|
|
38
39
|
enum class AndroidOutputFormat(val value: String) : Enumerable {
|
package/build/Audio.types.d.ts
CHANGED
|
@@ -98,6 +98,10 @@ export declare enum AudioQuality {
|
|
|
98
98
|
}
|
|
99
99
|
export type BitRateStrategy = 'constant' | 'longTermAverage' | 'variableConstrained' | 'variable';
|
|
100
100
|
export type RecordingOptions = {
|
|
101
|
+
/**
|
|
102
|
+
* A boolean that determines whether audio level information will be part of the status object under the "metering" key.
|
|
103
|
+
*/
|
|
104
|
+
isMeteringEnabled?: boolean;
|
|
101
105
|
/**
|
|
102
106
|
* The desired file extension.
|
|
103
107
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Audio.types.d.ts","sourceRoot":"","sources":["../src/Audio.types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Audio.types.d.ts","sourceRoot":"","sources":["../src/Audio.types.ts"],"names":[],"mappings":"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"}
|
package/build/Audio.types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Audio.types.js","sourceRoot":"","sources":["../src/Audio.types.ts"],"names":[],"mappings":"AA2EA,MAAM,CAAN,IAAY,eAmCX;AAnCD,WAAY,eAAe;IACzB,qCAAkB,CAAA;IAClB,+BAAY,CAAA;IACZ,oCAAmB,CAAA;IACnB,qCAAkB,CAAA;IAClB,oCAAiB,CAAA;IACjB,qCAAkB,CAAA;IAClB,qCAAkB,CAAA;IAClB,uCAAoB,CAAA;IACpB,iCAAc,CAAA;IACd,iCAAc,CAAA;IACd,gCAAa,CAAA;IACb,gCAAa,CAAA;IACb,mCAAgB,CAAA;IAChB,oCAAiB,CAAA;IACjB,oCAAiB,CAAA;IACjB,sCAAmB,CAAA;IACnB,sCAAmB,CAAA;IACnB,sCAAmB,CAAA;IACnB,yCAAsB,CAAA;IACtB,uCAAoB,CAAA;IACpB,uCAAoB,CAAA;IACpB,wCAAqB,CAAA;IACrB,4CAAyB,CAAA;IACzB,2CAAwB,CAAA;IACxB,0CAAuB,CAAA;IACvB,4CAAyB,CAAA;IACzB,+BAAY,CAAA;IACZ,kCAAe,CAAA;IACf,mCAAgB,CAAA;IAChB,gCAAa,CAAA;IACb,4EAAwB,CAAA;IACxB,8EAAyB,CAAA;IACzB,gCAAa,CAAA;IACb,uCAAoB,CAAA;AACtB,CAAC,EAnCW,eAAe,KAAf,eAAe,QAmC1B;AAED,MAAM,CAAN,IAAY,YAMX;AAND,WAAY,YAAY;IACtB,6CAAO,CAAA;IACP,8CAAU,CAAA;IACV,oDAAa,CAAA;IACb,gDAAW,CAAA;IACX,+CAAU,CAAA;AACZ,CAAC,EANW,YAAY,KAAZ,YAAY,QAMvB","sourcesContent":["export type AudioSource =\n | string\n | number\n | null\n | {\n /**\n * A string representing the resource identifier for the audio,\n * which could be an HTTPS address, a local file path, or the name of a static audio file resource.\n */\n uri?: string;\n /**\n * The asset ID of a local audio asset, acquired with the `require` function.\n * This property is exclusive with the `uri` property. When both are present, the `assetId` will be ignored.\n */\n assetId?: number;\n /**\n * An object representing the HTTP headers to send along with the request for a remote audio source.\n * On web requires the `Access-Control-Allow-Origin` header returned by the server to include the current domain.\n */\n headers?: Record<string, string>;\n };\n\nexport type RecordingInput = {\n name: string;\n type: string;\n uid: string;\n};\n\nexport type PitchCorrectionQuality = 'low' | 'medium' | 'high';\n\nexport type AudioStatus = {\n id: number;\n currentTime: number;\n playbackState: string;\n timeControlStatus: string;\n reasonForWaitingToPlay: string;\n mute: boolean;\n duration: number;\n playing: boolean;\n loop: boolean;\n isBuffering: boolean;\n isLoaded: boolean;\n playbackRate: number;\n shouldCorrectPitch: boolean;\n};\n\nexport type RecordingStatus = {\n id: number;\n isFinished: boolean;\n hasError: boolean;\n error: string | null;\n url: string | null;\n};\n\nexport type RecorderState = {\n canRecord: boolean;\n isRecording: boolean;\n durationMillis: number;\n mediaServicesDidReset: boolean;\n metering?: number;\n url: string | null;\n};\n\nexport type AndroidOutputFormat =\n | 'default'\n | '3gp'\n | 'mpeg4'\n | 'amrnb'\n | 'amrwb'\n | 'aac_adts'\n | 'mpeg2ts'\n | 'webm';\n\nexport type AndroidAudioEncoder = 'default' | 'amr_nb' | 'amr_wb' | 'aac' | 'he_aac' | 'aac_eld';\n\nexport enum IOSOutputFormat {\n LINEARPCM = 'lpcm',\n AC3 = 'ac-3',\n '60958AC3' = 'cac3',\n APPLEIMA4 = 'ima4',\n MPEG4AAC = 'aac ',\n MPEG4CELP = 'celp',\n MPEG4HVXC = 'hvxc',\n MPEG4TWINVQ = 'twvq',\n MACE3 = 'MAC3',\n MACE6 = 'MAC6',\n ULAW = 'ulaw',\n ALAW = 'alaw',\n QDESIGN = 'QDMC',\n QDESIGN2 = 'QDM2',\n QUALCOMM = 'Qclp',\n MPEGLAYER1 = '.mp1',\n MPEGLAYER2 = '.mp2',\n MPEGLAYER3 = '.mp3',\n APPLELOSSLESS = 'alac',\n MPEG4AAC_HE = 'aach',\n MPEG4AAC_LD = 'aacl',\n MPEG4AAC_ELD = 'aace',\n MPEG4AAC_ELD_SBR = 'aacf',\n MPEG4AAC_ELD_V2 = 'aacg',\n MPEG4AAC_HE_V2 = 'aacp',\n MPEG4AAC_SPATIAL = 'aacs',\n AMR = 'samr',\n AMR_WB = 'sawb',\n AUDIBLE = 'AUDB',\n ILBC = 'ilbc',\n DVIINTELIMA = 0x6d730011,\n MICROSOFTGSM = 0x6d730031,\n AES3 = 'aes3',\n ENHANCEDAC3 = 'ec-3',\n}\n\nexport enum AudioQuality {\n MIN = 0,\n LOW = 0x20,\n MEDIUM = 0x40,\n HIGH = 0x60,\n MAX = 0x7f,\n}\n\nexport type BitRateStrategy = 'constant' | 'longTermAverage' | 'variableConstrained' | 'variable';\n\nexport type RecordingOptions = {\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate: number;\n /**\n * The desired number of channels.\n *\n * @example 2\n */\n numberOfChannels: number;\n /**\n * The desired bit rate.\n *\n * @example 128000\n */\n bitRate: number;\n /**\n * Recording options for the Android platform.\n */\n android: RecordingOptionsAndroid;\n /**\n * Recording options for the iOS platform.\n */\n ios: RecordingOptionsIos;\n /**\n * Recording options for the Web platform.\n */\n web?: RecordingOptionsWeb;\n};\n\nexport type RecordingOptionsWeb = {\n mimeType?: string;\n bitsPerSecond?: number;\n};\n\nexport type RecordingOptionsIos = {\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension?: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate?: number;\n /**\n * The desired file format. See the [`IOSOutputFormat`](#iosoutputformat) enum for all valid values.\n */\n outputFormat?: string | IOSOutputFormat | number;\n /**\n * The desired audio quality. See the [`AudioQuality`](#audioquality) enum for all valid values.\n */\n audioQuality: AudioQuality | number;\n /**\n * The desired bit rate strategy. See the next section for an enumeration of all valid values of `bitRateStrategy`.\n */\n bitRateStrategy?: number;\n /**\n * The desired bit depth hint.\n *\n * @example 16\n */\n bitDepthHint?: number;\n /**\n * The desired PCM bit depth.\n *\n * @example 16\n */\n linearPCMBitDepth?: number;\n /**\n * A boolean describing if the PCM data should be formatted in big endian.\n */\n linearPCMIsBigEndian?: boolean;\n /**\n * A boolean describing if the PCM data should be encoded in floating point or integral values.\n */\n linearPCMIsFloat?: boolean;\n};\n\nexport type RecordingOptionsAndroid = {\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension?: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate?: number;\n /**\n * The desired file format. See the [`AndroidOutputFormat`](#androidoutputformat) enum for all valid values.\n */\n outputFormat: AndroidOutputFormat;\n /**\n * The desired audio encoder. See the [`AndroidAudioEncoder`](#androidaudioencoder) enum for all valid values.\n */\n audioEncoder: AndroidAudioEncoder;\n /**\n * The desired maximum file size in bytes, after which the recording will stop (but `stopAndUnloadAsync()` must still\n * be called after this point).\n *\n * @example\n * `65536`\n */\n maxFileSize?: number;\n};\n\nexport type AudioMode = {\n playsInSilentMode: boolean;\n interruptionMode: InterruptionMode;\n allowsRecording: boolean;\n shouldPlayInBackground: boolean;\n shouldRouteThroughEarpiece: boolean;\n};\n\nexport type InterruptionMode = 'mixWithOthers' | 'doNotMix' | 'duckOthers';\n"]}
|
|
1
|
+
{"version":3,"file":"Audio.types.js","sourceRoot":"","sources":["../src/Audio.types.ts"],"names":[],"mappings":"AA2EA,MAAM,CAAN,IAAY,eAmCX;AAnCD,WAAY,eAAe;IACzB,qCAAkB,CAAA;IAClB,+BAAY,CAAA;IACZ,oCAAmB,CAAA;IACnB,qCAAkB,CAAA;IAClB,oCAAiB,CAAA;IACjB,qCAAkB,CAAA;IAClB,qCAAkB,CAAA;IAClB,uCAAoB,CAAA;IACpB,iCAAc,CAAA;IACd,iCAAc,CAAA;IACd,gCAAa,CAAA;IACb,gCAAa,CAAA;IACb,mCAAgB,CAAA;IAChB,oCAAiB,CAAA;IACjB,oCAAiB,CAAA;IACjB,sCAAmB,CAAA;IACnB,sCAAmB,CAAA;IACnB,sCAAmB,CAAA;IACnB,yCAAsB,CAAA;IACtB,uCAAoB,CAAA;IACpB,uCAAoB,CAAA;IACpB,wCAAqB,CAAA;IACrB,4CAAyB,CAAA;IACzB,2CAAwB,CAAA;IACxB,0CAAuB,CAAA;IACvB,4CAAyB,CAAA;IACzB,+BAAY,CAAA;IACZ,kCAAe,CAAA;IACf,mCAAgB,CAAA;IAChB,gCAAa,CAAA;IACb,4EAAwB,CAAA;IACxB,8EAAyB,CAAA;IACzB,gCAAa,CAAA;IACb,uCAAoB,CAAA;AACtB,CAAC,EAnCW,eAAe,KAAf,eAAe,QAmC1B;AAED,MAAM,CAAN,IAAY,YAMX;AAND,WAAY,YAAY;IACtB,6CAAO,CAAA;IACP,8CAAU,CAAA;IACV,oDAAa,CAAA;IACb,gDAAW,CAAA;IACX,+CAAU,CAAA;AACZ,CAAC,EANW,YAAY,KAAZ,YAAY,QAMvB","sourcesContent":["export type AudioSource =\n | string\n | number\n | null\n | {\n /**\n * A string representing the resource identifier for the audio,\n * which could be an HTTPS address, a local file path, or the name of a static audio file resource.\n */\n uri?: string;\n /**\n * The asset ID of a local audio asset, acquired with the `require` function.\n * This property is exclusive with the `uri` property. When both are present, the `assetId` will be ignored.\n */\n assetId?: number;\n /**\n * An object representing the HTTP headers to send along with the request for a remote audio source.\n * On web requires the `Access-Control-Allow-Origin` header returned by the server to include the current domain.\n */\n headers?: Record<string, string>;\n };\n\nexport type RecordingInput = {\n name: string;\n type: string;\n uid: string;\n};\n\nexport type PitchCorrectionQuality = 'low' | 'medium' | 'high';\n\nexport type AudioStatus = {\n id: number;\n currentTime: number;\n playbackState: string;\n timeControlStatus: string;\n reasonForWaitingToPlay: string;\n mute: boolean;\n duration: number;\n playing: boolean;\n loop: boolean;\n isBuffering: boolean;\n isLoaded: boolean;\n playbackRate: number;\n shouldCorrectPitch: boolean;\n};\n\nexport type RecordingStatus = {\n id: number;\n isFinished: boolean;\n hasError: boolean;\n error: string | null;\n url: string | null;\n};\n\nexport type RecorderState = {\n canRecord: boolean;\n isRecording: boolean;\n durationMillis: number;\n mediaServicesDidReset: boolean;\n metering?: number;\n url: string | null;\n};\n\nexport type AndroidOutputFormat =\n | 'default'\n | '3gp'\n | 'mpeg4'\n | 'amrnb'\n | 'amrwb'\n | 'aac_adts'\n | 'mpeg2ts'\n | 'webm';\n\nexport type AndroidAudioEncoder = 'default' | 'amr_nb' | 'amr_wb' | 'aac' | 'he_aac' | 'aac_eld';\n\nexport enum IOSOutputFormat {\n LINEARPCM = 'lpcm',\n AC3 = 'ac-3',\n '60958AC3' = 'cac3',\n APPLEIMA4 = 'ima4',\n MPEG4AAC = 'aac ',\n MPEG4CELP = 'celp',\n MPEG4HVXC = 'hvxc',\n MPEG4TWINVQ = 'twvq',\n MACE3 = 'MAC3',\n MACE6 = 'MAC6',\n ULAW = 'ulaw',\n ALAW = 'alaw',\n QDESIGN = 'QDMC',\n QDESIGN2 = 'QDM2',\n QUALCOMM = 'Qclp',\n MPEGLAYER1 = '.mp1',\n MPEGLAYER2 = '.mp2',\n MPEGLAYER3 = '.mp3',\n APPLELOSSLESS = 'alac',\n MPEG4AAC_HE = 'aach',\n MPEG4AAC_LD = 'aacl',\n MPEG4AAC_ELD = 'aace',\n MPEG4AAC_ELD_SBR = 'aacf',\n MPEG4AAC_ELD_V2 = 'aacg',\n MPEG4AAC_HE_V2 = 'aacp',\n MPEG4AAC_SPATIAL = 'aacs',\n AMR = 'samr',\n AMR_WB = 'sawb',\n AUDIBLE = 'AUDB',\n ILBC = 'ilbc',\n DVIINTELIMA = 0x6d730011,\n MICROSOFTGSM = 0x6d730031,\n AES3 = 'aes3',\n ENHANCEDAC3 = 'ec-3',\n}\n\nexport enum AudioQuality {\n MIN = 0,\n LOW = 0x20,\n MEDIUM = 0x40,\n HIGH = 0x60,\n MAX = 0x7f,\n}\n\nexport type BitRateStrategy = 'constant' | 'longTermAverage' | 'variableConstrained' | 'variable';\n\nexport type RecordingOptions = {\n /**\n * A boolean that determines whether audio level information will be part of the status object under the \"metering\" key.\n */\n isMeteringEnabled?: boolean;\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate: number;\n /**\n * The desired number of channels.\n *\n * @example 2\n */\n numberOfChannels: number;\n /**\n * The desired bit rate.\n *\n * @example 128000\n */\n bitRate: number;\n /**\n * Recording options for the Android platform.\n */\n android: RecordingOptionsAndroid;\n /**\n * Recording options for the iOS platform.\n */\n ios: RecordingOptionsIos;\n /**\n * Recording options for the Web platform.\n */\n web?: RecordingOptionsWeb;\n};\n\nexport type RecordingOptionsWeb = {\n mimeType?: string;\n bitsPerSecond?: number;\n};\n\nexport type RecordingOptionsIos = {\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension?: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate?: number;\n /**\n * The desired file format. See the [`IOSOutputFormat`](#iosoutputformat) enum for all valid values.\n */\n outputFormat?: string | IOSOutputFormat | number;\n /**\n * The desired audio quality. See the [`AudioQuality`](#audioquality) enum for all valid values.\n */\n audioQuality: AudioQuality | number;\n /**\n * The desired bit rate strategy. See the next section for an enumeration of all valid values of `bitRateStrategy`.\n */\n bitRateStrategy?: number;\n /**\n * The desired bit depth hint.\n *\n * @example 16\n */\n bitDepthHint?: number;\n /**\n * The desired PCM bit depth.\n *\n * @example 16\n */\n linearPCMBitDepth?: number;\n /**\n * A boolean describing if the PCM data should be formatted in big endian.\n */\n linearPCMIsBigEndian?: boolean;\n /**\n * A boolean describing if the PCM data should be encoded in floating point or integral values.\n */\n linearPCMIsFloat?: boolean;\n};\n\nexport type RecordingOptionsAndroid = {\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension?: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate?: number;\n /**\n * The desired file format. See the [`AndroidOutputFormat`](#androidoutputformat) enum for all valid values.\n */\n outputFormat: AndroidOutputFormat;\n /**\n * The desired audio encoder. See the [`AndroidAudioEncoder`](#androidaudioencoder) enum for all valid values.\n */\n audioEncoder: AndroidAudioEncoder;\n /**\n * The desired maximum file size in bytes, after which the recording will stop (but `stopAndUnloadAsync()` must still\n * be called after this point).\n *\n * @example\n * `65536`\n */\n maxFileSize?: number;\n};\n\nexport type AudioMode = {\n playsInSilentMode: boolean;\n interruptionMode: InterruptionMode;\n allowsRecording: boolean;\n shouldPlayInBackground: boolean;\n shouldRouteThroughEarpiece: boolean;\n};\n\nexport type InterruptionMode = 'mixWithOthers' | 'doNotMix' | 'duckOthers';\n"]}
|
|
@@ -50,7 +50,7 @@ export declare class AudioPlayer extends SharedObject<AudioEvents> {
|
|
|
50
50
|
*/
|
|
51
51
|
isBuffering: boolean;
|
|
52
52
|
/**
|
|
53
|
-
* The current position through the audio item
|
|
53
|
+
* The current position through the audio item in seconds.
|
|
54
54
|
*/
|
|
55
55
|
currentTime: number;
|
|
56
56
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioModule.types.js","sourceRoot":"","sources":["../src/AudioModule.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAsB,YAAY,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["import { NativeModule, PermissionResponse, SharedObject } from 'expo-modules-core';\n\nimport {\n AudioMode,\n AudioSource,\n AudioStatus,\n PitchCorrectionQuality,\n RecorderState,\n RecordingInput,\n RecordingOptions,\n RecordingStatus,\n} from './Audio.types';\n\n/**\n * @hidden\n */\nexport declare class NativeAudioModule extends NativeModule {\n setIsAudioActiveAsync(active: boolean): Promise<void>;\n setAudioModeAsync(category: Partial<AudioMode>): Promise<void>;\n requestRecordingPermissionsAsync(): Promise<PermissionResponse>;\n getRecordingPermissionsAsync(): Promise<PermissionResponse>;\n\n readonly AudioPlayer: typeof AudioPlayer;\n readonly AudioRecorder: typeof AudioRecorder;\n}\n\nexport declare class AudioPlayer extends SharedObject<AudioEvents> {\n /**\n * Initializes a new audio player instance with the given source.\n * @hidden\n */\n constructor(source: AudioSource, updateInterval: number);\n\n /**\n * Unique identifier for the player object.\n */\n id: number;\n\n /**\n * Boolean value indicating whether the player is currently playing.\n */\n playing: boolean;\n\n /**\n * Boolean value indicating whether the player is currently muted.\n */\n muted: boolean;\n\n /**\n * Boolean value indicating whether the player is currently looping.\n */\n loop: boolean;\n\n /**\n * Boolean value indicating whether the player is currently paused.\n */\n paused: boolean;\n\n /**\n * Boolean value indicating whether the player is finished loading.\n */\n isLoaded: boolean;\n\n /**\n * Boolean value indicating whether audio sampling is supported on the platform.\n */\n isAudioSamplingSupported: boolean;\n\n /**\n * Boolean value indicating whether the player is buffering.\n */\n isBuffering: boolean;\n\n /**\n * The current position through the audio item
|
|
1
|
+
{"version":3,"file":"AudioModule.types.js","sourceRoot":"","sources":["../src/AudioModule.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAsB,YAAY,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["import { NativeModule, PermissionResponse, SharedObject } from 'expo-modules-core';\n\nimport {\n AudioMode,\n AudioSource,\n AudioStatus,\n PitchCorrectionQuality,\n RecorderState,\n RecordingInput,\n RecordingOptions,\n RecordingStatus,\n} from './Audio.types';\n\n/**\n * @hidden\n */\nexport declare class NativeAudioModule extends NativeModule {\n setIsAudioActiveAsync(active: boolean): Promise<void>;\n setAudioModeAsync(category: Partial<AudioMode>): Promise<void>;\n requestRecordingPermissionsAsync(): Promise<PermissionResponse>;\n getRecordingPermissionsAsync(): Promise<PermissionResponse>;\n\n readonly AudioPlayer: typeof AudioPlayer;\n readonly AudioRecorder: typeof AudioRecorder;\n}\n\nexport declare class AudioPlayer extends SharedObject<AudioEvents> {\n /**\n * Initializes a new audio player instance with the given source.\n * @hidden\n */\n constructor(source: AudioSource, updateInterval: number);\n\n /**\n * Unique identifier for the player object.\n */\n id: number;\n\n /**\n * Boolean value indicating whether the player is currently playing.\n */\n playing: boolean;\n\n /**\n * Boolean value indicating whether the player is currently muted.\n */\n muted: boolean;\n\n /**\n * Boolean value indicating whether the player is currently looping.\n */\n loop: boolean;\n\n /**\n * Boolean value indicating whether the player is currently paused.\n */\n paused: boolean;\n\n /**\n * Boolean value indicating whether the player is finished loading.\n */\n isLoaded: boolean;\n\n /**\n * Boolean value indicating whether audio sampling is supported on the platform.\n */\n isAudioSamplingSupported: boolean;\n\n /**\n * Boolean value indicating whether the player is buffering.\n */\n isBuffering: boolean;\n\n /**\n * The current position through the audio item in seconds.\n */\n currentTime: number;\n\n /**\n * The total duration of the audio in seconds.\n */\n duration: number;\n\n /**\n * The current volume of the audio.\n */\n volume: number;\n\n /**\n * The current playback rate of the audio.\n */\n playbackRate: number;\n\n /**\n * A boolean describing if we are correcting the pitch for a changed rate.\n */\n shouldCorrectPitch: boolean;\n\n /**\n * The current status of the audio player.\n * @hidden\n */\n currentStatus: AudioStatus;\n\n /**\n * Start playing audio.\n */\n play(): void;\n\n /**\n * Pauses the player.\n */\n pause(): void;\n\n /**\n * Replaces the current audio source with a new one.\n */\n replace(source: AudioSource): void;\n\n /**\n * Seeks the playback by the given number of seconds.\n * @param seconds The number of seconds to seek by.\n */\n seekTo(seconds: number): Promise<void>;\n\n /**\n * Sets the current playback rate of the audio.\n * @param rate The playback rate of the audio.\n * @param pitchCorrectionQuality The quality of the pitch correction.\n */\n setPlaybackRate(rate: number, pitchCorrectionQuality?: PitchCorrectionQuality): void;\n\n /**\n *\n * @hidden\n */\n setAudioSamplingEnabled(enabled: boolean): void;\n\n /**\n * Remove the player from memory to free up resources.\n */\n remove(): void;\n}\n\nexport type AudioSample = {\n channels: AudioSampleChannel[];\n timestamp: number;\n};\n\nexport type AudioSampleChannel = { frames: number[] };\n\nexport type AudioEvents = {\n playbackStatusUpdate(status: AudioStatus): void;\n audioSampleUpdate(data: AudioSample): void;\n};\n\nexport declare class AudioRecorder extends SharedObject<RecordingEvents> {\n /**\n * Initializes a new audio recorder instance with the given source.\n * @hidden\n */\n constructor(options: Partial<RecordingOptions>);\n\n /**\n * Unique identifier for the recorder object.\n */\n id: number;\n\n /**\n * The current length of the recording, in seconds.\n */\n currentTime: number;\n\n /**\n * Boolean value indicating whether the recording is in progress.\n */\n isRecording: boolean;\n\n /**\n * The uri of the recording.\n */\n uri: string | null;\n\n /**\n * Starts the recording.\n */\n record(): void;\n\n /**\n * Stop the recording.\n */\n stop(): Promise<void>;\n\n /**\n * Pause the recording.\n */\n pause(): void;\n\n /**\n * Returns a list of available recording inputs. This method can only be called if the `Recording` has been prepared.\n * @return A `Promise` that is fulfilled with an array of `RecordingInput` objects.\n */\n getAvailableInputs(): RecordingInput[];\n\n /**\n * Returns the currently-selected recording input. This method can only be called if the `Recording` has been prepared.\n * @return A `Promise` that is fulfilled with a `RecordingInput` object.\n */\n getCurrentInput(): RecordingInput;\n\n /**\n * Sets the current recording input.\n * @param inputUid The uid of a `RecordingInput`.\n * @return A `Promise` that is resolved if successful or rejected if not.\n */\n setInput(inputUid: string): void;\n\n /**\n * Status of the current recording.\n */\n getStatus(): RecorderState;\n\n /**\n * Starts the recording at the given time.\n * @param seconds The time in seconds to start recording at.\n */\n startRecordingAtTime(seconds: number): void;\n\n /**\n * Prepares the recording for recording.\n */\n prepareToRecordAsync(options?: Partial<RecordingOptions>): Promise<void>;\n\n /**\n * Stops the recording once the specified time has elapsed.\n * @param seconds The time in seconds to stop recording at.\n */\n recordForDuration(seconds: number): void;\n}\n\nexport type RecordingEvents = {\n recordingStatusUpdate: (status: RecordingStatus) => void;\n};\n"]}
|
package/build/ExpoAudio.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudio.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAA4B,MAAM,mBAAmB,CAAC;AAGjF,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAI9E,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAC7D,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AACvD,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"ExpoAudio.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAA4B,MAAM,mBAAmB,CAAC;AAGjF,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAI9E,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAC7D,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AACvD,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAS/D,wBAAgB,cAAc,CAC5B,MAAM,GAAE,WAAkB,EAC1B,cAAc,GAAE,MAAY,GAC3B,WAAW,CAMb;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAGrE;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,QAWhG;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GACjD,aAAa,CAcf;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,GAAE,MAAY,iBAYpF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,GAAE,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,IAAW,EACnD,cAAc,GAAE,MAAY,GAC3B,WAAW,CAGb;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/E;AAED,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEpF;AAED,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEhF;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
package/build/ExpoAudio.js
CHANGED
|
@@ -7,6 +7,12 @@ import { resolveSource } from './utils/resolveSource';
|
|
|
7
7
|
export const PLAYBACK_STATUS_UPDATE = 'playbackStatusUpdate';
|
|
8
8
|
export const AUDIO_SAMPLE_UPDATE = 'audioSampleUpdate';
|
|
9
9
|
export const RECORDING_STATUS_UPDATE = 'recordingStatusUpdate';
|
|
10
|
+
// TODO: Temporary solution until we develop a way of overriding prototypes that won't break the lazy loading of the module.
|
|
11
|
+
const replace = AudioModule.AudioPlayer.prototype.replace;
|
|
12
|
+
AudioModule.AudioPlayer.prototype.replace = function (source) {
|
|
13
|
+
return replace.call(this, resolveSource(source));
|
|
14
|
+
};
|
|
15
|
+
// @docsMissing
|
|
10
16
|
export function useAudioPlayer(source = null, updateInterval = 500) {
|
|
11
17
|
const parsedSource = resolveSource(source);
|
|
12
18
|
return useReleasingSharedObject(() => new AudioModule.AudioPlayer(parsedSource, updateInterval), [JSON.stringify(parsedSource)]);
|
|
@@ -16,11 +22,11 @@ export function useAudioPlayerStatus(player) {
|
|
|
16
22
|
return useEvent(player, PLAYBACK_STATUS_UPDATE, currentStatus);
|
|
17
23
|
}
|
|
18
24
|
export function useAudioSampleListener(player, listener) {
|
|
19
|
-
player.setAudioSamplingEnabled(true);
|
|
20
25
|
useEffect(() => {
|
|
21
26
|
if (!player.isAudioSamplingSupported) {
|
|
22
27
|
return;
|
|
23
28
|
}
|
|
29
|
+
player.setAudioSamplingEnabled(true);
|
|
24
30
|
const subscription = player.addListener(AUDIO_SAMPLE_UPDATE, listener);
|
|
25
31
|
return () => {
|
|
26
32
|
subscription.remove();
|
package/build/ExpoAudio.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudio.js","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAsB,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAUrD,OAAO,WAAW,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAC;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AACvD,MAAM,CAAC,MAAM,uBAAuB,GAAG,uBAAuB,CAAC;AAE/D,MAAM,UAAU,cAAc,CAC5B,SAAsB,IAAI,EAC1B,iBAAyB,GAAG;IAE5B,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO,wBAAwB,CAC7B,GAAG,EAAE,CAAC,IAAI,WAAW,CAAC,WAAW,CAAC,YAAY,EAAE,cAAc,CAAC,EAC/D,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAC/B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAmB;IACtD,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACvE,OAAO,QAAQ,CAAC,MAAM,EAAE,sBAAsB,EAAE,aAAa,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAmB,EAAE,QAAqC;IAC/F,
|
|
1
|
+
{"version":3,"file":"ExpoAudio.js","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEvent } from 'expo';\nimport { PermissionResponse, useReleasingSharedObject } from 'expo-modules-core';\nimport { useEffect, useState, useMemo } from 'react';\n\nimport {\n AudioMode,\n AudioSource,\n AudioStatus,\n RecorderState,\n RecordingOptions,\n RecordingStatus,\n} from './Audio.types';\nimport AudioModule from './AudioModule';\nimport { AudioPlayer, AudioRecorder, AudioSample } from './AudioModule.types';\nimport { createRecordingOptions } from './utils/options';\nimport { resolveSource } from './utils/resolveSource';\n\nexport const PLAYBACK_STATUS_UPDATE = 'playbackStatusUpdate';\nexport const AUDIO_SAMPLE_UPDATE = 'audioSampleUpdate';\nexport const RECORDING_STATUS_UPDATE = 'recordingStatusUpdate';\n\n// TODO: Temporary solution until we develop a way of overriding prototypes that won't break the lazy loading of the module.\nconst replace = AudioModule.AudioPlayer.prototype.replace;\nAudioModule.AudioPlayer.prototype.replace = function (source: AudioSource) {\n return replace.call(this, resolveSource(source));\n};\n\n// @docsMissing\nexport function useAudioPlayer(\n source: AudioSource = null,\n updateInterval: number = 500\n): AudioPlayer {\n const parsedSource = resolveSource(source);\n return useReleasingSharedObject(\n () => new AudioModule.AudioPlayer(parsedSource, updateInterval),\n [JSON.stringify(parsedSource)]\n );\n}\n\nexport function useAudioPlayerStatus(player: AudioPlayer): AudioStatus {\n const currentStatus = useMemo(() => player.currentStatus, [player.id]);\n return useEvent(player, PLAYBACK_STATUS_UPDATE, currentStatus);\n}\n\nexport function useAudioSampleListener(player: AudioPlayer, listener: (data: AudioSample) => void) {\n useEffect(() => {\n if (!player.isAudioSamplingSupported) {\n return;\n }\n player.setAudioSamplingEnabled(true);\n const subscription = player.addListener(AUDIO_SAMPLE_UPDATE, listener);\n return () => {\n subscription.remove();\n };\n }, [player.id]);\n}\n\nexport function useAudioRecorder(\n options: RecordingOptions,\n statusListener?: (status: RecordingStatus) => void\n): AudioRecorder {\n const platformOptions = createRecordingOptions(options);\n const recorder = useReleasingSharedObject(() => {\n return new AudioModule.AudioRecorder(platformOptions);\n }, [JSON.stringify(platformOptions)]);\n\n useEffect(() => {\n const subscription = recorder.addListener(RECORDING_STATUS_UPDATE, (status) => {\n statusListener?.(status);\n });\n return () => subscription.remove();\n }, [recorder.id]);\n\n return recorder;\n}\n\nexport function useAudioRecorderState(recorder: AudioRecorder, interval: number = 500) {\n const [state, setState] = useState<RecorderState>(recorder.getStatus());\n\n useEffect(() => {\n const int = setInterval(() => {\n setState(recorder.getStatus());\n }, interval);\n\n return () => clearInterval(int);\n }, [recorder.id]);\n\n return state;\n}\n\n/**\n * Creates an instance of an `AudioPlayer` that doesn't release automatically.\n *\n * > **info** For most use cases you should use the [`useAudioPlayer`](#useaudioplayersource-updateinterval) hook instead. See the [Using the `AudioPlayer` directly](#using-the-audioplayer-directly) section for more details.\n * @param source\n */\nexport function createAudioPlayer(\n source: AudioSource | string | number | null = null,\n updateInterval: number = 500\n): AudioPlayer {\n const parsedSource = resolveSource(source);\n return new AudioModule.AudioPlayer(parsedSource, updateInterval);\n}\n\nexport async function setIsAudioActiveAsync(active: boolean): Promise<void> {\n return await AudioModule.setIsAudioActiveAsync(active);\n}\n\nexport async function setAudioModeAsync(mode: Partial<AudioMode>): Promise<void> {\n return await AudioModule.setAudioModeAsync(mode);\n}\n\nexport async function requestRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.requestRecordingPermissionsAsync();\n}\n\nexport async function getRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.getRecordingPermissionsAsync();\n}\n\nexport { AudioModule };\n"]}
|
package/build/utils/options.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/utils/options.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/utils/options.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB;;;;;;EAqB/D"}
|
package/build/utils/options.js
CHANGED
|
@@ -5,6 +5,7 @@ export function createRecordingOptions(options) {
|
|
|
5
5
|
sampleRate: options.sampleRate,
|
|
6
6
|
numberOfChannels: options.numberOfChannels,
|
|
7
7
|
bitRate: options.bitRate,
|
|
8
|
+
isMeteringEnabled: options.isMeteringEnabled ?? false,
|
|
8
9
|
};
|
|
9
10
|
if (Platform.OS === 'ios') {
|
|
10
11
|
commonOptions = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/utils/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAI7C,MAAM,UAAU,sBAAsB,CAAC,OAAyB;IAC9D,IAAI,aAAa,GAAG;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,OAAO,EAAE,OAAO,CAAC,OAAO;
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/utils/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAI7C,MAAM,UAAU,sBAAsB,CAAC,OAAyB;IAC9D,IAAI,aAAa,GAAG;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,KAAK;KACtD,CAAC;IAEF,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE;QACzB,aAAa,GAAG;YACd,GAAG,aAAa;YAChB,GAAG,OAAO,CAAC,GAAG;SACf,CAAC;KACH;SAAM,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QACpC,aAAa,GAAG;YACd,GAAG,aAAa;YAChB,GAAG,OAAO,CAAC,OAAO;SACnB,CAAC;KACH;IACD,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import { Platform } from 'expo-modules-core';\n\nimport { RecordingOptions } from '../Audio.types';\n\nexport function createRecordingOptions(options: RecordingOptions) {\n let commonOptions = {\n extension: options.extension,\n sampleRate: options.sampleRate,\n numberOfChannels: options.numberOfChannels,\n bitRate: options.bitRate,\n isMeteringEnabled: options.isMeteringEnabled ?? false,\n };\n\n if (Platform.OS === 'ios') {\n commonOptions = {\n ...commonOptions,\n ...options.ios,\n };\n } else if (Platform.OS === 'android') {\n commonOptions = {\n ...commonOptions,\n ...options.android,\n };\n }\n return commonOptions;\n}\n"]}
|
package/ios/AudioModule.swift
CHANGED
|
@@ -91,12 +91,12 @@ public class AudioModule: Module {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
Property("currentTime") { player in
|
|
94
|
-
player.
|
|
94
|
+
player.currentTime
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
Property("duration") { player in
|
|
98
98
|
if player.ref.status == .readyToPlay {
|
|
99
|
-
|
|
99
|
+
player.duration
|
|
100
100
|
} else {
|
|
101
101
|
0.0
|
|
102
102
|
}
|
|
@@ -141,7 +141,7 @@ public class AudioModule: Module {
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
Function("replace") { (player, source: AudioSource) in
|
|
144
|
-
player.
|
|
144
|
+
player.replaceCurrentSource(source: source)
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
Function("pause") { player in
|
|
@@ -159,7 +159,7 @@ public class AudioModule: Module {
|
|
|
159
159
|
AsyncFunction("seekTo") { (player: AudioPlayer, seconds: Double) in
|
|
160
160
|
await player.ref.currentItem?.seek(
|
|
161
161
|
to: CMTime(
|
|
162
|
-
seconds: seconds
|
|
162
|
+
seconds: seconds,
|
|
163
163
|
preferredTimescale: CMTimeScale(NSEC_PER_SEC)
|
|
164
164
|
)
|
|
165
165
|
)
|
package/ios/AudioPlayer.swift
CHANGED
|
@@ -25,9 +25,14 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
25
25
|
private var audioProcessor: AudioTapProcessor?
|
|
26
26
|
private var samplingEnabled = false
|
|
27
27
|
private var tapInstalled = false
|
|
28
|
+
private var shouldInstallAudioTap = false
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
var duration: Double {
|
|
31
|
+
ref.currentItem?.duration.seconds ?? 0.0
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var currentTime: Double {
|
|
35
|
+
ref.currentItem?.currentTime().seconds ?? 0.0
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
init(_ ref: AVPlayer, interval: Double) {
|
|
@@ -65,15 +70,15 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
func currentStatus() -> [String: Any] {
|
|
68
|
-
let
|
|
73
|
+
let currentDuration = ref.status == .readyToPlay ? duration : 0.0
|
|
69
74
|
return [
|
|
70
75
|
"id": id,
|
|
71
|
-
"currentTime":
|
|
76
|
+
"currentTime": currentTime,
|
|
72
77
|
"playbackState": statusToString(status: ref.status),
|
|
73
78
|
"timeControlStatus": timeControlStatusString(status: ref.timeControlStatus),
|
|
74
79
|
"reasonForWaitingToPlay": reasonForWaitingToPlayString(status: ref.reasonForWaitingToPlay),
|
|
75
80
|
"mute": ref.isMuted,
|
|
76
|
-
"duration":
|
|
81
|
+
"duration": currentDuration,
|
|
77
82
|
"playing": ref.timeControlStatus == .playing,
|
|
78
83
|
"loop": isLooping,
|
|
79
84
|
"isLoaded": ref.currentItem?.status == .readyToPlay,
|
|
@@ -93,19 +98,42 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
93
98
|
|
|
94
99
|
private func setupPublisher() {
|
|
95
100
|
ref.publisher(for: \.currentItem?.status)
|
|
96
|
-
.sink { status in
|
|
97
|
-
guard let status else {
|
|
101
|
+
.sink { [weak self] status in
|
|
102
|
+
guard let self, let status else {
|
|
98
103
|
return
|
|
99
104
|
}
|
|
100
105
|
if status == .readyToPlay {
|
|
101
106
|
self.updateStatus(with: [
|
|
102
107
|
"isLoaded": true
|
|
103
108
|
])
|
|
109
|
+
// We can't add the audio tap until the asset has loaded, otherwise the asset track will be empty.
|
|
110
|
+
// This is particularly important after replacing the audio source
|
|
111
|
+
if shouldInstallAudioTap {
|
|
112
|
+
setSamplingEnabled(enabled: shouldInstallAudioTap)
|
|
113
|
+
shouldInstallAudioTap = false
|
|
114
|
+
}
|
|
104
115
|
}
|
|
105
116
|
}
|
|
106
117
|
.store(in: &cancellables)
|
|
107
118
|
}
|
|
108
119
|
|
|
120
|
+
func replaceCurrentSource(source: AudioSource) {
|
|
121
|
+
let wasPlaying = ref.timeControlStatus == .playing
|
|
122
|
+
let wasSamplingEnabled = samplingEnabled
|
|
123
|
+
ref.pause()
|
|
124
|
+
|
|
125
|
+
// Remove the audio tap if it is active
|
|
126
|
+
if samplingEnabled {
|
|
127
|
+
setSamplingEnabled(enabled: false)
|
|
128
|
+
}
|
|
129
|
+
ref.replaceCurrentItem(with: AudioUtils.createAVPlayerItem(from: source))
|
|
130
|
+
shouldInstallAudioTap = wasSamplingEnabled
|
|
131
|
+
|
|
132
|
+
if wasPlaying {
|
|
133
|
+
ref.play()
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
109
137
|
private func playerIsBuffering() -> Bool {
|
|
110
138
|
if ref.timeControlStatus == .playing {
|
|
111
139
|
return false
|
|
@@ -122,8 +150,8 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
122
150
|
}
|
|
123
151
|
|
|
124
152
|
private func installTap() {
|
|
125
|
-
if
|
|
126
|
-
audioProcessor = AudioTapProcessor(
|
|
153
|
+
if !tapInstalled {
|
|
154
|
+
audioProcessor = AudioTapProcessor(player: ref)
|
|
127
155
|
tapInstalled = audioProcessor?.installTap() ?? false
|
|
128
156
|
audioProcessor?.sampleBufferCallback = { [weak self] buffer, frameCount, timestamp in
|
|
129
157
|
guard let self,
|
|
@@ -183,7 +211,7 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
183
211
|
let interval = CMTime(seconds: updateInterval, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
|
|
184
212
|
timeToken = ref.addPeriodicTimeObserver(forInterval: interval, queue: nil) { time in
|
|
185
213
|
self.updateStatus(with: [
|
|
186
|
-
"currentTime": time.seconds
|
|
214
|
+
"currentTime": time.seconds
|
|
187
215
|
])
|
|
188
216
|
}
|
|
189
217
|
}
|
package/ios/AudioRecorder.swift
CHANGED
|
@@ -50,6 +50,9 @@ class AudioRecorder: SharedRef<AVAudioRecorder>, RecordingResultHandler {
|
|
|
50
50
|
ref = AudioUtils.createRecorder(directory: recordingDirectory, with: options)
|
|
51
51
|
ref.delegate = recordingDelegate
|
|
52
52
|
}
|
|
53
|
+
if let isMeteringEnabled = options?.isMeteringEnabled {
|
|
54
|
+
ref.isMeteringEnabled = isMeteringEnabled
|
|
55
|
+
}
|
|
53
56
|
ref.prepareToRecord()
|
|
54
57
|
isPrepared = true
|
|
55
58
|
}
|
package/ios/AudioRecords.swift
CHANGED
package/ios/AudioTapProcessor.h
CHANGED
|
@@ -6,9 +6,9 @@ typedef void (^SampleBufferCallback)(AudioBuffer *audioBuffer, long frameCount,
|
|
|
6
6
|
@interface AudioTapProcessor : NSObject
|
|
7
7
|
|
|
8
8
|
@property (nonatomic, copy) SampleBufferCallback sampleBufferCallback;
|
|
9
|
-
@property (nonatomic, strong)
|
|
9
|
+
@property (nonatomic, strong) AVPlayer *player;
|
|
10
10
|
|
|
11
|
-
- (instancetype)
|
|
11
|
+
- (instancetype)initWithPlayer:(AVPlayer *)player;
|
|
12
12
|
- (bool)installTap;
|
|
13
13
|
- (void)uninstallTap;
|
|
14
14
|
|
package/ios/AudioTapProcessor.m
CHANGED
|
@@ -14,20 +14,20 @@ typedef struct AVAudioTapProcessorContext {
|
|
|
14
14
|
|
|
15
15
|
@implementation AudioTapProcessor
|
|
16
16
|
|
|
17
|
-
- (instancetype)
|
|
17
|
+
- (instancetype)initWithPlayer:(AVPlayer *)player {
|
|
18
18
|
self = [super init];
|
|
19
19
|
if (self) {
|
|
20
|
-
|
|
20
|
+
_player = player;
|
|
21
21
|
}
|
|
22
22
|
return self;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
- (bool)installTap {
|
|
26
|
-
if (!
|
|
26
|
+
if (![_player currentItem]) {
|
|
27
27
|
return false;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
AVAssetTrack *track =
|
|
30
|
+
AVAssetTrack *track = _player.currentItem.tracks.firstObject.assetTrack;
|
|
31
31
|
if (!track) {
|
|
32
32
|
return false;
|
|
33
33
|
}
|
|
@@ -50,7 +50,7 @@ typedef struct AVAudioTapProcessorContext {
|
|
|
50
50
|
if (status == noErr) {
|
|
51
51
|
audioMixInputParameters.audioTapProcessor = audioProcessingTap;
|
|
52
52
|
audioMix.inputParameters = @[audioMixInputParameters];
|
|
53
|
-
[
|
|
53
|
+
[_player.currentItem setAudioMix:audioMix];
|
|
54
54
|
CFRelease(audioProcessingTap);
|
|
55
55
|
} else {
|
|
56
56
|
return false;
|
|
@@ -61,7 +61,7 @@ typedef struct AVAudioTapProcessorContext {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
- (void)uninstallTap {
|
|
64
|
-
[
|
|
64
|
+
[_player.currentItem setAudioMix:nil];
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
#pragma mark - Audio Sample Buffer Callbacks (MTAudioProcessingTapCallbacks)
|
|
@@ -103,8 +103,8 @@ void tapUnprepare(MTAudioProcessingTapRef tap) {
|
|
|
103
103
|
|
|
104
104
|
void tapProcess(MTAudioProcessingTapRef tap, CMItemCount numberFrames, MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut, CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut) {
|
|
105
105
|
AVAudioTapProcessorContext *context = (AVAudioTapProcessorContext *)MTAudioProcessingTapGetStorage(tap);
|
|
106
|
-
if (!context->self) {
|
|
107
|
-
NSLog(@"Audio Processing Tap
|
|
106
|
+
if (!context || !context->self) {
|
|
107
|
+
NSLog(@"Audio Processing Tap storage or context is invalid!");
|
|
108
108
|
return;
|
|
109
109
|
}
|
|
110
110
|
|
|
@@ -114,12 +114,12 @@ void tapProcess(MTAudioProcessingTapRef tap, CMItemCount numberFrames, MTAudioPr
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
OSStatus status = MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, flagsOut, NULL, numberFramesOut);
|
|
117
|
-
if (
|
|
117
|
+
if (status != noErr) {
|
|
118
118
|
NSLog(@"MTAudioProcessingTapGetSourceAudio: %d", (int)status);
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
double seconds = CMTimeGetSeconds([_self->
|
|
122
|
+
double seconds = CMTimeGetSeconds([_self->_player.currentItem currentTime]);
|
|
123
123
|
_self.sampleBufferCallback(&bufferListInOut->mBuffers[0], numberFrames, seconds);
|
|
124
124
|
}
|
|
125
125
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-audio",
|
|
3
3
|
"title": "Expo Audio",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.2",
|
|
5
5
|
"description": "A cross-platform audio library for React Native and Expo apps.",
|
|
6
6
|
"main": "build/index.js",
|
|
7
7
|
"types": "build/index.d.ts",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"react": "*",
|
|
41
41
|
"react-native": "*"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "1955c7d38e69c0eb62df89d516a392ea64db6405"
|
|
44
44
|
}
|
package/src/Audio.types.ts
CHANGED
|
@@ -121,6 +121,10 @@ export enum AudioQuality {
|
|
|
121
121
|
export type BitRateStrategy = 'constant' | 'longTermAverage' | 'variableConstrained' | 'variable';
|
|
122
122
|
|
|
123
123
|
export type RecordingOptions = {
|
|
124
|
+
/**
|
|
125
|
+
* A boolean that determines whether audio level information will be part of the status object under the "metering" key.
|
|
126
|
+
*/
|
|
127
|
+
isMeteringEnabled?: boolean;
|
|
124
128
|
/**
|
|
125
129
|
* The desired file extension.
|
|
126
130
|
*
|
package/src/AudioModule.types.ts
CHANGED
package/src/ExpoAudio.ts
CHANGED
|
@@ -19,6 +19,13 @@ export const PLAYBACK_STATUS_UPDATE = 'playbackStatusUpdate';
|
|
|
19
19
|
export const AUDIO_SAMPLE_UPDATE = 'audioSampleUpdate';
|
|
20
20
|
export const RECORDING_STATUS_UPDATE = 'recordingStatusUpdate';
|
|
21
21
|
|
|
22
|
+
// TODO: Temporary solution until we develop a way of overriding prototypes that won't break the lazy loading of the module.
|
|
23
|
+
const replace = AudioModule.AudioPlayer.prototype.replace;
|
|
24
|
+
AudioModule.AudioPlayer.prototype.replace = function (source: AudioSource) {
|
|
25
|
+
return replace.call(this, resolveSource(source));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// @docsMissing
|
|
22
29
|
export function useAudioPlayer(
|
|
23
30
|
source: AudioSource = null,
|
|
24
31
|
updateInterval: number = 500
|
|
@@ -36,11 +43,11 @@ export function useAudioPlayerStatus(player: AudioPlayer): AudioStatus {
|
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
export function useAudioSampleListener(player: AudioPlayer, listener: (data: AudioSample) => void) {
|
|
39
|
-
player.setAudioSamplingEnabled(true);
|
|
40
46
|
useEffect(() => {
|
|
41
47
|
if (!player.isAudioSamplingSupported) {
|
|
42
48
|
return;
|
|
43
49
|
}
|
|
50
|
+
player.setAudioSamplingEnabled(true);
|
|
44
51
|
const subscription = player.addListener(AUDIO_SAMPLE_UPDATE, listener);
|
|
45
52
|
return () => {
|
|
46
53
|
subscription.remove();
|
package/src/utils/options.ts
CHANGED
|
@@ -8,6 +8,7 @@ export function createRecordingOptions(options: RecordingOptions) {
|
|
|
8
8
|
sampleRate: options.sampleRate,
|
|
9
9
|
numberOfChannels: options.numberOfChannels,
|
|
10
10
|
bitRate: options.bitRate,
|
|
11
|
+
isMeteringEnabled: options.isMeteringEnabled ?? false,
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
if (Platform.OS === 'ios') {
|