Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions apps/common-app/src/demos/Record/Record.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ const Record: FC = () => {
setupNotification(false);

if (result.status === 'success') {
console.log('Recording started, file path:', result.path);
setState(RecordingState.Recording);
return;
}
Expand Down Expand Up @@ -124,7 +123,7 @@ const Record: FC = () => {
return;
}

const audioBuffer = await audioContext.decodeAudioData(info.path);
const audioBuffer = await audioContext.decodeAudioData(info.paths[0]);
setRecordedBuffer(audioBuffer);
setState(RecordingState.ReadyToPlay);
currentPositionSV.value = 0;
Expand Down
6 changes: 3 additions & 3 deletions apps/fabric-example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2476,7 +2476,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
FBLazyVector: c00c20551d40126351a6783c47ce75f5b374851b
hermes-engine: c399a2e224a0b13c589d76b4fc05e14bdd76fa88
hermes-engine: 91023181d4bc5948b457de5314623fbfe4f8604e
RCTDeprecation: 3bb167081b134461cfeb875ff7ae1945f8635257
RCTRequired: 74839f55d5058a133a0bc4569b0afec750957f64
RCTSwiftUI: 87a316382f3eab4dd13d2a0d0fd2adcce917361a
Expand All @@ -2485,7 +2485,7 @@ SPEC CHECKSUMS:
React: 1b1536b9099195944034e65b1830f463caaa8390
React-callinvoker: 6dff6d17d1d6cc8fdf85468a649bafed473c65f5
React-Core: 00faa4d038298089a1d5a5b21dde8660c4f0820d
React-Core-prebuilt: ab26be1216323aea7c76f96ca450bffa7bcd4a72
React-Core-prebuilt: a6d614de037caff7898424dfc22915ec792de921
React-CoreModules: a17807f849bfd86045b0b9a75ec8c19373b482f6
React-cxxreact: c7b53ace5827be54048288bce5c55f337c41e95f
React-debug: e1f00fcd2cef58a2897471a6d76a4ef5f5f90c74
Expand Down Expand Up @@ -2549,7 +2549,7 @@ SPEC CHECKSUMS:
ReactAppDependencyProvider: 5787b37b8e2e51dfeab697ec031cc7c4080dcea2
ReactCodegen: d07ee3c8db75b43d1cbe479ae6affebf9925c733
ReactCommon: fe2a3af8975e63efa60f95fca8c34dc85deee360
ReactNativeDependencies: 212738cc51e6c4cc34ee487890497d6f41979ec0
ReactNativeDependencies: 4d5ce2683b6d74f7c686bf90a88c7d381295cf3c
RNAudioAPI: 6f6c369c1df31fc8205cbc6f0c3bcb7322e9cfa9
RNGestureHandler: 187c5c7936abf427bc4d22d6c3b1ac80ad1f63c0
RNReanimated: 64f4b3b33b48b19e0ba76a352571b52b1e931981
Expand Down
34 changes: 19 additions & 15 deletions packages/audiodocs/docs/system/audio-manager.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function App() {
AudioManager.setAudioSessionOptions({
iosCategory: 'playback',
iosMode: 'default',
iosOptions: ['defaultToSpeaker', 'allowBluetoothA2DP'],
iosOptions: ['allowBluetoothHFP', 'allowAirPlay'],
})
// enabling emission of events
AudioManager.observeAudioInterruptions(true);
Expand Down Expand Up @@ -181,33 +181,37 @@ type AudioFocusType =
<summary>Type definitions</summary>
```typescript
type IOSCategory =
| 'record'
| 'ambient'
| 'playback'
| 'multiRoute'
| 'soloAmbient'
| 'playAndRecord';
| 'playAndRecord'
| 'playback'
| 'record'
| 'soloAmbient';

type IOSMode =
| 'default'
| 'dualRoute'
| 'gameChat'
| 'videoChat'
| 'voiceChat'
| 'measurement'
| 'voicePrompt'
| 'spokenAudio'
| 'moviePlayback'
| 'videoRecording';
| 'shortFormVideo'
| 'spokenAudio'
| 'videoChat'
| 'videoRecording'
| 'voiceChat'
| 'voicePrompt';

type IOSOption =
| 'duckOthers'
| 'allowAirPlay'
| 'mixWithOthers'
| 'allowBluetoothA2DP'
| 'allowBluetoothHFP'
| 'bluetoothHighQualityRecording'
| 'defaultToSpeaker'
| 'allowBluetoothA2DP'
| 'overrideMutedMicrophoneInterruption'
| 'interruptSpokenAudioAndMixWithOthers';
| 'duckOthers'
| 'farFieldInput'
| 'interruptSpokenAudioAndMixWithOthers'
| 'mixWithOthers'
| 'overrideMutedMicrophoneInterruption';

interface SessionOptions {
iosMode?: IOSMode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,18 +344,18 @@ - (AVAudioSessionCategory)categoryFromString:(NSString *)categorySTR
{
AVAudioSessionCategory category = 0;

if ([categorySTR isEqualToString:@"record"]) {
category = AVAudioSessionCategoryRecord;
} else if ([categorySTR isEqualToString:@"ambient"]) {
if ([categorySTR isEqualToString:@"ambient"]) {
category = AVAudioSessionCategoryAmbient;
} else if ([categorySTR isEqualToString:@"playback"]) {
category = AVAudioSessionCategoryPlayback;
} else if ([categorySTR isEqualToString:@"multiRoute"]) {
category = AVAudioSessionCategoryMultiRoute;
} else if ([categorySTR isEqualToString:@"soloAmbient"]) {
category = AVAudioSessionCategorySoloAmbient;
} else if ([categorySTR isEqualToString:@"playAndRecord"]) {
category = AVAudioSessionCategoryPlayAndRecord;
} else if ([categorySTR isEqualToString:@"playback"]) {
category = AVAudioSessionCategoryPlayback;
} else if ([categorySTR isEqualToString:@"record"]) {
category = AVAudioSessionCategoryRecord;
} else if ([categorySTR isEqualToString:@"soloAmbient"]) {
category = AVAudioSessionCategorySoloAmbient;
}

return category;
Expand All @@ -367,22 +367,34 @@ - (AVAudioSessionMode)modeFromString:(NSString *)modeSTR

if ([modeSTR isEqualToString:@"default"]) {
mode = AVAudioSessionModeDefault;
} else if ([modeSTR isEqualToString:@"dualRoute"]) {
if (@available(iOS 26.2, *)) {
mode = AVAudioSessionModeDualRoute;
} else {
mode = AVAudioSessionModeDefault;
}
} else if ([modeSTR isEqualToString:@"gameChat"]) {
mode = AVAudioSessionModeGameChat;
} else if ([modeSTR isEqualToString:@"videoChat"]) {
mode = AVAudioSessionModeVideoChat;
} else if ([modeSTR isEqualToString:@"voiceChat"]) {
mode = AVAudioSessionModeVoiceChat;
} else if ([modeSTR isEqualToString:@"measurement"]) {
mode = AVAudioSessionModeMeasurement;
} else if ([modeSTR isEqualToString:@"voicePrompt"]) {
mode = AVAudioSessionModeVoicePrompt;
} else if ([modeSTR isEqualToString:@"spokenAudio"]) {
mode = AVAudioSessionModeSpokenAudio;
} else if ([modeSTR isEqualToString:@"moviePlayback"]) {
mode = AVAudioSessionModeMoviePlayback;
} else if ([modeSTR isEqualToString:@"shortFormVideo"]) {
if (@available(iOS 26, *)) {
mode = AVAudioSessionModeShortFormVideo;
} else {
mode = AVAudioSessionModeDefault;
}
} else if ([modeSTR isEqualToString:@"spokenAudio"]) {
mode = AVAudioSessionModeSpokenAudio;
} else if ([modeSTR isEqualToString:@"videoChat"]) {
mode = AVAudioSessionModeVideoChat;
} else if ([modeSTR isEqualToString:@"videoRecording"]) {
mode = AVAudioSessionModeVideoRecording;
} else if ([modeSTR isEqualToString:@"voiceChat"]) {
mode = AVAudioSessionModeVoiceChat;
} else if ([modeSTR isEqualToString:@"voicePrompt"]) {
mode = AVAudioSessionModeVoicePrompt;
}

return mode;
Expand All @@ -393,41 +405,58 @@ - (AVAudioSessionCategoryOptions)optionsFromArray:(NSArray *)optionsArray
AVAudioSessionCategoryOptions options = 0;

for (NSString *option in optionsArray) {
if ([option isEqualToString:@"duckOthers"]) {
options |= AVAudioSessionCategoryOptionDuckOthers;
}

if ([option isEqualToString:@"allowAirPlay"]) {
options |= AVAudioSessionCategoryOptionAllowAirPlay;
continue;
}

if ([option isEqualToString:@"mixWithOthers"]) {
options |= AVAudioSessionCategoryOptionMixWithOthers;
if ([option isEqualToString:@"allowBluetoothA2DP"]) {
options |= AVAudioSessionCategoryOptionAllowBluetoothA2DP;
continue;
}

if ([option isEqualToString:@"allowBluetoothHFP"]) {
// XCode 26.x (default support SDK >= 26.x) uses AVAudioSessionCategoryOptionAllowBluetoothHFP as new standard for every platfrom (down to iOS 1.0)
// Older Xcode (default support SDKs) versions doesn't define it at all.
// Both (AVAudioSessionCategoryOptionAllowBluetooth in SDK < 26.x) and (AVAudioSessionCategoryOptionAllowBluetoothHFP in SDK >= 26.x) resolve to this value
// We use it here directly as there is no reliable way to switch between them (no @available for this).
// TODO: replace with AVAudioSessionCategoryOptionAllowBluetoothHFP once XCode 16.x will dig its grave
options |= 0x4;
options |= AVAudioSessionCategoryOptionAllowBluetoothHFP;
continue;
}

if ([option isEqualToString:@"bluetoothHighQualityRecording"]) {
if (@available(iOS 26, *)) {
options |= AVAudioSessionCategoryOptionBluetoothHighQualityRecording;
}
continue;
}

if ([option isEqualToString:@"defaultToSpeaker"]) {
options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
continue;
}

if ([option isEqualToString:@"allowBluetoothA2DP"]) {
options |= AVAudioSessionCategoryOptionAllowBluetoothA2DP;
if ([option isEqualToString:@"duckOthers"]) {
options |= AVAudioSessionCategoryOptionDuckOthers;
continue;
}

if ([option isEqualToString:@"overrideMutedMicrophoneInterruption"]) {
options |= AVAudioSessionCategoryOptionOverrideMutedMicrophoneInterruption;
if ([option isEqualToString:@"farFieldInput"]) {
if (@available(iOS 26.2, *)) {
options |= AVAudioSessionCategoryOptionFarFieldInput;
continue;
}
}

if ([option isEqualToString:@"interruptSpokenAudioAndMixWithOthers"]) {
options |= AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers;
continue;
}

if ([option isEqualToString:@"mixWithOthers"]) {
options |= AVAudioSessionCategoryOptionMixWithOthers;
continue;
}

if ([option isEqualToString:@"overrideMutedMicrophoneInterruption"]) {
options |= AVAudioSessionCategoryOptionOverrideMutedMicrophoneInterruption;
continue;
}
}

Expand Down
34 changes: 19 additions & 15 deletions packages/react-native-audio-api/src/system/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,37 @@ import type { AudioEventSubscription } from '../events';
import type { SystemEventCallback, SystemEventName } from '../events/types';

export type IOSCategory =
| 'record'
| 'ambient'
| 'playback'
| 'multiRoute'
| 'soloAmbient'
| 'playAndRecord';
| 'playAndRecord'
| 'playback'
| 'record'
| 'soloAmbient';

export type IOSMode =
| 'default'
| 'dualRoute'
| 'gameChat'
| 'videoChat'
| 'voiceChat'
| 'measurement'
| 'voicePrompt'
| 'spokenAudio'
| 'moviePlayback'
| 'videoRecording';
| 'shortFormVideo'
| 'spokenAudio'
| 'videoChat'
| 'videoRecording'
| 'voiceChat'
| 'voicePrompt';

export type IOSOption =
| 'duckOthers'
| 'allowAirPlay'
| 'mixWithOthers'
| 'defaultToSpeaker'
| 'allowBluetoothHFP'
| 'allowBluetoothA2DP'
| 'overrideMutedMicrophoneInterruption'
| 'interruptSpokenAudioAndMixWithOthers';
| 'allowBluetoothHFP'
| 'bluetoothHighQualityRecording'
| 'defaultToSpeaker'
| 'duckOthers'
| 'farFieldInput'
| 'interruptSpokenAudioAndMixWithOthers'
| 'mixWithOthers'
| 'overrideMutedMicrophoneInterruption';

export type AudioFocusType =
| 'gain'
Expand Down
Loading