@siteed/expo-audio-studio 2.4.1 → 2.5.0

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 (80) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/README.md +25 -0
  3. package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +22 -0
  4. package/android/src/main/java/net/siteed/audiostream/AudioDeviceManager.kt +1501 -0
  5. package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +10 -5
  6. package/android/src/main/java/net/siteed/audiostream/AudioNotificationsManager.kt +27 -25
  7. package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +73 -71
  8. package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +576 -252
  9. package/android/src/main/java/net/siteed/audiostream/Constants.kt +17 -1
  10. package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +419 -155
  11. package/android/src/main/java/net/siteed/audiostream/LogUtils.kt +65 -0
  12. package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +9 -1
  13. package/build/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
  14. package/build/AudioDeviceManager.d.ts +107 -0
  15. package/build/AudioDeviceManager.d.ts.map +1 -0
  16. package/build/AudioDeviceManager.js +493 -0
  17. package/build/AudioDeviceManager.js.map +1 -0
  18. package/build/AudioRecorder.provider.d.ts.map +1 -1
  19. package/build/AudioRecorder.provider.js +3 -0
  20. package/build/AudioRecorder.provider.js.map +1 -1
  21. package/build/ExpoAudioStream.types.d.ts +90 -1
  22. package/build/ExpoAudioStream.types.d.ts.map +1 -1
  23. package/build/ExpoAudioStream.types.js +7 -1
  24. package/build/ExpoAudioStream.types.js.map +1 -1
  25. package/build/ExpoAudioStream.web.d.ts +37 -0
  26. package/build/ExpoAudioStream.web.d.ts.map +1 -1
  27. package/build/ExpoAudioStream.web.js +399 -54
  28. package/build/ExpoAudioStream.web.js.map +1 -1
  29. package/build/ExpoAudioStreamModule.d.ts.map +1 -1
  30. package/build/ExpoAudioStreamModule.js +20 -0
  31. package/build/ExpoAudioStreamModule.js.map +1 -1
  32. package/build/WebRecorder.web.d.ts +63 -10
  33. package/build/WebRecorder.web.d.ts.map +1 -1
  34. package/build/WebRecorder.web.js +277 -68
  35. package/build/WebRecorder.web.js.map +1 -1
  36. package/build/hooks/useAudioDevices.d.ts +14 -0
  37. package/build/hooks/useAudioDevices.d.ts.map +1 -0
  38. package/build/hooks/useAudioDevices.js +151 -0
  39. package/build/hooks/useAudioDevices.js.map +1 -0
  40. package/build/index.d.ts +2 -0
  41. package/build/index.d.ts.map +1 -1
  42. package/build/index.js +4 -0
  43. package/build/index.js.map +1 -1
  44. package/build/useAudioRecorder.d.ts +1 -0
  45. package/build/useAudioRecorder.d.ts.map +1 -1
  46. package/build/useAudioRecorder.js +20 -1
  47. package/build/useAudioRecorder.js.map +1 -1
  48. package/build/utils/BlobFix.d.ts.map +1 -1
  49. package/build/utils/BlobFix.js +2 -2
  50. package/build/utils/BlobFix.js.map +1 -1
  51. package/build/workers/InlineFeaturesExtractor.web.d.ts +1 -1
  52. package/build/workers/InlineFeaturesExtractor.web.d.ts.map +1 -1
  53. package/build/workers/InlineFeaturesExtractor.web.js +27 -26
  54. package/build/workers/InlineFeaturesExtractor.web.js.map +1 -1
  55. package/build/workers/inlineAudioWebWorker.web.d.ts +1 -1
  56. package/build/workers/inlineAudioWebWorker.web.d.ts.map +1 -1
  57. package/build/workers/inlineAudioWebWorker.web.js +25 -1
  58. package/build/workers/inlineAudioWebWorker.web.js.map +1 -1
  59. package/ios/AudioDeviceManager.swift +654 -0
  60. package/ios/AudioStreamManager.swift +964 -760
  61. package/ios/ExpoAudioStreamModule.swift +174 -19
  62. package/ios/Features.swift +1 -1
  63. package/ios/ISSUE_IOS.md +45 -0
  64. package/ios/Logger.swift +13 -1
  65. package/ios/RecordingSettings.swift +12 -0
  66. package/package.json +2 -2
  67. package/src/AudioAnalysis/AudioAnalysis.types.ts +2 -2
  68. package/src/AudioDeviceManager.ts +571 -0
  69. package/src/AudioRecorder.provider.tsx +3 -0
  70. package/src/ExpoAudioStream.types.ts +97 -1
  71. package/src/ExpoAudioStream.web.ts +513 -63
  72. package/src/ExpoAudioStreamModule.ts +23 -0
  73. package/src/WebRecorder.web.ts +346 -81
  74. package/src/hooks/useAudioDevices.ts +180 -0
  75. package/src/index.ts +6 -0
  76. package/src/types/crc-32.d.ts +6 -6
  77. package/src/useAudioRecorder.tsx +27 -1
  78. package/src/utils/BlobFix.ts +6 -4
  79. package/src/workers/InlineFeaturesExtractor.web.tsx +27 -26
  80. package/src/workers/inlineAudioWebWorker.web.tsx +25 -1
@@ -145,7 +145,7 @@ export interface StartRecordingResult {
145
145
  }
146
146
 
