@siteed/expo-audio-studio 2.14.1 → 2.14.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 +7 -1
- package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +11 -0
- package/build/cjs/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
- package/build/cjs/ExpoAudioStream.types.js.map +1 -1
- package/build/cjs/constants/platformLimitations.js +99 -0
- package/build/cjs/constants/platformLimitations.js.map +1 -0
- package/build/cjs/index.js +9 -1
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/useAudioRecorder.js +53 -3
- package/build/cjs/useAudioRecorder.js.map +1 -1
- package/build/esm/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
- package/build/esm/ExpoAudioStream.types.js.map +1 -1
- package/build/esm/constants/platformLimitations.js +90 -0
- package/build/esm/constants/platformLimitations.js.map +1 -0
- package/build/esm/index.js +2 -0
- package/build/esm/index.js.map +1 -1
- package/build/esm/useAudioRecorder.js +20 -3
- package/build/esm/useAudioRecorder.js.map +1 -1
- package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts +14 -0
- package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts.map +1 -1
- package/build/types/ExpoAudioStream.types.d.ts +43 -1
- package/build/types/ExpoAudioStream.types.d.ts.map +1 -1
- package/build/types/constants/platformLimitations.d.ts +40 -0
- package/build/types/constants/platformLimitations.d.ts.map +1 -0
- package/build/types/index.d.ts +1 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/useAudioRecorder.d.ts.map +1 -1
- package/ios/AudioStreamManager.swift +27 -3
- package/package.json +1 -1
- package/src/AudioAnalysis/AudioAnalysis.types.ts +15 -1
- package/src/ExpoAudioStream.types.ts +46 -1
- package/src/constants/platformLimitations.ts +118 -0
- package/src/index.ts +11 -0
- package/src/useAudioRecorder.tsx +29 -3
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-specific audio recording limitations and capabilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Platform } from 'react-native'
|
|
6
|
+
|
|
7
|
+
import { EncodingType, BitDepth } from '../ExpoAudioStream.types'
|
|
8
|
+
|
|
9
|
+
export interface PlatformCapabilities {
|
|
10
|
+
supportedEncodings: EncodingType[]
|
|
11
|
+
supportedBitDepths: BitDepth[]
|
|
12
|
+
notes: string[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const PLATFORM_CAPABILITIES: Record<string, PlatformCapabilities> = {
|
|
16
|
+
ios: {
|
|
17
|
+
supportedEncodings: ['pcm_16bit', 'pcm_32bit'],
|
|
18
|
+
supportedBitDepths: [16, 32],
|
|
19
|
+
notes: [
|
|
20
|
+
'8-bit PCM is not natively supported by iOS AVAudioFormat',
|
|
21
|
+
'Recording with 8-bit will fallback to 16-bit',
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
android: {
|
|
25
|
+
supportedEncodings: ['pcm_8bit', 'pcm_16bit', 'pcm_32bit'],
|
|
26
|
+
supportedBitDepths: [8, 16, 32],
|
|
27
|
+
notes: ['All PCM formats are fully supported'],
|
|
28
|
+
},
|
|
29
|
+
web: {
|
|
30
|
+
supportedEncodings: ['pcm_16bit', 'pcm_32bit'],
|
|
31
|
+
supportedBitDepths: [16, 32],
|
|
32
|
+
notes: [
|
|
33
|
+
'Web Audio API typically works with 32-bit float',
|
|
34
|
+
'8-bit is not commonly supported in browsers',
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get the current platform's audio capabilities
|
|
41
|
+
*/
|
|
42
|
+
export function getPlatformCapabilities(): PlatformCapabilities {
|
|
43
|
+
return PLATFORM_CAPABILITIES[Platform.OS] || PLATFORM_CAPABILITIES.web
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check if a specific encoding is supported on the current platform
|
|
48
|
+
*/
|
|
49
|
+
export function isEncodingSupported(encoding: EncodingType): boolean {
|
|
50
|
+
const capabilities = getPlatformCapabilities()
|
|
51
|
+
return capabilities.supportedEncodings.includes(encoding)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check if a specific bit depth is supported on the current platform
|
|
56
|
+
*/
|
|
57
|
+
export function isBitDepthSupported(bitDepth: BitDepth): boolean {
|
|
58
|
+
const capabilities = getPlatformCapabilities()
|
|
59
|
+
return capabilities.supportedBitDepths.includes(bitDepth)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get a fallback encoding if the requested one is not supported
|
|
64
|
+
*/
|
|
65
|
+
export function getFallbackEncoding(
|
|
66
|
+
requestedEncoding: EncodingType
|
|
67
|
+
): EncodingType {
|
|
68
|
+
if (isEncodingSupported(requestedEncoding)) {
|
|
69
|
+
return requestedEncoding
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Default fallback is 16-bit PCM (supported on all platforms)
|
|
73
|
+
return 'pcm_16bit'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get a fallback bit depth if the requested one is not supported
|
|
78
|
+
*/
|
|
79
|
+
export function getFallbackBitDepth(requestedBitDepth: BitDepth): BitDepth {
|
|
80
|
+
if (isBitDepthSupported(requestedBitDepth)) {
|
|
81
|
+
return requestedBitDepth
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Default fallback is 16-bit (supported on all platforms)
|
|
85
|
+
return 16
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Validate and adjust recording configuration based on platform limitations
|
|
90
|
+
*/
|
|
91
|
+
export function validateRecordingConfig(config: { encoding?: EncodingType }): {
|
|
92
|
+
encoding: EncodingType
|
|
93
|
+
warnings: string[]
|
|
94
|
+
} {
|
|
95
|
+
const warnings: string[] = []
|
|
96
|
+
const capabilities = getPlatformCapabilities()
|
|
97
|
+
|
|
98
|
+
let encoding = config.encoding || 'pcm_16bit'
|
|
99
|
+
|
|
100
|
+
// Check if encoding is supported
|
|
101
|
+
if (!isEncodingSupported(encoding)) {
|
|
102
|
+
const fallback = getFallbackEncoding(encoding)
|
|
103
|
+
warnings.push(
|
|
104
|
+
`${encoding} is not supported on ${Platform.OS}. Using ${fallback} instead.`
|
|
105
|
+
)
|
|
106
|
+
encoding = fallback
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Add platform-specific notes if there were changes
|
|
110
|
+
if (warnings.length > 0) {
|
|
111
|
+
warnings.push(...capabilities.notes)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
encoding,
|
|
116
|
+
warnings,
|
|
117
|
+
}
|
|
118
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,17 @@ export * from './utils/convertPCMToFloat32'
|
|
|
19
19
|
export * from './utils/getWavFileInfo'
|
|
20
20
|
export * from './utils/writeWavHeader'
|
|
21
21
|
|
|
22
|
+
// Export platform capabilities
|
|
23
|
+
export {
|
|
24
|
+
getPlatformCapabilities,
|
|
25
|
+
isEncodingSupported,
|
|
26
|
+
isBitDepthSupported,
|
|
27
|
+
getFallbackEncoding,
|
|
28
|
+
getFallbackBitDepth,
|
|
29
|
+
validateRecordingConfig,
|
|
30
|
+
type PlatformCapabilities,
|
|
31
|
+
} from './constants/platformLimitations'
|
|
32
|
+
|
|
22
33
|
// Export AudioDeviceManager
|
|
23
34
|
export { AudioDeviceManager, audioDeviceManager } from './AudioDeviceManager'
|
|
24
35
|
|
package/src/useAudioRecorder.tsx
CHANGED
|
@@ -473,8 +473,34 @@ export function useAudioRecorder({
|
|
|
473
473
|
|
|
474
474
|
const startRecording = useCallback(
|
|
475
475
|
async (recordingOptions: RecordingConfig) => {
|
|
476
|
-
|
|
477
|
-
|
|
476
|
+
// Import validation function
|
|
477
|
+
const { validateRecordingConfig } = await import(
|
|
478
|
+
'./constants/platformLimitations'
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
// Validate the encoding configuration
|
|
482
|
+
const validationResult = validateRecordingConfig({
|
|
483
|
+
encoding: recordingOptions.encoding,
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
// Log warnings if any
|
|
487
|
+
if (validationResult.warnings.length > 0) {
|
|
488
|
+
validationResult.warnings.forEach((warning) => {
|
|
489
|
+
logger?.warn(warning)
|
|
490
|
+
})
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Update recording options with validated values
|
|
494
|
+
const validatedOptions = {
|
|
495
|
+
...recordingOptions,
|
|
496
|
+
encoding: validationResult.encoding,
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
recordingConfigRef.current = validatedOptions
|
|
500
|
+
logger?.debug(
|
|
501
|
+
`start recording with validated config`,
|
|
502
|
+
validatedOptions
|
|
503
|
+
)
|
|
478
504
|
|
|
479
505
|
analysisRef.current = { ...defaultAnalysis } // Reset analysis data
|
|
480
506
|
fullAnalysisRef.current = { ...defaultAnalysis }
|
|
@@ -483,7 +509,7 @@ export function useAudioRecorder({
|
|
|
483
509
|
onRecordingInterrupted,
|
|
484
510
|
onAudioAnalysis,
|
|
485
511
|
...options
|
|
486
|
-
} =
|
|
512
|
+
} = validatedOptions
|
|
487
513
|
const { enableProcessing } = options
|
|
488
514
|
|
|
489
515
|
const maxRecentDataDuration = 10000 // TODO compute maxRecentDataDuration based on screen dimensions
|