@edkimmel/expo-audio-stream 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/NATIVE_EVENTS.md +60 -6
  2. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  4. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  5. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  6. package/android/.gradle/8.9/gc.properties +0 -0
  7. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  8. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  9. package/android/.gradle/vcs-1/gc.properties +0 -0
  10. package/android/src/main/java/expo/modules/audiostream/AudioEffectsManager.kt +6 -11
  11. package/android/src/main/java/expo/modules/audiostream/AudioRecorderManager.kt +23 -6
  12. package/android/src/main/java/expo/modules/audiostream/CommunicationAudioManager.kt +155 -0
  13. package/android/src/main/java/expo/modules/audiostream/Constants.kt +1 -0
  14. package/android/src/main/java/expo/modules/audiostream/ExpoPlayAudioStreamModule.kt +12 -3
  15. package/android/src/main/java/expo/modules/audiostream/pipeline/AudioPipeline.kt +12 -9
  16. package/build/events.d.ts +22 -0
  17. package/build/events.d.ts.map +1 -1
  18. package/build/events.js +18 -0
  19. package/build/events.js.map +1 -1
  20. package/build/index.d.ts +2 -0
  21. package/build/index.d.ts.map +1 -1
  22. package/build/index.js +21 -10
  23. package/build/index.js.map +1 -1
  24. package/build/types.d.ts +13 -0
  25. package/build/types.d.ts.map +1 -1
  26. package/build/types.js.map +1 -1
  27. package/ios/ExpoPlayAudioStreamModule.swift +29 -12
  28. package/ios/Microphone.swift +153 -197
  29. package/ios/MicrophoneDataDelegate.swift +10 -1
  30. package/ios/SharedAudioEngine.swift +18 -0
  31. package/package.json +1 -1
  32. package/src/events.ts +28 -0
  33. package/src/index.ts +29 -26
  34. package/src/types.ts +13 -0
package/build/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import ExpoPlayAudioStreamModule from "./ExpoPlayAudioStreamModule";
2
2
  import { EncodingTypes, PlaybackModes, } from "./types";