147
147
  export interface AudioSessionConfig {
148
- /**
148
+ /**
149
149
  * Audio session category that defines the audio behavior
150
150
  * - 'Ambient': Audio continues with silent switch, mixes with other audio
151
151
  * - 'SoloAmbient': Audio continues with silent switch, interrupts other audio
@@ -219,6 +219,14 @@ export type RecordingInterruptionReason =
219
219
  | 'phoneCallEnded'
220
220
  /** Recording was stopped by the system or another app */
221
221
  | 'recordingStopped'
222
+ /** Recording device was disconnected */
223
+ | 'deviceDisconnected'
224
+ /** Recording switched to default device after disconnection */
225
+ | 'deviceFallback'
226
+ /** A new audio device was connected */
227
+ | 'deviceConnected'
228
+ /** Device switching failed */
229
+ | 'deviceSwitchFailed'
222
230
 
223
231
  // Add new interface for interruption events
224
232
  export interface RecordingInterruptionEvent {
@@ -228,6 +236,48 @@ export interface RecordingInterruptionEvent {
228
236
  isPaused: boolean
229
237
  }
230
238
 
239
+ export interface AudioDeviceCapabilities {
240
+ /** Supported sample rates for the device */
241
+ sampleRates: number[]
242
+ /** Supported channel counts for the device */
243
+ channelCounts: number[]
244
+ /** Supported bit depths for the device */
245
+ bitDepths: number[]
246
+ /** Whether the device supports echo cancellation */
247
+ hasEchoCancellation?: boolean
248
+ /** Whether the device supports noise suppression */
249
+ hasNoiseSuppression?: boolean
250
+ /** Whether the device supports automatic gain control */
251
+ hasAutomaticGainControl?: boolean
252
+ }
253
+
254
+ export interface AudioDevice {
255
+ /** Unique identifier for the device */
256
+ id: string
257
+ /** Human-readable name of the device */
258
+ name: string
259
+ /** Device type (builtin_mic, bluetooth, etc.) */
260
+ type: string
261
+ /** Whether this is the system default device */
262
+ isDefault: boolean
263
+ /** Audio capabilities for the device */
264
+ capabilities: AudioDeviceCapabilities
265
+ /** Whether the device is currently available */
266
+ isAvailable: boolean
267
+ }
268
+
269
+ /** Defines how recording should behave when a device becomes unavailable */
270
+ export const DeviceDisconnectionBehavior = {
271
+ /** Pause recording when device disconnects */
272
+ PAUSE: 'pause',
273
+ /** Switch to default device and continue recording */
274
+ FALLBACK: 'fallback',
275
+ } as const
276
+
277
+ /** Type for DeviceDisconnectionBehavior values */
278
+ export type DeviceDisconnectionBehaviorType =
279
+ (typeof DeviceDisconnectionBehavior)[keyof typeof DeviceDisconnectionBehavior]
280
+
231
281
  export interface RecordingConfig {
232
282
  /** Sample rate for recording in Hz (16000, 44100, or 48000) */
233
283
  sampleRate?: SampleRate
@@ -294,6 +344,12 @@ export interface RecordingConfig {
294
344
  outputDirectory?: string // If not provided, uses default app directory
295
345
  /** Optional filename for the recording (uses UUID if not provided) */
296
346
  filename?: string // If not provided, uses UUID
347
+
348
+ /** ID of the device to use for recording (if not specified, uses default) */
349
+ deviceId?: string
350
+
351
+ /** How to handle device disconnection during recording */
352
+ deviceDisconnectionBehavior?: DeviceDisconnectionBehaviorType
297
353
  }
298
354
 
299
355
  export interface NotificationConfig {
@@ -420,6 +476,46 @@ export interface ExtractedAudioData {
420
476
  }
421
477
 
422
478
  export interface UseAudioRecorderState {
479
+ /**
480
+ * Prepares recording with the specified configuration without starting it.
481
+ *
482
+ * This method eliminates the latency between calling startRecording and the actual recording beginning.
483
+ * It pre-initializes all audio resources, requests permissions, and sets up audio sessions in advance,
484
+ * allowing for true zero-latency recording start when startRecording is called later.
485
+ *
486
+ * Technical benefits:
487
+ * - Eliminates audio pipeline initialization delay (50-300ms depending on platform)
488
+ * - Pre-allocates audio buffers to avoid memory allocation during recording start
489
+ * - Initializes audio hardware in advance (particularly important on iOS)
490
+ * - Requests and verifies permissions before the critical recording moment
491
+ *
492
+ * Use this method when:
493
+ * - You need zero-latency recording start (e.g., voice commands, musical applications)
494
+ * - You're building time-sensitive applications where missing initial audio would be problematic
495
+ * - You want to prepare resources during app initialization, screen loading, or preceding user interaction
496
+ * - You need to ensure recording starts reliably and instantly on all platforms
497
+ *
498
+ * @param config - The recording configuration, identical to what you would pass to startRecording
499
+ * @returns A promise that resolves when preparation is complete
500
+ *
501
+ * @example
502
+ * // Prepare during component mounting
503
+ * useEffect(() => {
504
+ * prepareRecording({
505
+ * sampleRate: 44100,
506
+ * channels: 1,
507
+ * encoding: 'pcm_16bit',
508
+ * });
509
+ * }, []);
510
+ *
511
+ * // Later when user taps record button, it starts with zero latency
512
+ * const handleRecordPress = () => startRecording({
513
+ * sampleRate: 44100,
514
+ * channels: 1,
515
+ * encoding: 'pcm_16bit',
516
+ * });
517
+ */
518
+ prepareRecording: (_: RecordingConfig) => Promise<void>
423
519
  /** Starts recording with the specified configuration */
424
520
  startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>
425
521
  /** Stops the current recording and returns the recording data */