@siteed/expo-audio-stream 1.3.0 → 1.3.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.
- package/CHANGELOG.md +10 -0
- package/android/build/.transforms/0588d516016bbd2e5b51abc80cc3d78d/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +1 -1
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.s +1 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build.gradle +13 -5
- package/package.json +2 -3
- package/plugin/src/index.ts +5 -4
- package/src/AudioAnalysis/extractAudioAnalysis.ts +13 -13
- package/src/AudioAnalysis/extractWaveform.ts +0 -3
- package/src/ExpoAudioStream.types.ts +7 -0
- package/src/ExpoAudioStream.web.ts +8 -6
- package/src/WebRecorder.web.ts +15 -14
- package/src/events.ts +0 -4
- package/src/useAudioRecorder.tsx +32 -36
- package/src/utils/convertPCMToFloat32.ts +5 -5
- package/src/logger.ts +0 -22
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
## [1.3.1] - 2024-12-05
|
|
12
|
+
- feat(web): implement throttling and optimize event processing (#49) ([da28765](https://github.com/deeeed/expo-audio-stream/commit/da2876524c2c9d6e0a980fde40a0197b929d8a7f))
|
|
13
|
+
|
|
11
14
|
## [1.3.0] - 2024-11-28
|
|
12
15
|
### Added
|
|
13
16
|
- refactor(permissions): standardize permission status response structure across platforms (#44) ([7c9c800](https://github.com/deeeed/expo-audio-stream/commit/7c9c800d83b7cea3516643371484d5e1f3b99e4c))
|
|
@@ -16,11 +19,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
16
19
|
- feat: latest expo fixes ([9cc5ac3](https://github.com/deeeed/expo-audio-stream/commit/9cc5ac39751999e5b33e11c16355557143d68d10))
|
|
17
20
|
- feat: latest expo sdk ([258ef6c](https://github.com/deeeed/expo-audio-stream/commit/258ef6cf68e70c7855f696a01204f79b0793fdc0))
|
|
18
21
|
|
|
22
|
+
|
|
19
23
|
## [1.2.5] - 2024-11-12
|
|
20
24
|
### Added
|
|
21
25
|
- docs(license): add MIT license to all packages (6 files changed)
|
|
22
26
|
- fix(expo-audio-stream): return actual recording settings from startRecording on iOS #37
|
|
23
27
|
|
|
28
|
+
|
|
24
29
|
## [1.2.4] - 2024-11-05
|
|
25
30
|
### Changed
|
|
26
31
|
- Android minimum audio interval set to 10ms.
|
|
@@ -29,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
29
34
|
### Fixed
|
|
30
35
|
- Remove frequently firing log statements on web.
|
|
31
36
|
|
|
37
|
+
|
|
32
38
|
## [1.2.0] - 2024-10-24
|
|
33
39
|
### Added
|
|
34
40
|
- Feature: Keep device awake during recording with `keepAwake` option
|
|
@@ -37,11 +43,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
37
43
|
- Android: Configurable notification actions, colors, and priorities
|
|
38
44
|
- iOS: Integration with media player
|
|
39
45
|
|
|
46
|
+
|
|
40
47
|
## [1.1.17] - 2024-10-21
|
|
41
48
|
### Added
|
|
42
49
|
- Support bluetooth headset on ios
|
|
43
50
|
- Fixes: android not reading custom interval audio update
|
|
44
51
|
|
|
52
|
+
|
|
45
53
|
## [1.0.0] - 2024-04-01
|
|
46
54
|
|
|
47
55
|
### Added
|
|
@@ -53,5 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
53
61
|
- Feature: Audio features extraction during recording.
|
|
54
62
|
- Feature: Consistent WAV PCM recording format across all platforms.
|
|
55
63
|
|
|
64
|
+
[unreleased]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.3.1...HEAD
|
|
65
|
+
[1.3.1]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-stream@1.3.0...@siteed/expo-audio-stream@1.3.1
|
|
56
66
|
[Unreleased]: https://github.com/deeeed/expo-audio-stream/compare/v1.0.0...HEAD
|
|
57
67
|
[1.0.0]: https://github.com/deeeed/expo-audio-stream/releases/tag/v1.0.0
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
23
|
|
2
2
|
0
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len
CHANGED
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values
ADDED
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at
CHANGED
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.s
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
�Q�a�c�f
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin
CHANGED
|
Binary file
|
package/android/build.gradle
CHANGED
|
@@ -51,17 +51,19 @@ afterEvaluate {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
android {
|
|
54
|
-
compileSdkVersion safeExtGet("compileSdkVersion",
|
|
54
|
+
compileSdkVersion safeExtGet("compileSdkVersion", 34)
|
|
55
55
|
|
|
56
56
|
def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
|
|
57
57
|
if (agpVersion.tokenize('.')[0].toInteger() < 8) {
|
|
58
58
|
compileOptions {
|
|
59
|
-
sourceCompatibility JavaVersion.
|
|
60
|
-
targetCompatibility JavaVersion.
|
|
59
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
60
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
|
|
64
|
+
kotlinOptions {
|
|
65
|
+
jvmTarget = '17'
|
|
66
|
+
}
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
69
|
|
|
@@ -95,3 +97,9 @@ dependencies {
|
|
|
95
97
|
testImplementation 'org.jetbrains.kotlin:kotlin-test:1.8.10'
|
|
96
98
|
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit:1.8.10'
|
|
97
99
|
}
|
|
100
|
+
|
|
101
|
+
kotlin {
|
|
102
|
+
jvmToolchain {
|
|
103
|
+
languageVersion.set(JavaLanguageVersion.of(17))
|
|
104
|
+
}
|
|
105
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@siteed/expo-audio-stream",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "stream audio crossplatform",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "build/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@expo/config-plugins": "~8.0.0",
|
|
41
41
|
"@siteed/publisher": "^0.4.15",
|
|
42
|
-
"@siteed/react-native-logger": "^0.
|
|
42
|
+
"@siteed/react-native-logger": "^1.0.1",
|
|
43
43
|
"@size-limit/preset-big-lib": "^11.1.4",
|
|
44
44
|
"@types/jest": "^29.5.12",
|
|
45
45
|
"@types/node": "^20.12.7",
|
|
@@ -67,7 +67,6 @@
|
|
|
67
67
|
"typescript": "~5.3.3"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
|
-
"@siteed/react-native-logger": "*",
|
|
71
70
|
"expo": "*",
|
|
72
71
|
"react": "*",
|
|
73
72
|
"react-native": "*"
|
package/plugin/src/index.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AndroidConfig,
|
|
3
2
|
ConfigPlugin,
|
|
4
3
|
withAndroidManifest,
|
|
5
4
|
withInfoPlist,
|
|
5
|
+
AndroidConfig,
|
|
6
6
|
} from '@expo/config-plugins'
|
|
7
|
+
import { ExpoConfig } from '@expo/config-types'
|
|
7
8
|
|
|
8
9
|
const MICROPHONE_USAGE = 'Allow $(PRODUCT_NAME) to access your microphone'
|
|
9
10
|
const NOTIFICATION_USAGE = 'Show recording notifications and controls'
|
|
10
11
|
|
|
11
|
-
const withRecordingPermission: ConfigPlugin = (config) => {
|
|
12
|
+
const withRecordingPermission: ConfigPlugin = (config: ExpoConfig) => {
|
|
12
13
|
// iOS Configuration
|
|
13
|
-
config = withInfoPlist(config
|
|
14
|
+
config = withInfoPlist(config, (config) => {
|
|
14
15
|
// Existing microphone permission
|
|
15
16
|
config.modResults['NSMicrophoneUsageDescription'] =
|
|
16
17
|
config.modResults['NSMicrophoneUsageDescription'] ||
|
|
@@ -38,7 +39,7 @@ const withRecordingPermission: ConfigPlugin = (config) => {
|
|
|
38
39
|
})
|
|
39
40
|
|
|
40
41
|
// Android Configuration
|
|
41
|
-
config = withAndroidManifest(config
|
|
42
|
+
config = withAndroidManifest(config, (config) => {
|
|
42
43
|
const androidManifest = config.modResults
|
|
43
44
|
if (!androidManifest.manifest) {
|
|
44
45
|
console.warn(
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
// packages/expo-audio-stream/src/AudioAnalysis/extractAudioAnalysis.ts
|
|
2
|
+
import { ConsoleLike } from '../ExpoAudioStream.types'
|
|
3
|
+
import ExpoAudioStreamModule from '../ExpoAudioStreamModule'
|
|
4
|
+
import { isWeb } from '../constants'
|
|
2
5
|
import {
|
|
3
6
|
AmplitudeAlgorithm,
|
|
4
7
|
AudioAnalysis,
|
|
5
8
|
AudioFeaturesOptions,
|
|
6
9
|
} from './AudioAnalysis.types'
|
|
7
|
-
import ExpoAudioStreamModule from '../ExpoAudioStreamModule'
|
|
8
|
-
import { isWeb } from '../constants'
|
|
9
|
-
import { getLogger } from '../logger'
|
|
10
10
|
import { convertPCMToFloat32 } from '../utils/convertPCMToFloat32'
|
|
11
11
|
import { getWavFileInfo, WavFileInfo } from '../utils/getWavFileInfo'
|
|
12
12
|
import { InlineFeaturesExtractor } from '../workers/InlineFeaturesExtractor.web'
|
|
13
13
|
|
|
14
|
-
const logger = getLogger('extractAudioAnalysis')
|
|
15
|
-
|
|
16
14
|
export interface ExtractAudioAnalysisProps {
|
|
17
15
|
fileUri?: string // should provide either fileUri or arrayBuffer
|
|
18
16
|
wavMetadata?: WavFileInfo
|
|
@@ -28,6 +26,7 @@ export interface ExtractAudioAnalysisProps {
|
|
|
28
26
|
pointsPerSecond?: number // Optional number of points per second. Use to reduce the number of points and compute the number of datapoints to return.
|
|
29
27
|
features?: AudioFeaturesOptions
|
|
30
28
|
featuresExtratorUrl?: string
|
|
29
|
+
logger?: ConsoleLike
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
export const extractAudioAnalysis = async ({
|
|
@@ -42,6 +41,7 @@ export const extractAudioAnalysis = async ({
|
|
|
42
41
|
algorithm = 'rms',
|
|
43
42
|
features,
|
|
44
43
|
featuresExtratorUrl,
|
|
44
|
+
logger,
|
|
45
45
|
}: ExtractAudioAnalysisProps): Promise<AudioAnalysis> => {
|
|
46
46
|
if (isWeb) {
|
|
47
47
|
if (!arrayBuffer && !fileUri) {
|
|
@@ -49,7 +49,7 @@ export const extractAudioAnalysis = async ({
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
if (!arrayBuffer) {
|
|
52
|
-
logger
|
|
52
|
+
logger?.log(`fetching fileUri`, fileUri)
|
|
53
53
|
const response = await fetch(fileUri!)
|
|
54
54
|
|
|
55
55
|
if (!response.ok) {
|
|
@@ -59,25 +59,25 @@ export const extractAudioAnalysis = async ({
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
arrayBuffer = await response.arrayBuffer()
|
|
62
|
-
logger
|
|
62
|
+
logger?.log(`fetched fileUri`, arrayBuffer.byteLength, arrayBuffer)
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Create a new copy of the ArrayBuffer to avoid detachment issues
|
|
66
66
|
const bufferCopy = arrayBuffer.slice(0)
|
|
67
|
-
logger
|
|
67
|
+
logger?.log(
|
|
68
68
|
`extractAudioAnalysis skipWavHeader=${skipWavHeader} bitDepth=${bitDepth} len=${bufferCopy.byteLength}`,
|
|
69
69
|
bufferCopy.slice(0, 100)
|
|
70
70
|
)
|
|
71
71
|
|
|
72
72
|
let actualBitDepth = bitDepth
|
|
73
73
|
if (!actualBitDepth) {
|
|
74
|
-
logger
|
|
74
|
+
logger?.log(
|
|
75
75
|
`extractAudioAnalysis bitDepth not provided -- getting wav file info`
|
|
76
76
|
)
|
|
77
77
|
const fileInfo = await getWavFileInfo(bufferCopy)
|
|
78
78
|
actualBitDepth = fileInfo.bitDepth
|
|
79
79
|
}
|
|
80
|
-
logger
|
|
80
|
+
logger?.log(`extractAudioAnalysis actualBitDepth=${actualBitDepth}`)
|
|
81
81
|
|
|
82
82
|
const {
|
|
83
83
|
pcmValues: channelData,
|
|
@@ -88,7 +88,7 @@ export const extractAudioAnalysis = async ({
|
|
|
88
88
|
bitDepth: actualBitDepth,
|
|
89
89
|
skipWavHeader,
|
|
90
90
|
})
|
|
91
|
-
logger
|
|
91
|
+
logger?.log(
|
|
92
92
|
`extractAudioAnalysis skipWaveHeader=${skipWavHeader} convertPCMToFloat32 length=${channelData.length} range: [ ${min} :: ${max} ]`
|
|
93
93
|
)
|
|
94
94
|
|
|
@@ -129,7 +129,7 @@ export const extractAudioAnalysis = async ({
|
|
|
129
129
|
if (!fileUri) {
|
|
130
130
|
throw new Error('fileUri is required')
|
|
131
131
|
}
|
|
132
|
-
logger
|
|
132
|
+
logger?.log(`extractAudioAnalysis`, {
|
|
133
133
|
fileUri,
|
|
134
134
|
pointsPerSecond,
|
|
135
135
|
algorithm,
|
|
@@ -141,7 +141,7 @@ export const extractAudioAnalysis = async ({
|
|
|
141
141
|
algorithm,
|
|
142
142
|
features,
|
|
143
143
|
})
|
|
144
|
-
logger
|
|
144
|
+
logger?.log(`extractAudioAnalysis`, res)
|
|
145
145
|
return res
|
|
146
146
|
}
|
|
147
147
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import ExpoAudioStreamModule from '../ExpoAudioStreamModule'
|
|
2
|
-
import { getLogger } from '../logger'
|
|
3
2
|
|
|
4
|
-
const logger = getLogger('extractWaveform')
|
|
5
3
|
export interface ExtractWaveformProps {
|
|
6
4
|
fileUri: string
|
|
7
5
|
numberOfSamples: number
|
|
@@ -20,6 +18,5 @@ export const extractWaveform = async ({
|
|
|
20
18
|
offset,
|
|
21
19
|
length,
|
|
22
20
|
})
|
|
23
|
-
logger.log(`extractWaveform`, res)
|
|
24
21
|
return res
|
|
25
22
|
}
|
|
@@ -27,6 +27,13 @@ export type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'
|
|
|
27
27
|
export type SampleRate = 16000 | 44100 | 48000
|
|
28
28
|
export type BitDepth = 8 | 16 | 32
|
|
29
29
|
|
|
30
|
+
export type ConsoleLike = {
|
|
31
|
+
log: (message: string, ...args: unknown[]) => void
|
|
32
|
+
debug: (message: string, ...args: unknown[]) => void
|
|
33
|
+
warn: (message: string, ...args: unknown[]) => void
|
|
34
|
+
error: (message: string, ...args: unknown[]) => void
|
|
35
|
+
}
|
|
36
|
+
|
|
30
37
|
export interface Chunk {
|
|
31
38
|
text: string
|
|
32
39
|
timestamp: [number, number | null]
|
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
AudioRecording,
|
|
7
7
|
AudioStreamStatus,
|
|
8
8
|
BitDepth,
|
|
9
|
+
ConsoleLike,
|
|
9
10
|
RecordingConfig,
|
|
10
11
|
StartRecordingResult,
|
|
11
12
|
} from './ExpoAudioStream.types'
|
|
12
13
|
import { WebRecorder } from './WebRecorder.web'
|
|
13
14
|
import { AudioEventPayload } from './events'
|
|
14
|
-
import { getLogger } from './logger'
|
|
15
15
|
import { encodingToBitDepth } from './utils/encodingToBitDepth'
|
|
16
16
|
import { WavHeaderOptions, writeWavHeader } from './utils/writeWavHeader'
|
|
17
17
|
|
|
@@ -23,12 +23,11 @@ export type EmitAudioEventFunction = (_: EmitAudioEventProps) => void
|
|
|
23
23
|
export type EmitAudioAnalysisFunction = (_: AudioAnalysis) => void
|
|
24
24
|
|
|
25
25
|
export interface ExpoAudioStreamWebProps {
|
|
26
|
+
logger?: ConsoleLike
|
|
26
27
|
audioWorkletUrl: string
|
|
27
28
|
featuresExtratorUrl: string
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
const logger = getLogger('ExpoAudioStreamWeb')
|
|
31
|
-
|
|
32
31
|
export class ExpoAudioStreamWeb extends LegacyEventEmitter {
|
|
33
32
|
customRecorder: WebRecorder | null
|
|
34
33
|
audioChunks: ArrayBuffer[]
|
|
@@ -47,10 +46,12 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
|
|
|
47
46
|
bitDepth: BitDepth // Bit depth of the audio
|
|
48
47
|
audioWorkletUrl: string
|
|
49
48
|
featuresExtratorUrl: string
|
|
49
|
+
logger?: ConsoleLike
|
|
50
50
|
|
|
51
51
|
constructor({
|
|
52
52
|
audioWorkletUrl,
|
|
53
53
|
featuresExtratorUrl,
|
|
54
|
+
logger,
|
|
54
55
|
}: ExpoAudioStreamWebProps) {
|
|
55
56
|
const mockNativeModule = {
|
|
56
57
|
addListener: () => {
|
|
@@ -62,6 +63,7 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
|
|
|
62
63
|
}
|
|
63
64
|
super(mockNativeModule) // Pass the mock native module to the parent class
|
|
64
65
|
|
|
66
|
+
this.logger = logger
|
|
65
67
|
this.customRecorder = null
|
|
66
68
|
this.audioChunks = []
|
|
67
69
|
this.isRecording = false
|
|
@@ -123,7 +125,7 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
|
|
|
123
125
|
this.lastEmittedSize = this.currentSize
|
|
124
126
|
},
|
|
125
127
|
emitAudioAnalysisCallback: (audioAnalysisData: AudioAnalysis) => {
|
|
126
|
-
logger
|
|
128
|
+
this.logger?.log(`Emitted AudioAnalysis:`, audioAnalysisData)
|
|
127
129
|
this.emit('AudioAnalysis', audioAnalysisData)
|
|
128
130
|
},
|
|
129
131
|
})
|
|
@@ -181,7 +183,7 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
|
|
|
181
183
|
const fullPcmBufferArray = await this.customRecorder.stop()
|
|
182
184
|
|
|
183
185
|
// concat all audio chunks
|
|
184
|
-
logger
|
|
186
|
+
this.logger?.debug(`Stopped recording`, fullPcmBufferArray)
|
|
185
187
|
this.isRecording = false
|
|
186
188
|
this.isPaused = false
|
|
187
189
|
this.currentDurationMs = Date.now() - this.recordingStartTime
|
|
@@ -193,7 +195,7 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
|
|
|
193
195
|
numChannels: this.recordingConfig?.channels ?? 1,
|
|
194
196
|
bitDepth: this.bitDepth,
|
|
195
197
|
}
|
|
196
|
-
logger
|
|
198
|
+
this.logger?.debug(`Writing wav header`, wavConfig)
|
|
197
199
|
const wavBuffer = writeWavHeader(wavConfig).slice(0)
|
|
198
200
|
|
|
199
201
|
// Create blob fileUri from audio chunks
|
package/src/WebRecorder.web.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
// src/WebRecorder.ts
|
|
2
|
-
import { buffer } from 'stream/consumers'
|
|
3
2
|
|
|
4
3
|
import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'
|
|
5
|
-
import { RecordingConfig } from './ExpoAudioStream.types'
|
|
4
|
+
import { ConsoleLike, RecordingConfig } from './ExpoAudioStream.types'
|
|
6
5
|
import {
|
|
7
6
|
EmitAudioAnalysisFunction,
|
|
8
7
|
EmitAudioEventFunction,
|
|
9
8
|
} from './ExpoAudioStream.web'
|
|
10
|
-
import { getLogger } from './logger'
|
|
11
9
|
import { convertPCMToFloat32 } from './utils/convertPCMToFloat32'
|
|
12
10
|
import { encodingToBitDepth } from './utils/encodingToBitDepth'
|
|
13
11
|
import { writeWavHeader } from './utils/writeWavHeader'
|
|
@@ -36,7 +34,6 @@ const DEFAULT_WEB_NUMBER_OF_CHANNELS = 1
|
|
|
36
34
|
const DEFAULT_ALGORITHM = 'rms'
|
|
37
35
|
|
|
38
36
|
const TAG = 'WebRecorder'
|
|
39
|
-
const logger = getLogger(TAG)
|
|
40
37
|
|
|
41
38
|
export class WebRecorder {
|
|
42
39
|
private audioContext: AudioContext
|
|
@@ -55,6 +52,7 @@ export class WebRecorder {
|
|
|
55
52
|
private audioBufferSize: number // Keep track of the buffer size
|
|
56
53
|
private audioAnalysisData: AudioAnalysis // Keep updating the full audio analysis data with latest events
|
|
57
54
|
private packetCount: number = 0
|
|
55
|
+
private logger?: ConsoleLike
|
|
58
56
|
|
|
59
57
|
constructor({
|
|
60
58
|
audioContext,
|
|
@@ -63,6 +61,7 @@ export class WebRecorder {
|
|
|
63
61
|
audioWorkletUrl,
|
|
64
62
|
emitAudioEventCallback,
|
|
65
63
|
emitAudioAnalysisCallback,
|
|
64
|
+
logger,
|
|
66
65
|
}: {
|
|
67
66
|
audioContext: AudioContext
|
|
68
67
|
source: MediaStreamAudioSourceNode
|
|
@@ -70,6 +69,7 @@ export class WebRecorder {
|
|
|
70
69
|
audioWorkletUrl: string
|
|
71
70
|
emitAudioEventCallback: EmitAudioEventFunction
|
|
72
71
|
emitAudioAnalysisCallback: EmitAudioAnalysisFunction
|
|
72
|
+
logger?: ConsoleLike
|
|
73
73
|
}) {
|
|
74
74
|
this.audioContext = audioContext
|
|
75
75
|
this.source = source
|
|
@@ -78,11 +78,12 @@ export class WebRecorder {
|
|
|
78
78
|
this.emitAudioAnalysisCallback = emitAudioAnalysisCallback
|
|
79
79
|
this.config = recordingConfig
|
|
80
80
|
this.position = 0
|
|
81
|
+
this.logger = logger
|
|
81
82
|
|
|
82
83
|
const audioContextFormat = this.checkAudioContextFormat({
|
|
83
84
|
sampleRate: this.audioContext.sampleRate,
|
|
84
85
|
})
|
|
85
|
-
logger
|
|
86
|
+
this.logger?.debug('Initialized WebRecorder with config:', {
|
|
86
87
|
sampleRate: audioContextFormat.sampleRate,
|
|
87
88
|
bitDepth: audioContextFormat.bitDepth,
|
|
88
89
|
numberOfChannels: audioContextFormat.numberOfChannels,
|
|
@@ -150,12 +151,12 @@ export class WebRecorder {
|
|
|
150
151
|
const pcmBufferFloat = event.data.recordedData
|
|
151
152
|
|
|
152
153
|
if (!pcmBufferFloat) {
|
|
153
|
-
logger
|
|
154
|
+
this.logger?.warn('Received empty audio buffer', event)
|
|
154
155
|
return
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
// Handle the audio blob (e.g., send it to the server or process it further)
|
|
158
|
-
logger
|
|
159
|
+
this.logger?.debug(
|
|
159
160
|
`Received audio blob from processor len:${pcmBufferFloat?.length}`,
|
|
160
161
|
event
|
|
161
162
|
)
|
|
@@ -220,7 +221,7 @@ export class WebRecorder {
|
|
|
220
221
|
)
|
|
221
222
|
}
|
|
222
223
|
|
|
223
|
-
logger
|
|
224
|
+
this.logger?.debug(
|
|
224
225
|
`WebRecorder initialized -- recordSampleRate=${this.audioContext.sampleRate}`,
|
|
225
226
|
this.config
|
|
226
227
|
)
|
|
@@ -281,7 +282,7 @@ export class WebRecorder {
|
|
|
281
282
|
this.featureExtractorWorker.onerror = (error) => {
|
|
282
283
|
console.error(`[${TAG}] Default Inline worker failed`, error)
|
|
283
284
|
}
|
|
284
|
-
logger
|
|
285
|
+
this.logger?.log('Inline worker initialized successfully')
|
|
285
286
|
} catch (error) {
|
|
286
287
|
console.error(
|
|
287
288
|
`[${TAG}] Failed to initialize Inline Feature Extractor worker`,
|
|
@@ -317,8 +318,8 @@ export class WebRecorder {
|
|
|
317
318
|
}
|
|
318
319
|
}
|
|
319
320
|
// Handle the extracted features (e.g., emit an event or log them)
|
|
320
|
-
logger
|
|
321
|
-
logger
|
|
321
|
+
this.logger?.debug('features event segmentResult', segmentResult)
|
|
322
|
+
this.logger?.debug(
|
|
322
323
|
`features event audioAnalysisData duration=${this.audioAnalysisData.durationMs}`,
|
|
323
324
|
this.audioAnalysisData
|
|
324
325
|
)
|
|
@@ -373,10 +374,10 @@ export class WebRecorder {
|
|
|
373
374
|
(this.audioContext.sampleRate *
|
|
374
375
|
(this.exportBitDepth /
|
|
375
376
|
this.numberOfChannels))
|
|
376
|
-
logger
|
|
377
|
+
this.logger?.debug(
|
|
377
378
|
`Received recorded data -- Duration: ${duration} vs ${rawPCMDataFull.byteLength / this.audioContext.sampleRate} seconds`
|
|
378
379
|
)
|
|
379
|
-
logger
|
|
380
|
+
this.logger?.debug(
|
|
380
381
|
`recordedData.length=${rawPCMDataFull.byteLength} vs transmittedData.length=${this.audioBufferSize}`
|
|
381
382
|
)
|
|
382
383
|
|
|
@@ -448,7 +449,7 @@ export class WebRecorder {
|
|
|
448
449
|
bufferSource.buffer = audioBuffer
|
|
449
450
|
bufferSource.connect(this.audioContext.destination)
|
|
450
451
|
bufferSource.start()
|
|
451
|
-
logger
|
|
452
|
+
this.logger?.debug('Playing recorded data', recordedData)
|
|
452
453
|
} catch (error) {
|
|
453
454
|
console.error(`[${TAG}] Failed to play recorded data:`, error)
|
|
454
455
|
}
|
package/src/events.ts
CHANGED
|
@@ -4,10 +4,8 @@ import { LegacyEventEmitter, type EventSubscription } from 'expo-modules-core'
|
|
|
4
4
|
|
|
5
5
|
import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'
|
|
6
6
|
import ExpoAudioStreamModule from './ExpoAudioStreamModule'
|
|
7
|
-
import { getLogger } from './logger'
|
|
8
7
|
|
|
9
8
|
const emitter = new LegacyEventEmitter(ExpoAudioStreamModule)
|
|
10
|
-
const logger = getLogger('events')
|
|
11
9
|
|
|
12
10
|
export interface AudioEventPayload {
|
|
13
11
|
encoded?: string
|
|
@@ -24,7 +22,6 @@ export interface AudioEventPayload {
|
|
|
24
22
|
export function addAudioEventListener(
|
|
25
23
|
listener: (event: AudioEventPayload) => Promise<void>
|
|
26
24
|
): EventSubscription {
|
|
27
|
-
logger.log('Adding listener for AudioData event')
|
|
28
25
|
return emitter.addListener<AudioEventPayload>('AudioData', listener)
|
|
29
26
|
}
|
|
30
27
|
|
|
@@ -34,6 +31,5 @@ export interface AudioAnalysisEvent extends AudioAnalysis {}
|
|
|
34
31
|
export function addAudioAnalysisListener(
|
|
35
32
|
listener: (event: AudioAnalysisEvent) => Promise<void>
|
|
36
33
|
): EventSubscription {
|
|
37
|
-
logger.log('Adding listener for AudioAnalysis event')
|
|
38
34
|
return emitter.addListener<AudioAnalysisEvent>('AudioAnalysis', listener)
|
|
39
35
|
}
|
package/src/useAudioRecorder.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/useAudioRecorder.ts
|
|
2
|
-
import {
|
|
2
|
+
import { EventSubscription, Platform } from 'expo-modules-core'
|
|
3
3
|
import { useCallback, useEffect, useReducer, useRef } from 'react'
|
|
4
4
|
|
|
5
5
|
import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
AudioDataEvent,
|
|
8
8
|
AudioRecording,
|
|
9
9
|
AudioStreamStatus,
|
|
10
|
+
ConsoleLike,
|
|
10
11
|
RecordingConfig,
|
|
11
12
|
StartRecordingResult,
|
|
12
13
|
} from './ExpoAudioStream.types'
|
|
@@ -16,12 +17,9 @@ import {
|
|
|
16
17
|
addAudioEventListener,
|
|
17
18
|
AudioEventPayload,
|
|
18
19
|
} from './events'
|
|
19
|
-
import { getLogger } from './logger'
|
|
20
20
|
|
|
21
|
-
const TAG = 'useAudioRecorder'
|
|
22
|
-
const logger = getLogger(TAG)
|
|
23
21
|
export interface UseAudioRecorderProps {
|
|
24
|
-
|
|
22
|
+
logger?: ConsoleLike
|
|
25
23
|
audioWorkletUrl?: string
|
|
26
24
|
featuresExtratorUrl?: string
|
|
27
25
|
}
|
|
@@ -122,7 +120,7 @@ interface HandleAudioAnalysisProps {
|
|
|
122
120
|
}
|
|
123
121
|
|
|
124
122
|
export function useAudioRecorder({
|
|
125
|
-
|
|
123
|
+
logger,
|
|
126
124
|
audioWorkletUrl,
|
|
127
125
|
featuresExtratorUrl,
|
|
128
126
|
}: UseAudioRecorderProps = {}): UseAudioRecorderState {
|
|
@@ -141,12 +139,15 @@ export function useAudioRecorder({
|
|
|
141
139
|
const fullAnalysisRef = useRef<AudioAnalysis>({
|
|
142
140
|
...defaultAnalysis,
|
|
143
141
|
})
|
|
144
|
-
const globalIdRef = useRef(0);
|
|
145
142
|
|
|
146
143
|
// Instantiate the module for web with URLs
|
|
147
144
|
const ExpoAudioStream =
|
|
148
145
|
Platform.OS === 'web'
|
|
149
|
-
? ExpoAudioStreamModule({
|
|
146
|
+
? ExpoAudioStreamModule({
|
|
147
|
+
audioWorkletUrl,
|
|
148
|
+
featuresExtratorUrl,
|
|
149
|
+
logger,
|
|
150
|
+
})
|
|
150
151
|
: ExpoAudioStreamModule
|
|
151
152
|
|
|
152
153
|
const onAudioStreamRef = useRef<
|
|
@@ -164,7 +165,7 @@ export function useAudioRecorder({
|
|
|
164
165
|
|
|
165
166
|
const maxDuration = visualizationDuration
|
|
166
167
|
|
|
167
|
-
logger
|
|
168
|
+
logger?.debug(
|
|
168
169
|
`[handleAudioAnalysis] Received audio analysis: maxDuration=${maxDuration} analysis.dataPoints=${analysis.dataPoints.length} analysisData.dataPoints=${savedAnalysisData.dataPoints.length}`,
|
|
169
170
|
analysis
|
|
170
171
|
)
|
|
@@ -186,7 +187,7 @@ export function useAudioRecorder({
|
|
|
186
187
|
const maxDataPoints =
|
|
187
188
|
(pointsPerSecond * visualizationDuration) / 1000
|
|
188
189
|
|
|
189
|
-
logger
|
|
190
|
+
logger?.debug(
|
|
190
191
|
`[handleAudioAnalysis] Combined data points before trimming: pointsPerSecond=${pointsPerSecond} visualizationDuration=${visualizationDuration} combinedDataPointsLength=${combinedDataPoints.length} vs maxDataPoints=${maxDataPoints}`
|
|
191
192
|
)
|
|
192
193
|
|
|
@@ -230,7 +231,7 @@ export function useAudioRecorder({
|
|
|
230
231
|
max: newMax,
|
|
231
232
|
}
|
|
232
233
|
|
|
233
|
-
logger
|
|
234
|
+
logger?.debug(
|
|
234
235
|
`[handleAudioAnalysis] Updated analysis data: durationMs=${savedAnalysisData.durationMs}`,
|
|
235
236
|
savedAnalysisData
|
|
236
237
|
)
|
|
@@ -261,7 +262,7 @@ export function useAudioRecorder({
|
|
|
261
262
|
mimeType,
|
|
262
263
|
buffer,
|
|
263
264
|
} = eventData
|
|
264
|
-
logger
|
|
265
|
+
logger?.debug(`[handleAudioEvent] Received audio event:`, {
|
|
265
266
|
fileUri,
|
|
266
267
|
deltaSize,
|
|
267
268
|
totalSize,
|
|
@@ -280,7 +281,7 @@ export function useAudioRecorder({
|
|
|
280
281
|
if (Platform.OS !== 'web') {
|
|
281
282
|
// Read the audio file as a base64 string for comparison
|
|
282
283
|
if (!encoded) {
|
|
283
|
-
|
|
284
|
+
logger?.error(`Encoded audio data is missing`)
|
|
284
285
|
throw new Error('Encoded audio data is missing')
|
|
285
286
|
}
|
|
286
287
|
onAudioStreamRef.current?.({
|
|
@@ -300,13 +301,13 @@ export function useAudioRecorder({
|
|
|
300
301
|
totalSize,
|
|
301
302
|
}
|
|
302
303
|
onAudioStreamRef.current?.(webEvent)
|
|
303
|
-
logger
|
|
304
|
+
logger?.debug(
|
|
304
305
|
`[handleAudioEvent] Audio data sent to onAudioStream`,
|
|
305
306
|
webEvent
|
|
306
307
|
)
|
|
307
308
|
}
|
|
308
309
|
} catch (error) {
|
|
309
|
-
|
|
310
|
+
logger?.error(`Error processing audio event:`, error)
|
|
310
311
|
}
|
|
311
312
|
},
|
|
312
313
|
[]
|
|
@@ -315,11 +316,9 @@ export function useAudioRecorder({
|
|
|
315
316
|
const checkStatus = useCallback(async () => {
|
|
316
317
|
try {
|
|
317
318
|
const status: AudioStreamStatus = ExpoAudioStream.status()
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
)
|
|
322
|
-
}
|
|
319
|
+
logger?.debug(
|
|
320
|
+
`Status: paused: ${status.isPaused} durationMs: ${status.durationMs} size: ${status.size}`
|
|
321
|
+
)
|
|
323
322
|
|
|
324
323
|
// Check and update recording state
|
|
325
324
|
if (
|
|
@@ -349,13 +348,13 @@ export function useAudioRecorder({
|
|
|
349
348
|
})
|
|
350
349
|
}
|
|
351
350
|
} catch (error) {
|
|
352
|
-
|
|
351
|
+
logger?.error(`Error getting status:`, error)
|
|
353
352
|
}
|
|
354
353
|
}, [state.isRecording])
|
|
355
354
|
|
|
356
355
|
const startRecording = useCallback(
|
|
357
356
|
async (recordingOptions: RecordingConfig) => {
|
|
358
|
-
logger
|
|
357
|
+
logger?.debug(`start recoding`, recordingOptions)
|
|
359
358
|
|
|
360
359
|
analysisRef.current = { ...defaultAnalysis } // Reset analysis data
|
|
361
360
|
fullAnalysisRef.current = { ...defaultAnalysis }
|
|
@@ -366,10 +365,7 @@ export function useAudioRecorder({
|
|
|
366
365
|
if (typeof onAudioStream === 'function') {
|
|
367
366
|
onAudioStreamRef.current = onAudioStream
|
|
368
367
|
} else {
|
|
369
|
-
|
|
370
|
-
`${TAG} onAudioStream is not a function`,
|
|
371
|
-
onAudioStream
|
|
372
|
-
)
|
|
368
|
+
logger?.warn(`onAudioStream is not a function`, onAudioStream)
|
|
373
369
|
onAudioStreamRef.current = null
|
|
374
370
|
}
|
|
375
371
|
const startResult: StartRecordingResult =
|
|
@@ -377,7 +373,7 @@ export function useAudioRecorder({
|
|
|
377
373
|
dispatch({ type: 'START' })
|
|
378
374
|
|
|
379
375
|
if (enableProcessing) {
|
|
380
|
-
logger
|
|
376
|
+
logger?.debug(`Enabling audio analysis listener`)
|
|
381
377
|
const listener = addAudioAnalysisListener(
|
|
382
378
|
async (analysisData) => {
|
|
383
379
|
try {
|
|
@@ -386,8 +382,8 @@ export function useAudioRecorder({
|
|
|
386
382
|
visualizationDuration: maxRecentDataDuration,
|
|
387
383
|
})
|
|
388
384
|
} catch (error) {
|
|
389
|
-
|
|
390
|
-
|
|
385
|
+
logger?.warn(
|
|
386
|
+
`Error processing audio analysis:`,
|
|
391
387
|
error
|
|
392
388
|
)
|
|
393
389
|
}
|
|
@@ -403,7 +399,7 @@ export function useAudioRecorder({
|
|
|
403
399
|
)
|
|
404
400
|
|
|
405
401
|
const stopRecording = useCallback(async () => {
|
|
406
|
-
logger
|
|
402
|
+
logger?.debug(`stoping recording`)
|
|
407
403
|
|
|
408
404
|
const stopResult: AudioRecording = await ExpoAudioStream.stopRecording()
|
|
409
405
|
stopResult.analysisData = fullAnalysisRef.current
|
|
@@ -413,20 +409,20 @@ export function useAudioRecorder({
|
|
|
413
409
|
analysisListenerRef.current = null
|
|
414
410
|
}
|
|
415
411
|
onAudioStreamRef.current = null
|
|
416
|
-
logger
|
|
412
|
+
logger?.debug(`recording stopped`, stopResult)
|
|
417
413
|
dispatch({ type: 'STOP' })
|
|
418
414
|
return stopResult
|
|
419
415
|
}, [dispatch])
|
|
420
416
|
|
|
421
417
|
const pauseRecording = useCallback(async () => {
|
|
422
|
-
logger
|
|
418
|
+
logger?.debug(`pause recording`)
|
|
423
419
|
const pauseResult = await ExpoAudioStream.pauseRecording()
|
|
424
420
|
dispatch({ type: 'PAUSE' })
|
|
425
421
|
return pauseResult
|
|
426
422
|
}, [dispatch])
|
|
427
423
|
|
|
428
424
|
const resumeRecording = useCallback(async () => {
|
|
429
|
-
logger
|
|
425
|
+
logger?.debug(`resume recording`)
|
|
430
426
|
const resumeResult = await ExpoAudioStream.resumeRecording()
|
|
431
427
|
dispatch({ type: 'RESUME' })
|
|
432
428
|
return resumeResult
|
|
@@ -445,10 +441,10 @@ export function useAudioRecorder({
|
|
|
445
441
|
}, [checkStatus, state.isRecording, state.isPaused])
|
|
446
442
|
|
|
447
443
|
useEffect(() => {
|
|
448
|
-
logger
|
|
444
|
+
logger?.debug(`Registering audio event listener`)
|
|
449
445
|
const subscribeAudio = addAudioEventListener(handleAudioEvent)
|
|
450
446
|
|
|
451
|
-
logger
|
|
447
|
+
logger?.debug(
|
|
452
448
|
`Subscribed to audio event listener and analysis listener`,
|
|
453
449
|
{
|
|
454
450
|
subscribeAudio,
|
|
@@ -456,7 +452,7 @@ export function useAudioRecorder({
|
|
|
456
452
|
)
|
|
457
453
|
|
|
458
454
|
return () => {
|
|
459
|
-
logger
|
|
455
|
+
logger?.debug(`Removing audio event listener`)
|
|
460
456
|
subscribeAudio.remove()
|
|
461
457
|
}
|
|
462
458
|
}, [handleAudioEvent, handleAudioAnalysis])
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
+
import { ConsoleLike } from '../ExpoAudioStream.types'
|
|
1
2
|
import { getWavFileInfo, WavFileInfo } from './getWavFileInfo'
|
|
2
|
-
import { getLogger } from '../logger'
|
|
3
3
|
|
|
4
4
|
export const WAV_HEADER_SIZE = 44
|
|
5
5
|
|
|
6
|
-
const logger = getLogger('convertPCMToFloat32')
|
|
7
|
-
|
|
8
6
|
const convertSample = (
|
|
9
7
|
dataView: DataView,
|
|
10
8
|
offset: number,
|
|
@@ -35,13 +33,15 @@ export const convertPCMToFloat32 = async ({
|
|
|
35
33
|
bitDepth,
|
|
36
34
|
buffer,
|
|
37
35
|
skipWavHeader = false,
|
|
36
|
+
logger,
|
|
38
37
|
}: {
|
|
39
38
|
buffer: ArrayBuffer
|
|
40
39
|
bitDepth: number
|
|
41
40
|
skipWavHeader?: boolean
|
|
41
|
+
logger?: ConsoleLike
|
|
42
42
|
}): Promise<{ pcmValues: Float32Array; min: number; max: number }> => {
|
|
43
43
|
try {
|
|
44
|
-
logger
|
|
44
|
+
logger?.debug(
|
|
45
45
|
`Converting PCM to Float32: bitDepth: ${bitDepth}, buffer.byteLength: ${buffer.byteLength}`
|
|
46
46
|
)
|
|
47
47
|
const dataView = new DataView(buffer)
|
|
@@ -69,7 +69,7 @@ export const convertPCMToFloat32 = async ({
|
|
|
69
69
|
|
|
70
70
|
return { pcmValues: float32Array, min, max }
|
|
71
71
|
} catch (error: unknown) {
|
|
72
|
-
logger
|
|
72
|
+
logger?.error(`Error converting PCM to Float32`, error)
|
|
73
73
|
return { pcmValues: new Float32Array(), min: 0, max: 0 }
|
|
74
74
|
}
|
|
75
75
|
}
|
package/src/logger.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// packages/expo-audio-stream/src/logger.ts
|
|
2
|
-
import { getLogger as siteedGetLogger } from '@siteed/react-native-logger'
|
|
3
|
-
|
|
4
|
-
import { DEBUG_NAMESPACE } from './constants'
|
|
5
|
-
|
|
6
|
-
type ConsoleLike = {
|
|
7
|
-
log: (message: string, ...args: unknown[]) => void
|
|
8
|
-
debug: (message: string, ...args: unknown[]) => void
|
|
9
|
-
warn: (message: string, ...args: unknown[]) => void
|
|
10
|
-
error: (message: string, ...args: unknown[]) => void
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const getLogger = (tag: string): ConsoleLike => {
|
|
14
|
-
const baseLogger = siteedGetLogger(`${DEBUG_NAMESPACE}:${tag}`)
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
log: (...args: unknown[]) => baseLogger.log(...(args as [unknown])),
|
|
18
|
-
debug: (...args: unknown[]) => baseLogger.debug(...(args as [unknown])),
|
|
19
|
-
error: (...args: unknown[]) => baseLogger.error(...(args as [unknown])),
|
|
20
|
-
warn: (...args: unknown[]) => baseLogger.warn(...(args as [unknown])),
|
|
21
|
-
}
|
|
22
|
-
}
|