3
- import { addAudioEventListener, AudioEvents, subscribeToEvent, } from "./events";
3
+ import { addAudioEventListener, addMicrophoneErrorListener, AudioEvents, subscribeToEvent, } from "./events";
4
4
  export class ExpoPlayAudioStream {
5
5
  /**
6
6
  * Destroys the audio stream module, cleaning up all resources.
@@ -20,19 +20,21 @@ export class ExpoPlayAudioStream {
20
20
  let subscription;
21
21
  try {
22
22
  const { onAudioStream, onError, ...options } = recordingConfig;
23
- if ((onAudioStream && typeof onAudioStream == "function") ||
24
- (onError && typeof onError == "function")) {
25
- subscription = addAudioEventListener(async (event) => {
26
- const { fileUri, deltaSize, totalSize, position, encoded, soundLevel, frequencyBands, error, errorMessage, } = event;
27
- if (error) {
28
- onError?.({ code: error, message: errorMessage ?? "" });
23
+ const subscriptions = [];
24
+ if (onAudioStream && typeof onAudioStream === "function") {
25
+ subscriptions.push(addAudioEventListener(async (event) => {
26
+ const { fileUri, deltaSize, totalSize, position, encoded, soundLevel, frequencyBands, error } = event;
27
+ // Only suppress AudioData error events when onError is wired up — the
28
+ // MicrophoneError subscription will handle them. Without onError (old
29
+ // integration or old native binary), fall through so the missing-encoded
30
+ // path below preserves the pre-v0.6.0 behavior.
31
+ if (error && onError)
29
32
  return;
30
- }
31
33
  if (!encoded) {
32
34
  console.error(`[ExpoPlayAudioStream] Encoded audio data is missing`);
33
35
  throw new Error("Encoded audio data is missing");
34
36
  }
35
- onAudioStream?.({
37
+ onAudioStream({
36
38
  data: encoded,
37
39
  position,
38
40
  fileUri,
@@ -41,7 +43,15 @@ export class ExpoPlayAudioStream {
41
43
  soundLevel,
42
44
  frequencyBands,
43
45
  });
44
- });
46
+ }));
47
+ }
48
+ if (onError && typeof onError === "function") {
49
+ subscriptions.push(addMicrophoneErrorListener((event) => {
50
+ onError(event);
51
+ }));
52
+ }
53
+ if (subscriptions.length > 0) {
54
+ subscription = { remove: () => subscriptions.forEach((s) => s.remove()) };
45
55
  }
46
56
  const result = await ExpoPlayAudioStreamModule.startMicrophone(options);
47
57
  return { recordingResult: result, subscription };
@@ -142,6 +152,7 @@ export class ExpoPlayAudioStream {
142
152
  }
143
153
  }
144
154
  export { AudioEvents, EncodingTypes, PlaybackModes, };
155
+ export { addMicrophoneErrorListener } from "./events";
145
156
  // Export native audio pipeline V3
146
157
  export { Pipeline } from "./pipeline";
147
158
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { EventSubscription } from \"expo-modules-core\";\nimport ExpoPlayAudioStreamModule from \"./ExpoPlayAudioStreamModule\";\n\n// Type alias for backwards compatibility\ntype Subscription = EventSubscription;\nimport {\n AudioDataEvent,\n AudioRecording,\n RecordingConfig,\n StartRecordingResult,\n PlaybackMode,\n Encoding,\n EncodingTypes,\n FrequencyBands,\n PlaybackModes,\n // Audio jitter buffer types\n IAudioBufferConfig,\n IAudioPlayPayload,\n IAudioFrame,\n BufferHealthState,\n IBufferHealthMetrics,\n IAudioBufferManager,\n IFrameProcessor,\n IQualityMonitor,\n BufferedStreamConfig,\n SmartBufferConfig,\n SmartBufferMode,\n NetworkConditions,\n} from \"./types\";\n\nimport {\n addAudioEventListener,\n AudioEventPayload,\n AudioEvents,\n subscribeToEvent,\n DeviceReconnectedReason,\n DeviceReconnectedEventPayload,\n} from \"./events\";\n\nexport class ExpoPlayAudioStream {\n /**\n * Destroys the audio stream module, cleaning up all resources.\n * This should be called when the module is no longer needed.\n * It will reset all internal state and release audio resources.\n */\n static async destroy() {\n await ExpoPlayAudioStreamModule.destroy();\n }\n\n /**\n * Starts microphone streaming.\n * @param {RecordingConfig} recordingConfig - The recording configuration.\n * @returns {Promise<{recordingResult: StartRecordingResult, subscription: Subscription}>} A promise that resolves to an object containing the recording result and a subscription to audio events.\n * @throws {Error} If the recording fails to start.\n */\n static async startMicrophone(recordingConfig: RecordingConfig): Promise<{\n recordingResult: StartRecordingResult;\n subscription?: Subscription;\n }> {\n let subscription: Subscription | undefined;\n try {\n const { onAudioStream, onError, ...options } = recordingConfig;\n\n if (\n (onAudioStream && typeof onAudioStream == \"function\") ||\n (onError && typeof onError == \"function\")\n ) {\n subscription = addAudioEventListener(\n async (event: AudioEventPayload) => {\n const {\n fileUri,\n deltaSize,\n totalSize,\n position,\n encoded,\n soundLevel,\n frequencyBands,\n error,\n errorMessage,\n } = event;\n if (error) {\n onError?.({ code: error, message: errorMessage ?? \"\" });\n return;\n }\n if (!encoded) {\n console.error(\n `[ExpoPlayAudioStream] Encoded audio data is missing`\n );\n throw new Error(\"Encoded audio data is missing\");\n }\n onAudioStream?.({\n data: encoded,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n soundLevel,\n frequencyBands,\n });\n }\n );\n }\n\n const result = await ExpoPlayAudioStreamModule.startMicrophone(options);\n\n return { recordingResult: result, subscription };\n } catch (error) {\n console.error(error);\n subscription?.remove();\n throw new Error(`Failed to start recording: ${error}`);\n }\n }\n\n /**\n * Stops the current microphone streaming.\n * @returns {Promise<void>}\n * @throws {Error} If the microphone streaming fails to stop.\n */\n static async stopMicrophone(): Promise<AudioRecording | null> {\n try {\n return await ExpoPlayAudioStreamModule.stopMicrophone();\n } catch (error) {\n console.error(error);\n throw new Error(`Failed to stop mic stream: ${error}`);\n }\n }\n\n /**\n * Subscribes to audio events emitted during recording/streaming.\n * @param onMicrophoneStream - Callback function that will be called when audio data is received.\n * @returns {Subscription} A subscription object that can be used to unsubscribe from the events\n */\n static subscribeToAudioEvents(\n onMicrophoneStream: (event: AudioDataEvent) => Promise<void>\n ): Subscription {\n return addAudioEventListener(async (event: AudioEventPayload) => {\n const { fileUri, deltaSize, totalSize, position, encoded, soundLevel, frequencyBands } =\n event;\n if (!encoded) {\n console.error(`[ExpoPlayAudioStream] Encoded audio data is missing`);\n throw new Error(\"Encoded audio data is missing\");\n }\n onMicrophoneStream?.({\n data: encoded,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n soundLevel,\n frequencyBands,\n });\n });\n }\n\n /**\n * Subscribes to events emitted by the audio stream module, for advanced use cases.\n * @param eventName - The name of the event to subscribe to.\n * @param onEvent - Callback function that will be called when the event is emitted.\n * @returns {Subscription} A subscription object that can be used to unsubscribe from the events.\n */\n static subscribe<T extends unknown>(\n eventName: string,\n onEvent: (event: T | undefined) => Promise<void>\n ): Subscription {\n return subscribeToEvent(eventName, onEvent);\n }\n\n /**\n * Prompts the user to select the microphone mode.\n * @returns {Promise<void>}\n * @throws {Error} If the microphone mode fails to prompt.\n */\n static promptMicrophoneModes() {\n ExpoPlayAudioStreamModule.promptMicrophoneModes();\n }\n\n /**\n * Toggles the silence state of the microphone.\n * @returns {Promise<void>}\n * @throws {Error} If the microphone fails to toggle silence.\n */\n static toggleSilence(isSilent: boolean) {\n ExpoPlayAudioStreamModule.toggleSilence(isSilent);\n }\n\n /**\n * Requests microphone permission from the user.\n * @returns {Promise<{granted: boolean, canAskAgain?: boolean, status?: string}>} A promise that resolves to the permission result.\n */\n static async requestPermissionsAsync(): Promise<{\n granted: boolean;\n canAskAgain?: boolean;\n status?: string;\n }> {\n try {\n return await ExpoPlayAudioStreamModule.requestPermissionsAsync();\n } catch (error) {\n console.error(error);\n throw new Error(`Failed to request permissions: ${error}`);\n }\n }\n\n /**\n * Gets the current microphone permission status.\n * @returns {Promise<{granted: boolean, canAskAgain?: boolean, status?: string}>} A promise that resolves to the permission status.\n */\n static async getPermissionsAsync(): Promise<{\n granted: boolean;\n canAskAgain?: boolean;\n status?: string;\n }> {\n try {\n return await ExpoPlayAudioStreamModule.getPermissionsAsync();\n } catch (error) {\n console.error(error);\n throw new Error(`Failed to get permissions: ${error}`);\n }\n }\n}\n\nexport {\n AudioDataEvent,\n DeviceReconnectedReason,\n DeviceReconnectedEventPayload,\n AudioRecording,\n RecordingConfig,\n StartRecordingResult,\n AudioEvents,\n PlaybackMode,\n Encoding,\n EncodingTypes,\n FrequencyBands,\n PlaybackModes,\n // Audio jitter buffer types\n IAudioBufferConfig,\n IAudioPlayPayload,\n IAudioFrame,\n BufferHealthState,\n IBufferHealthMetrics,\n IAudioBufferManager,\n IFrameProcessor,\n IQualityMonitor,\n BufferedStreamConfig,\n SmartBufferConfig,\n SmartBufferMode,\n NetworkConditions,\n};\n\n// Re-export Subscription type for backwards compatibility\nexport type { EventSubscription } from \"expo-modules-core\";\nexport type { Subscription } from \"./events\";\n\n// Export native audio pipeline V3\nexport { Pipeline } from \"./pipeline\";\nexport type {\n ConnectPipelineOptions,\n ConnectPipelineResult,\n PushPipelineAudioOptions,\n InvalidatePipelineTurnOptions,\n PipelineState,\n PipelineEventMap,\n PipelineEventName,\n PipelineBufferTelemetry,\n PipelineTelemetry,\n PipelineStateChangedEvent,\n PipelinePlaybackStartedEvent,\n PipelineErrorEvent,\n PipelineZombieDetectedEvent,\n PipelineUnderrunEvent,\n PipelineDrainedEvent,\n PipelinePlaybackStoppedEvent,\n PipelineAudioFocusLostEvent,\n PipelineAudioFocusResumedEvent,\n} from \"./pipeline\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { EventSubscription } from \"expo-modules-core\";\nimport ExpoPlayAudioStreamModule from \"./ExpoPlayAudioStreamModule\";\n\n// Type alias for backwards compatibility\ntype Subscription = EventSubscription;\nimport {\n AudioDataEvent,\n AudioRecording,\n RecordingConfig,\n StartRecordingResult,\n PlaybackMode,\n Encoding,\n EncodingTypes,\n FrequencyBands,\n PlaybackModes,\n // Audio jitter buffer types\n IAudioBufferConfig,\n IAudioPlayPayload,\n IAudioFrame,\n BufferHealthState,\n IBufferHealthMetrics,\n IAudioBufferManager,\n IFrameProcessor,\n IQualityMonitor,\n BufferedStreamConfig,\n SmartBufferConfig,\n SmartBufferMode,\n NetworkConditions,\n} from \"./types\";\n\nimport {\n addAudioEventListener,\n addMicrophoneErrorListener,\n AudioEventPayload,\n AudioEvents,\n subscribeToEvent,\n DeviceReconnectedReason,\n DeviceReconnectedEventPayload,\n} from \"./events\";\n\nexport class ExpoPlayAudioStream {\n /**\n * Destroys the audio stream module, cleaning up all resources.\n * This should be called when the module is no longer needed.\n * It will reset all internal state and release audio resources.\n */\n static async destroy() {\n await ExpoPlayAudioStreamModule.destroy();\n }\n\n /**\n * Starts microphone streaming.\n * @param {RecordingConfig} recordingConfig - The recording configuration.\n * @returns {Promise<{recordingResult: StartRecordingResult, subscription: Subscription}>} A promise that resolves to an object containing the recording result and a subscription to audio events.\n * @throws {Error} If the recording fails to start.\n */\n static async startMicrophone(recordingConfig: RecordingConfig): Promise<{\n recordingResult: StartRecordingResult;\n subscription?: Subscription;\n }> {\n let subscription: Subscription | undefined;\n try {\n const { onAudioStream, onError, ...options } = recordingConfig;\n\n const subscriptions: EventSubscription[] = [];\n\n if (onAudioStream && typeof onAudioStream === \"function\") {\n subscriptions.push(\n addAudioEventListener(async (event: AudioEventPayload) => {\n const { fileUri, deltaSize, totalSize, position, encoded, soundLevel, frequencyBands, error } = event;\n // Only suppress AudioData error events when onError is wired up — the\n // MicrophoneError subscription will handle them. Without onError (old\n // integration or old native binary), fall through so the missing-encoded\n // path below preserves the pre-v0.6.0 behavior.\n if (error && onError) return;\n if (!encoded) {\n console.error(`[ExpoPlayAudioStream] Encoded audio data is missing`);\n throw new Error(\"Encoded audio data is missing\");\n }\n onAudioStream({\n data: encoded,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n soundLevel,\n frequencyBands,\n });\n })\n );\n }\n\n if (onError && typeof onError === \"function\") {\n subscriptions.push(\n addMicrophoneErrorListener((event) => {\n onError(event);\n })\n );\n }\n\n if (subscriptions.length > 0) {\n subscription = { remove: () => subscriptions.forEach((s) => s.remove()) };\n }\n\n const result = await ExpoPlayAudioStreamModule.startMicrophone(options);\n\n return { recordingResult: result, subscription };\n } catch (error) {\n console.error(error);\n subscription?.remove();\n throw new Error(`Failed to start recording: ${error}`);\n }\n }\n\n /**\n * Stops the current microphone streaming.\n * @returns {Promise<void>}\n * @throws {Error} If the microphone streaming fails to stop.\n */\n static async stopMicrophone(): Promise<AudioRecording | null> {\n try {\n return await ExpoPlayAudioStreamModule.stopMicrophone();\n } catch (error) {\n console.error(error);\n throw new Error(`Failed to stop mic stream: ${error}`);\n }\n }\n\n /**\n * Subscribes to audio events emitted during recording/streaming.\n * @param onMicrophoneStream - Callback function that will be called when audio data is received.\n * @returns {Subscription} A subscription object that can be used to unsubscribe from the events\n */\n static subscribeToAudioEvents(\n onMicrophoneStream: (event: AudioDataEvent) => Promise<void>\n ): Subscription {\n return addAudioEventListener(async (event: AudioEventPayload) => {\n const { fileUri, deltaSize, totalSize, position, encoded, soundLevel, frequencyBands } =\n event;\n if (!encoded) {\n console.error(`[ExpoPlayAudioStream] Encoded audio data is missing`);\n throw new Error(\"Encoded audio data is missing\");\n }\n onMicrophoneStream?.({\n data: encoded,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n soundLevel,\n frequencyBands,\n });\n });\n }\n\n /**\n * Subscribes to events emitted by the audio stream module, for advanced use cases.\n * @param eventName - The name of the event to subscribe to.\n * @param onEvent - Callback function that will be called when the event is emitted.\n * @returns {Subscription} A subscription object that can be used to unsubscribe from the events.\n */\n static subscribe<T extends unknown>(\n eventName: string,\n onEvent: (event: T | undefined) => Promise<void>\n ): Subscription {\n return subscribeToEvent(eventName, onEvent);\n }\n\n /**\n * Prompts the user to select the microphone mode.\n * @returns {Promise<void>}\n * @throws {Error} If the microphone mode fails to prompt.\n */\n static promptMicrophoneModes() {\n ExpoPlayAudioStreamModule.promptMicrophoneModes();\n }\n\n /**\n * Toggles the silence state of the microphone.\n * @returns {Promise<void>}\n * @throws {Error} If the microphone fails to toggle silence.\n */\n static toggleSilence(isSilent: boolean) {\n ExpoPlayAudioStreamModule.toggleSilence(isSilent);\n }\n\n /**\n * Requests microphone permission from the user.\n * @returns {Promise<{granted: boolean, canAskAgain?: boolean, status?: string}>} A promise that resolves to the permission result.\n */\n static async requestPermissionsAsync(): Promise<{\n granted: boolean;\n canAskAgain?: boolean;\n status?: string;\n }> {\n try {\n return await ExpoPlayAudioStreamModule.requestPermissionsAsync();\n } catch (error) {\n console.error(error);\n throw new Error(`Failed to request permissions: ${error}`);\n }\n }\n\n /**\n * Gets the current microphone permission status.\n * @returns {Promise<{granted: boolean, canAskAgain?: boolean, status?: string}>} A promise that resolves to the permission status.\n */\n static async getPermissionsAsync(): Promise<{\n granted: boolean;\n canAskAgain?: boolean;\n status?: string;\n }> {\n try {\n return await ExpoPlayAudioStreamModule.getPermissionsAsync();\n } catch (error) {\n console.error(error);\n throw new Error(`Failed to get permissions: ${error}`);\n }\n }\n}\n\nexport {\n AudioDataEvent,\n DeviceReconnectedReason,\n DeviceReconnectedEventPayload,\n AudioRecording,\n RecordingConfig,\n StartRecordingResult,\n AudioEvents,\n PlaybackMode,\n Encoding,\n EncodingTypes,\n FrequencyBands,\n PlaybackModes,\n // Audio jitter buffer types\n IAudioBufferConfig,\n IAudioPlayPayload,\n IAudioFrame,\n BufferHealthState,\n IBufferHealthMetrics,\n IAudioBufferManager,\n IFrameProcessor,\n IQualityMonitor,\n BufferedStreamConfig,\n SmartBufferConfig,\n SmartBufferMode,\n NetworkConditions,\n};\n\n// Re-export Subscription type for backwards compatibility\nexport type { EventSubscription } from \"expo-modules-core\";\nexport type { Subscription } from \"./events\";\nexport { addMicrophoneErrorListener } from \"./events\";\nexport type { MicrophoneErrorEventPayload } from \"./events\";\n\n// Export native audio pipeline V3\nexport { Pipeline } from \"./pipeline\";\nexport type {\n ConnectPipelineOptions,\n ConnectPipelineResult,\n PushPipelineAudioOptions,\n InvalidatePipelineTurnOptions,\n PipelineState,\n PipelineEventMap,\n PipelineEventName,\n PipelineBufferTelemetry,\n PipelineTelemetry,\n PipelineStateChangedEvent,\n PipelinePlaybackStartedEvent,\n PipelineErrorEvent,\n PipelineZombieDetectedEvent,\n PipelineUnderrunEvent,\n PipelineDrainedEvent,\n PipelinePlaybackStoppedEvent,\n PipelineAudioFocusLostEvent,\n PipelineAudioFocusResumedEvent,\n} from \"./pipeline\";\n"]}
package/build/types.d.ts CHANGED
@@ -113,6 +113,19 @@ export interface RecordingConfig {
113
113
  export interface MicrophoneErrorEvent {
114
114
  code: string;
115
115
  message: string;
116
+ /**
117
+ * True when the recording session has stopped and the caller must call
118
+ * stopMicrophone() and reconnect to resume. False for transient conditions
119
+ * where recording continues (READ_ERROR on iOS) or the library will
120
+ * auto-recover (INTERRUPTED + autoResuming: true).
121
+ */
122
+ isFatal: boolean;
123
+ /**
124
+ * True only when code is INTERRUPTED — the library is waiting for the
125
+ * system to return the audio session and will reinstall the tap
126
+ * automatically. Always false when isFatal is true.
127
+ */
128
+ autoResuming: boolean;
116
129
  }
117
130
  export interface Chunk {
118
131
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE,SAAS;IAClB,gBAAgB,EAAE,iBAAiB;IACnC,YAAY,EAAE,cAAc;CACpB,CAAC;AAgCX,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;CACd,CAAC","sourcesContent":["export type RecordingEncodingType =\n | 'pcm_32bit'\n | 'pcm_16bit'\n | 'pcm_8bit';\nexport type SampleRate = 16000 | 24000 | 44100 | 48000;\nexport type BitDepth = 8 | 16 | 32;\n\nexport const PlaybackModes = {\n REGULAR: 'regular',\n VOICE_PROCESSING: 'voiceProcessing',\n CONVERSATION: 'conversation',\n} as const;\n/**\n * Defines different playback modes for audio processing\n */\nexport type PlaybackMode =\n (typeof PlaybackModes)[keyof typeof PlaybackModes];\n\n/**\n * Configuration for buffered audio streaming\n */\nexport interface BufferedStreamConfig {\n /**\n * Turn ID for queue management\n */\n turnId: string;\n\n /**\n * Audio encoding format\n */\n encoding?: Encoding;\n\n /**\n * Buffer configuration options\n */\n bufferConfig?: Partial<IAudioBufferConfig>;\n\n /**\n * Callback for buffer health updates\n */\n onBufferHealth?: (metrics: IBufferHealthMetrics) => void;\n}\n\nexport const EncodingTypes = {\n PCM_F32LE: 'pcm_f32le',\n PCM_S16LE: 'pcm_s16le',\n} as const;\n\n/**\n * Defines different encoding formats for audio data\n */\nexport type Encoding =\n (typeof EncodingTypes)[keyof typeof EncodingTypes];\n\n/** RMS energy per frequency band, range [0, 1]. */\nexport interface FrequencyBands {\n low: number;\n mid: number;\n high: number;\n}\n\n/** Crossover frequency configuration for band analysis. */\nexport interface FrequencyBandConfig {\n /** Low/mid crossover in Hz (default 300). */\n lowCrossoverHz?: number;\n /** Mid/high crossover in Hz (default 2000). */\n highCrossoverHz?: number;\n}\n\n/**\n * Smart buffering mode options\n */\nexport type SmartBufferMode =\n | 'conservative'\n | 'balanced'\n | 'aggressive'\n | 'adaptive';\n\n/**\n * Network condition indicators for smart buffering\n */\nexport interface NetworkConditions {\n latency?: number; // Round-trip time in ms\n jitter?: number; // Network jitter in ms\n packetLoss?: number; // Packet loss percentage (0-100)\n bandwidth?: number; // Available bandwidth estimate\n}\n\n/**\n * Smart buffering configuration\n */\nexport interface SmartBufferConfig {\n mode: SmartBufferMode;\n networkConditions?: NetworkConditions;\n adaptiveThresholds?: {\n highLatencyMs?: number; // Threshold to enable aggressive buffering\n highJitterMs?: number; // Threshold to increase buffer size\n packetLossPercent?: number; // Threshold to enable buffering\n };\n}\n\nexport interface StartRecordingResult {\n fileUri: string;\n mimeType: string;\n channels?: number;\n bitDepth?: BitDepth;\n sampleRate?: SampleRate;\n}\n\nexport interface AudioDataEvent {\n data: string | Float32Array;\n data16kHz?: string | Float32Array;\n position: number;\n fileUri: string;\n eventDataSize: number;\n totalSize: number;\n soundLevel?: number;\n /** Frequency band RMS energy, present when recording is active. */\n frequencyBands?: FrequencyBands;\n}\n\nexport interface RecordingConfig {\n sampleRate?: SampleRate; // Sample rate for recording\n channels?: 1 | 2; // 1 or 2 (MONO or STEREO)\n encoding?: RecordingEncodingType; // Encoding type for the recording\n interval?: number; // Interval in milliseconds at which to emit recording data\n\n // Optional parameters for audio processing\n enableProcessing?: boolean; // Boolean to enable/disable audio processing (default is false)\n pointsPerSecond?: number; // Number of data points to extract per second of audio (default is 1000)\n onAudioStream?: (event: AudioDataEvent) => Promise<void>; // Callback function to handle audio stream\n /** Fired when the native layer reports a mid-recording error (e.g. system\n * interruption like Siri or a phone call). The consumer should treat the\n * recording session as terminated and clean up. */\n onError?: (event: MicrophoneErrorEvent) => void;\n /** Optional frequency band crossover configuration. */\n frequencyBandConfig?: FrequencyBandConfig;\n}\n\nexport interface MicrophoneErrorEvent {\n code: string;\n message: string;\n}\n\nexport interface Chunk {\n text: string;\n timestamp: [number, number | null];\n}\n\nexport interface TranscriberData {\n id: string;\n isBusy: boolean;\n text: string;\n startTime: number;\n endTime: number;\n chunks: Chunk[];\n}\n\nexport interface AudioRecording {\n fileUri: string;\n filename: string;\n durationMs: number;\n size: number;\n channels: number;\n bitDepth: BitDepth;\n sampleRate: SampleRate;\n mimeType: string;\n transcripts?: TranscriberData[];\n wavPCMData?: Float32Array; // Full PCM data for the recording in WAV format (only on web, for native use the fileUri)\n}\n\n// Audio Jitter Buffer Types\n\n/**\n * Configuration for audio buffer management\n */\nexport interface IAudioBufferConfig {\n targetBufferMs: number; // Target buffer size in milliseconds\n minBufferMs: number; // Minimum buffer size before underrun handling\n maxBufferMs: number; // Maximum buffer size before overrun handling\n frameIntervalMs: number; // Expected frame interval in milliseconds\n}\n\n/**\n * Audio payload for playback containing base64 encoded audio data\n */\nexport interface IAudioPlayPayload {\n audioData: string; // Base64 encoded PCM audio data\n isFirst?: boolean; // True if this is the first chunk in a stream\n isFinal?: boolean; // True if this is the final chunk in a stream\n}\n\n/**\n * Processed audio frame with metadata\n */\nexport interface IAudioFrame {\n sequenceNumber: number; // Sequential frame number\n data: IAudioPlayPayload; // Original audio payload\n duration: number; // Estimated frame duration in milliseconds\n timestamp: number; // Frame timestamp when processed\n}\n\n/**\n * Buffer health states for quality monitoring\n */\nexport type BufferHealthState =\n | 'idle'\n | 'healthy'\n | 'degraded'\n | 'critical';\n\n/**\n * Comprehensive buffer health and quality metrics\n */\nexport interface IBufferHealthMetrics {\n currentBufferMs: number; // Current buffer level in milliseconds\n targetBufferMs: number; // Target buffer level in milliseconds\n underrunCount: number; // Total number of buffer underruns\n overrunCount: number; // Total number of buffer overruns\n averageJitter: number; // Average network jitter in milliseconds\n bufferHealthState: BufferHealthState; // Current buffer health assessment\n adaptiveAdjustmentsCount: number; // Number of adaptive adjustments made\n}\n\n/**\n * Interface for audio buffer management\n */\nexport interface IAudioBufferManager {\n enqueueFrames(audioData: IAudioPlayPayload): void;\n startPlayback(): void;\n stopPlayback(): void;\n isPlaying(): boolean;\n getHealthMetrics(): IBufferHealthMetrics;\n updateConfig(config: Partial<IAudioBufferConfig>): void;\n applyAdaptiveAdjustments(): void;\n destroy(): void;\n getCurrentBufferMs(): number;\n}\n\n/**\n * Interface for frame processing\n */\nexport interface IFrameProcessor {\n parseChunk(payload: IAudioPlayPayload): IAudioFrame[];\n reset(): void;\n}\n\n/**\n * Interface for quality monitoring\n */\nexport interface IQualityMonitor {\n recordFrameArrival(timestamp: number): void;\n recordUnderrun(): void;\n recordOverrun(): void;\n updateBufferLevel(bufferMs: number): void;\n getMetrics(): IBufferHealthMetrics;\n getBufferHealthState(\n isPlaying: boolean,\n currentLatencyMs: number\n ): BufferHealthState;\n getRecommendedAdjustment(): number;\n reset(): void;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE,SAAS;IAClB,gBAAgB,EAAE,iBAAiB;IACnC,YAAY,EAAE,cAAc;CACpB,CAAC;AAgCX,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;CACd,CAAC","sourcesContent":["export type RecordingEncodingType =\n | 'pcm_32bit'\n | 'pcm_16bit'\n | 'pcm_8bit';\nexport type SampleRate = 16000 | 24000 | 44100 | 48000;\nexport type BitDepth = 8 | 16 | 32;\n\nexport const PlaybackModes = {\n REGULAR: 'regular',\n VOICE_PROCESSING: 'voiceProcessing',\n CONVERSATION: 'conversation',\n} as const;\n/**\n * Defines different playback modes for audio processing\n */\nexport type PlaybackMode =\n (typeof PlaybackModes)[keyof typeof PlaybackModes];\n\n/**\n * Configuration for buffered audio streaming\n */\nexport interface BufferedStreamConfig {\n /**\n * Turn ID for queue management\n */\n turnId: string;\n\n /**\n * Audio encoding format\n */\n encoding?: Encoding;\n\n /**\n * Buffer configuration options\n */\n bufferConfig?: Partial<IAudioBufferConfig>;\n\n /**\n * Callback for buffer health updates\n */\n onBufferHealth?: (metrics: IBufferHealthMetrics) => void;\n}\n\nexport const EncodingTypes = {\n PCM_F32LE: 'pcm_f32le',\n PCM_S16LE: 'pcm_s16le',\n} as const;\n\n/**\n * Defines different encoding formats for audio data\n */\nexport type Encoding =\n (typeof EncodingTypes)[keyof typeof EncodingTypes];\n\n/** RMS energy per frequency band, range [0, 1]. */\nexport interface FrequencyBands {\n low: number;\n mid: number;\n high: number;\n}\n\n/** Crossover frequency configuration for band analysis. */\nexport interface FrequencyBandConfig {\n /** Low/mid crossover in Hz (default 300). */\n lowCrossoverHz?: number;\n /** Mid/high crossover in Hz (default 2000). */\n highCrossoverHz?: number;\n}\n\n/**\n * Smart buffering mode options\n */\nexport type SmartBufferMode =\n | 'conservative'\n | 'balanced'\n | 'aggressive'\n | 'adaptive';\n\n/**\n * Network condition indicators for smart buffering\n */\nexport interface NetworkConditions {\n latency?: number; // Round-trip time in ms\n jitter?: number; // Network jitter in ms\n packetLoss?: number; // Packet loss percentage (0-100)\n bandwidth?: number; // Available bandwidth estimate\n}\n\n/**\n * Smart buffering configuration\n */\nexport interface SmartBufferConfig {\n mode: SmartBufferMode;\n networkConditions?: NetworkConditions;\n adaptiveThresholds?: {\n highLatencyMs?: number; // Threshold to enable aggressive buffering\n highJitterMs?: number; // Threshold to increase buffer size\n packetLossPercent?: number; // Threshold to enable buffering\n };\n}\n\nexport interface StartRecordingResult {\n fileUri: string;\n mimeType: string;\n channels?: number;\n bitDepth?: BitDepth;\n sampleRate?: SampleRate;\n}\n\nexport interface AudioDataEvent {\n data: string | Float32Array;\n data16kHz?: string | Float32Array;\n position: number;\n fileUri: string;\n eventDataSize: number;\n totalSize: number;\n soundLevel?: number;\n /** Frequency band RMS energy, present when recording is active. */\n frequencyBands?: FrequencyBands;\n}\n\nexport interface RecordingConfig {\n sampleRate?: SampleRate; // Sample rate for recording\n channels?: 1 | 2; // 1 or 2 (MONO or STEREO)\n encoding?: RecordingEncodingType; // Encoding type for the recording\n interval?: number; // Interval in milliseconds at which to emit recording data\n\n // Optional parameters for audio processing\n enableProcessing?: boolean; // Boolean to enable/disable audio processing (default is false)\n pointsPerSecond?: number; // Number of data points to extract per second of audio (default is 1000)\n onAudioStream?: (event: AudioDataEvent) => Promise<void>; // Callback function to handle audio stream\n /** Fired when the native layer reports a mid-recording error (e.g. system\n * interruption like Siri or a phone call). The consumer should treat the\n * recording session as terminated and clean up. */\n onError?: (event: MicrophoneErrorEvent) => void;\n /** Optional frequency band crossover configuration. */\n frequencyBandConfig?: FrequencyBandConfig;\n}\n\nexport interface MicrophoneErrorEvent {\n code: string;\n message: string;\n /**\n * True when the recording session has stopped and the caller must call\n * stopMicrophone() and reconnect to resume. False for transient conditions\n * where recording continues (READ_ERROR on iOS) or the library will\n * auto-recover (INTERRUPTED + autoResuming: true).\n */\n isFatal: boolean;\n /**\n * True only when code is INTERRUPTED — the library is waiting for the\n * system to return the audio session and will reinstall the tap\n * automatically. Always false when isFatal is true.\n */\n autoResuming: boolean;\n}\n\nexport interface Chunk {\n text: string;\n timestamp: [number, number | null];\n}\n\nexport interface TranscriberData {\n id: string;\n isBusy: boolean;\n text: string;\n startTime: number;\n endTime: number;\n chunks: Chunk[];\n}\n\nexport interface AudioRecording {\n fileUri: string;\n filename: string;\n durationMs: number;\n size: number;\n channels: number;\n bitDepth: BitDepth;\n sampleRate: SampleRate;\n mimeType: string;\n transcripts?: TranscriberData[];\n wavPCMData?: Float32Array; // Full PCM data for the recording in WAV format (only on web, for native use the fileUri)\n}\n\n// Audio Jitter Buffer Types\n\n/**\n * Configuration for audio buffer management\n */\nexport interface IAudioBufferConfig {\n targetBufferMs: number; // Target buffer size in milliseconds\n minBufferMs: number; // Minimum buffer size before underrun handling\n maxBufferMs: number; // Maximum buffer size before overrun handling\n frameIntervalMs: number; // Expected frame interval in milliseconds\n}\n\n/**\n * Audio payload for playback containing base64 encoded audio data\n */\nexport interface IAudioPlayPayload {\n audioData: string; // Base64 encoded PCM audio data\n isFirst?: boolean; // True if this is the first chunk in a stream\n isFinal?: boolean; // True if this is the final chunk in a stream\n}\n\n/**\n * Processed audio frame with metadata\n */\nexport interface IAudioFrame {\n sequenceNumber: number; // Sequential frame number\n data: IAudioPlayPayload; // Original audio payload\n duration: number; // Estimated frame duration in milliseconds\n timestamp: number; // Frame timestamp when processed\n}\n\n/**\n * Buffer health states for quality monitoring\n */\nexport type BufferHealthState =\n | 'idle'\n | 'healthy'\n | 'degraded'\n | 'critical';\n\n/**\n * Comprehensive buffer health and quality metrics\n */\nexport interface IBufferHealthMetrics {\n currentBufferMs: number; // Current buffer level in milliseconds\n targetBufferMs: number; // Target buffer level in milliseconds\n underrunCount: number; // Total number of buffer underruns\n overrunCount: number; // Total number of buffer overruns\n averageJitter: number; // Average network jitter in milliseconds\n bufferHealthState: BufferHealthState; // Current buffer health assessment\n adaptiveAdjustmentsCount: number; // Number of adaptive adjustments made\n}\n\n/**\n * Interface for audio buffer management\n */\nexport interface IAudioBufferManager {\n enqueueFrames(audioData: IAudioPlayPayload): void;\n startPlayback(): void;\n stopPlayback(): void;\n isPlaying(): boolean;\n getHealthMetrics(): IBufferHealthMetrics;\n updateConfig(config: Partial<IAudioBufferConfig>): void;\n applyAdaptiveAdjustments(): void;\n destroy(): void;\n getCurrentBufferMs(): number;\n}\n\n/**\n * Interface for frame processing\n */\nexport interface IFrameProcessor {\n parseChunk(payload: IAudioPlayPayload): IAudioFrame[];\n reset(): void;\n}\n\n/**\n * Interface for quality monitoring\n */\nexport interface IQualityMonitor {\n recordFrameArrival(timestamp: number): void;\n recordUnderrun(): void;\n recordOverrun(): void;\n updateBufferLevel(bufferMs: number): void;\n getMetrics(): IBufferHealthMetrics;\n getBufferHealthState(\n isPlaying: boolean,\n currentLatencyMs: number\n ): BufferHealthState;\n getRecommendedAdjustment(): number;\n reset(): void;\n}\n"]}
@@ -3,6 +3,7 @@ import AVFoundation
3
3
  import ExpoModulesCore
4
4
 
5
5
  let audioDataEvent: String = "AudioData"
6
+ let microphoneErrorEvent: String = "MicrophoneError"
6
7
  let deviceReconnectedEvent: String = "DeviceReconnected"
7
8
 
8
9
 
@@ -17,6 +18,7 @@ public class ExpoPlayAudioStreamModule: Module, MicrophoneDataDelegate, Pipeline
17
18
  if _microphone == nil {
18
19
  _microphone = Microphone()
19
20
  _microphone?.delegate = self
21
+ _microphone?.sharedAudioEngine = sharedAudioEngine
20
22
  }
21
23
  return _microphone!
22
24
  }
@@ -41,6 +43,7 @@ public class ExpoPlayAudioStreamModule: Module, MicrophoneDataDelegate, Pipeline
41
43
  // Defines event names that the module can send to JavaScript.
42
44
  Events([
43
45
  audioDataEvent,
46
+ microphoneErrorEvent,
44
47
  deviceReconnectedEvent,
45
48
  PipelineIntegration.EVENT_STATE_CHANGED,
46
49
  PipelineIntegration.EVENT_PLAYBACK_STARTED,
@@ -55,6 +58,9 @@ public class ExpoPlayAudioStreamModule: Module, MicrophoneDataDelegate, Pipeline
55
58
  ])
56
59
 
57
60
  AsyncFunction("destroy") { (promise: Promise) in
61
+ // Stop the microphone before tearing down the engine so the tap is
62
+ // cleanly removed and the capture callback cannot fire on a dead node.
63
+ self._microphone?.stopRecording(resolver: nil)
58
64
  self._pipelineIntegration?.destroy()
59
65
  self._pipelineIntegration = nil
60
66
  self.sharedAudioEngine.teardown()
@@ -120,13 +126,17 @@ public class ExpoPlayAudioStreamModule: Module, MicrophoneDataDelegate, Pipeline
120
126
  pointsPerSecond: nil
121
127
  )
122
128
 
123
- if !isAudioSessionInitialized {
124
- do {
129
+ do {
130
+ if !isAudioSessionInitialized {
125
131
  try ensureAudioSessionInitialized(settings: settings)
126
- } catch {
127
- promise.reject("ERROR", "Failed to init audio session \(error.localizedDescription)")
128
- return
129
132
  }
133
+ // Ensure the shared engine is configured so AEC is applied to mic audio.
134
+ if !self.sharedAudioEngine.isConfigured {
135
+ try self.sharedAudioEngine.configure(playbackMode: .conversation)
136
+ }
137
+ } catch {
138
+ promise.reject("ERROR", "Failed to init audio session: \(error.localizedDescription)")
139
+ return
130
140
  }
131
141
 
132
142
  if let result = self.microphone.startRecording(settings: settings, intervalMilliseconds: interval, frequencyBandConfig: fbConfig) {
@@ -334,13 +344,20 @@ public class ExpoPlayAudioStreamModule: Module, MicrophoneDataDelegate, Pipeline
334
344
  sendEvent(audioDataEvent, eventBody)
335
345
  }
336
346
 
337
- func onMicrophoneError(_ error: String, _ errorMessage: String) {
338
- let eventBody: [String: Any] = [
339
- "error": error,
340
- "errorMessage": errorMessage,
341
- "streamUuid": ""
342
- ]
343
- sendEvent(audioDataEvent, eventBody)
347
+ func onMicrophoneError(_ error: MicrophoneErrorInfo) {
348
+ // Rich structured channel for new consumers
349
+ sendEvent(microphoneErrorEvent, [
350
+ "code": error.code,
351
+ "message": error.message,
352
+ "isFatal": error.isFatal,
353
+ "autoResuming": error.autoResuming,
354
+ ])
355
+ // Backward-compat: keep the error variant on AudioData for existing consumers
356
+ sendEvent(audioDataEvent, [
357
+ "error": error.code,
358
+ "errorMessage": error.message,
359
+ "streamUuid": "",
360
+ ])
344
361
  }
345
362
 
346
363
  func onDeviceReconnected(_ reason: AVAudioSession.RouteChangeReason) {