@siteed/audio-studio 3.0.0 → 3.0.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/CHANGELOG.md +1073 -414
  2. package/README.md +1 -1
  3. package/android/src/main/CMakeLists.txt +3 -0
  4. package/build/cjs/AudioAnalysis/audioFeaturesWasm.js +7 -155
  5. package/build/cjs/AudioAnalysis/audioFeaturesWasm.js.map +1 -1
  6. package/build/cjs/AudioAnalysis/audioFeaturesWasm.web.js +164 -0
  7. package/build/cjs/AudioAnalysis/audioFeaturesWasm.web.js.map +1 -0
  8. package/build/cjs/AudioAnalysis/melSpectrogramWasm.js +8 -140
  9. package/build/cjs/AudioAnalysis/melSpectrogramWasm.js.map +1 -1
  10. package/build/cjs/AudioAnalysis/melSpectrogramWasm.web.js +149 -0
  11. package/build/cjs/AudioAnalysis/melSpectrogramWasm.web.js.map +1 -0
  12. package/build/cjs/prebuilt/wasm/mel-spectrogram.js +18 -0
  13. package/build/esm/AudioAnalysis/audioFeaturesWasm.js +7 -122
  14. package/build/esm/AudioAnalysis/audioFeaturesWasm.js.map +1 -1
  15. package/build/esm/AudioAnalysis/audioFeaturesWasm.web.js +126 -0
  16. package/build/esm/AudioAnalysis/audioFeaturesWasm.web.js.map +1 -0
  17. package/build/esm/AudioAnalysis/melSpectrogramWasm.js +8 -107
  18. package/build/esm/AudioAnalysis/melSpectrogramWasm.js.map +1 -1
  19. package/build/esm/AudioAnalysis/melSpectrogramWasm.web.js +111 -0
  20. package/build/esm/AudioAnalysis/melSpectrogramWasm.web.js.map +1 -0
  21. package/build/esm/prebuilt/wasm/mel-spectrogram.js +18 -0
  22. package/build/types/AudioAnalysis/audioFeaturesWasm.d.ts +3 -15
  23. package/build/types/AudioAnalysis/audioFeaturesWasm.d.ts.map +1 -1
  24. package/build/types/AudioAnalysis/audioFeaturesWasm.web.d.ts +24 -0
  25. package/build/types/AudioAnalysis/audioFeaturesWasm.web.d.ts.map +1 -0
  26. package/build/types/AudioAnalysis/melSpectrogramWasm.d.ts +3 -15
  27. package/build/types/AudioAnalysis/melSpectrogramWasm.d.ts.map +1 -1
  28. package/build/types/AudioAnalysis/melSpectrogramWasm.web.d.ts +16 -0
  29. package/build/types/AudioAnalysis/melSpectrogramWasm.web.d.ts.map +1 -0
  30. package/package.json +3 -2
  31. package/src/AudioAnalysis/audioFeaturesWasm.ts +18 -179
  32. package/src/AudioAnalysis/audioFeaturesWasm.web.ts +200 -0
  33. package/src/AudioAnalysis/melSpectrogramWasm.ts +23 -169
  34. package/src/AudioAnalysis/melSpectrogramWasm.web.ts +179 -0
@@ -1,179 +1,33 @@
1
- import type { MelSpectrogramWasmModule } from './mel-spectrogram-wasm'
1
+ // Native stub WASM mel spectrogram is web-only.
2
+ // These functions are only called in web contexts; on native, the C++ TurboModule handles mel spectrograms.
2
3
 
3
- let modulePromise: Promise<MelSpectrogramWasmModule> | null = null
4
-
5
- function getModule(): Promise<MelSpectrogramWasmModule> {
6
- if (!modulePromise) {
7
- modulePromise = (async () => {
8
- // Dynamic import of the prebuilt SINGLE_FILE Emscripten module
9
- // @ts-expect-error -- prebuilt Emscripten JS glue has no .d.ts
10
- const mod = await import('../../prebuilt/wasm/mel-spectrogram.js')
11
- const factory = mod.default ?? mod
12
- return factory() as Promise<MelSpectrogramWasmModule>
13
- })().catch((err) => {
14
- modulePromise = null
15
- throw err
16
- })
17
- }
18
- return modulePromise
19
- }
20
-
21
- // --- Streaming (per-frame) API for live mel spectrogram ---
22
-
23
- let streamingModule: MelSpectrogramWasmModule | null = null
24
- let streamingNMels = 0
25
- let streamingFramePtr = 0
26
- let streamingMelPtr = 0
27
- let streamingFrameCapacity = 0
28
-
29
- /**
30
- * Initialise the WASM streaming processor. Call once before computeMelFrame().
31
- * Re-initialises only when config changes.
32
- */
33
4
  export async function initMelStreamingWasm(
34
- sampleRate: number,
35
- nMels = 128,
36
- fftLength = 2048,
37
- windowSizeSamples = 400,
38
- hopLengthSamples = 160,
39
- fMin = 0,
40
- fMax = 0
5
+ _sampleRate: number,
6
+ _nMels?: number,
7
+ _fftLength?: number,
8
+ _windowSizeSamples?: number,
9
+ _hopLengthSamples?: number,
10
+ _fMin?: number,
11
+ _fMax?: number
41
12
  ): Promise<void> {
42
- const Module = await getModule()
43
- streamingModule = Module
44
- const actualFMax = fMax > 0 ? fMax : sampleRate / 2
45
- Module._mel_spectrogram_init(
46
- sampleRate,
47
- fftLength,
48
- windowSizeSamples,
49
- hopLengthSamples,
50
- nMels,
51
- fMin,
52
- actualFMax,
53
- 0 /* hann */
54
- )
55
- streamingNMels = nMels
56
-
57
- // Pre-allocate output buffer (fixed size)
58
- if (streamingMelPtr) Module._free(streamingMelPtr)
59
- streamingMelPtr = Module._malloc(nMels * 4)
60
-
61
- // Frame input buffer allocated on demand in computeMelFrame
62
- streamingFrameCapacity = 0
63
- streamingFramePtr = 0
13
+ throw new Error('WASM mel spectrogram is not available on native')
64
14
  }
65
15
 
66
- /**
67
- * Compute a single mel spectrogram frame from raw PCM samples via WASM C++.
68
- * Returns null if not initialised or on error.
69
- */
70
- export function computeMelFrameWasm(samples: Float32Array): number[] | null {
71
- if (!streamingModule || !streamingMelPtr) return null
72
- const Module = streamingModule
73
-
74
- // (Re-)allocate frame input buffer if needed
75
- if (samples.length > streamingFrameCapacity) {
76
- if (streamingFramePtr) Module._free(streamingFramePtr)
77
- streamingFramePtr = Module._malloc(samples.length * 4)
78
- streamingFrameCapacity = samples.length
79
- }
80
-
81
- // Copy samples to WASM heap
82
- Module.HEAPF32.set(samples, streamingFramePtr >> 2)
83
-
84
- const ok = Module._mel_spectrogram_compute_frame(
85
- streamingFramePtr,
86
- samples.length,
87
- streamingMelPtr
88
- )
89
- if (!ok) return null
90
-
91
- // Read mel output from WASM heap
92
- const offset = streamingMelPtr >> 2
93
- const result = new Array(streamingNMels)
94
- for (let i = 0; i < streamingNMels; i++) {
95
- result[i] = Module.HEAPF32[offset + i]
96
- }
97
- return result
16
+ export function computeMelFrameWasm(_samples: Float32Array): number[] | null {
17
+ return null
98
18
  }
99
19
 
100
- /**
101
- * Computes a mel spectrogram via the WASM-compiled C++ implementation.
102
- * Lazy-loads the WASM module on first call.
103
- */
104
20
  export async function computeMelSpectrogramWasm(
105
- audioData: Float32Array,
106
- sampleRate: number,
107
- nMels: number,
108
- windowSizeSamples: number,
109
- hopLengthSamples: number,
110
- fMin: number,
111
- fMax: number,
112
- windowType: 'hann' | 'hamming',
113
- normalize: boolean,
114
- logScale: boolean
21
+ _audioData: Float32Array,
22
+ _sampleRate: number,
23
+ _nMels: number,
24
+ _windowSizeSamples: number,
25
+ _hopLengthSamples: number,
26
+ _fMin: number,
27
+ _fMax: number,
28
+ _windowType: 'hann' | 'hamming',
29
+ _normalize: boolean,
30
+ _logScale: boolean
115
31
  ): Promise<number[][]> {
116
- const Module = await getModule()
117
-
118
- const fftLength = 2048
119
- const windowTypeInt = windowType === 'hamming' ? 1 : 0
120
-
121
- // Allocate input buffer on WASM heap
122
- const numSamples = audioData.length
123
- const inputPtr = Module._malloc(numSamples * 4) // 4 bytes per float
124
- Module.HEAPF32.set(audioData, inputPtr >> 2)
125
-
126
- // Call the C bridge
127
- const resultPtr = Module._mel_spectrogram_compute(
128
- inputPtr,
129
- numSamples,
130
- sampleRate,
131
- fftLength,
132
- windowSizeSamples,
133
- hopLengthSamples,
134
- nMels,
135
- fMin,
136
- fMax,
137
- windowTypeInt,
138
- logScale ? 1 : 0,
139
- normalize ? 1 : 0
140
- )
141
-
142
- // Free input buffer
143
- Module._free(inputPtr)
144
-
145
- if (resultPtr === 0) {
146
- throw new Error(
147
- 'mel_spectrogram_compute returned null (too few samples?)'
148
- )
149
- }
150
-
151
- // Read CMelSpectrogramResult struct (wasm32 pointers are 4 bytes)
152
- // struct layout: { float* data (offset 0), int timeSteps (offset 4), int nMels (offset 8) }
153
- const dataPtr = Module.getValue(resultPtr, 'i32')
154
- const timeSteps = Module.getValue(resultPtr + 4, 'i32')
155
- const resultNMels = Module.getValue(resultPtr + 8, 'i32')
156
-
157
- if (!dataPtr || timeSteps <= 0 || resultNMels <= 0) {
158
- Module._mel_spectrogram_free(resultPtr)
159
- throw new Error(
160
- 'mel_spectrogram_compute returned invalid result struct'
161
- )
162
- }
163
-
164
- // Copy spectrogram data to JS arrays
165
- const spectrogram: number[][] = []
166
- const heapOffset = dataPtr >> 2 // float32 offset into HEAPF32
167
- for (let t = 0; t < timeSteps; t++) {
168
- const row = new Array(resultNMels)
169
- for (let m = 0; m < resultNMels; m++) {
170
- row[m] = Module.HEAPF32[heapOffset + t * resultNMels + m]
171
- }
172
- spectrogram.push(row)
173
- }
174
-
175
- // Free the C result
176
- Module._mel_spectrogram_free(resultPtr)
177
-
178
- return spectrogram
32
+ throw new Error('WASM mel spectrogram is not available on native')
179
33
  }
@@ -0,0 +1,179 @@
1
+ import type { MelSpectrogramWasmModule } from './mel-spectrogram-wasm'
2
+
3
+ let modulePromise: Promise<MelSpectrogramWasmModule> | null = null
4
+
5
+ function getModule(): Promise<MelSpectrogramWasmModule> {
6
+ if (!modulePromise) {
7
+ modulePromise = (async () => {
8
+ // Dynamic import of the prebuilt SINGLE_FILE Emscripten module
9
+ // @ts-expect-error -- prebuilt Emscripten JS glue has no .d.ts
10
+ const mod = await import('../../prebuilt/wasm/mel-spectrogram.js')
11
+ const factory = mod.default ?? mod
12
+ return factory() as Promise<MelSpectrogramWasmModule>
13
+ })().catch((err) => {
14
+ modulePromise = null
15
+ throw err
16
+ })
17
+ }
18
+ return modulePromise
19
+ }
20
+
21
+ // --- Streaming (per-frame) API for live mel spectrogram ---
22
+
23
+ let streamingModule: MelSpectrogramWasmModule | null = null
24
+ let streamingNMels = 0
25
+ let streamingFramePtr = 0
26
+ let streamingMelPtr = 0
27
+ let streamingFrameCapacity = 0
28
+
29
+ /**
30
+ * Initialise the WASM streaming processor. Call once before computeMelFrame().
31
+ * Re-initialises only when config changes.
32
+ */
33
+ export async function initMelStreamingWasm(
34
+ sampleRate: number,
35
+ nMels = 128,
36
+ fftLength = 2048,
37
+ windowSizeSamples = 400,
38
+ hopLengthSamples = 160,
39
+ fMin = 0,
40
+ fMax = 0
41
+ ): Promise<void> {
42
+ const Module = await getModule()
43
+ streamingModule = Module
44
+ const actualFMax = fMax > 0 ? fMax : sampleRate / 2
45
+ Module._mel_spectrogram_init(
46
+ sampleRate,
47
+ fftLength,
48
+ windowSizeSamples,
49
+ hopLengthSamples,
50
+ nMels,
51
+ fMin,
52
+ actualFMax,
53
+ 0 /* hann */
54
+ )
55
+ streamingNMels = nMels
56
+
57
+ // Pre-allocate output buffer (fixed size)
58
+ if (streamingMelPtr) Module._free(streamingMelPtr)
59
+ streamingMelPtr = Module._malloc(nMels * 4)
60
+
61
+ // Frame input buffer allocated on demand in computeMelFrame
62
+ streamingFrameCapacity = 0
63
+ streamingFramePtr = 0
64
+ }
65
+
66
+ /**
67
+ * Compute a single mel spectrogram frame from raw PCM samples via WASM C++.
68
+ * Returns null if not initialised or on error.
69
+ */
70
+ export function computeMelFrameWasm(samples: Float32Array): number[] | null {
71
+ if (!streamingModule || !streamingMelPtr) return null
72
+ const Module = streamingModule
73
+
74
+ // (Re-)allocate frame input buffer if needed
75
+ if (samples.length > streamingFrameCapacity) {
76
+ if (streamingFramePtr) Module._free(streamingFramePtr)
77
+ streamingFramePtr = Module._malloc(samples.length * 4)
78
+ streamingFrameCapacity = samples.length
79
+ }
80
+
81
+ // Copy samples to WASM heap
82
+ Module.HEAPF32.set(samples, streamingFramePtr >> 2)
83
+
84
+ const ok = Module._mel_spectrogram_compute_frame(
85
+ streamingFramePtr,
86
+ samples.length,
87
+ streamingMelPtr
88
+ )
89
+ if (!ok) return null
90
+
91
+ // Read mel output from WASM heap
92
+ const offset = streamingMelPtr >> 2
93
+ const result = new Array(streamingNMels)
94
+ for (let i = 0; i < streamingNMels; i++) {
95
+ result[i] = Module.HEAPF32[offset + i]
96
+ }
97
+ return result
98
+ }
99
+
100
+ /**
101
+ * Computes a mel spectrogram via the WASM-compiled C++ implementation.
102
+ * Lazy-loads the WASM module on first call.
103
+ */
104
+ export async function computeMelSpectrogramWasm(
105
+ audioData: Float32Array,
106
+ sampleRate: number,
107
+ nMels: number,
108
+ windowSizeSamples: number,
109
+ hopLengthSamples: number,
110
+ fMin: number,
111
+ fMax: number,
112
+ windowType: 'hann' | 'hamming',
113
+ normalize: boolean,
114
+ logScale: boolean
115
+ ): Promise<number[][]> {
116
+ const Module = await getModule()
117
+
118
+ const fftLength = 2048
119
+ const windowTypeInt = windowType === 'hamming' ? 1 : 0
120
+
121
+ // Allocate input buffer on WASM heap
122
+ const numSamples = audioData.length
123
+ const inputPtr = Module._malloc(numSamples * 4) // 4 bytes per float
124
+ Module.HEAPF32.set(audioData, inputPtr >> 2)
125
+
126
+ // Call the C bridge
127
+ const resultPtr = Module._mel_spectrogram_compute(
128
+ inputPtr,
129
+ numSamples,
130
+ sampleRate,
131
+ fftLength,
132
+ windowSizeSamples,
133
+ hopLengthSamples,
134
+ nMels,
135
+ fMin,
136
+ fMax,
137
+ windowTypeInt,
138
+ logScale ? 1 : 0,
139
+ normalize ? 1 : 0
140
+ )
141
+
142
+ // Free input buffer
143
+ Module._free(inputPtr)
144
+
145
+ if (resultPtr === 0) {
146
+ throw new Error(
147
+ 'mel_spectrogram_compute returned null (too few samples?)'
148
+ )
149
+ }
150
+
151
+ // Read CMelSpectrogramResult struct (wasm32 pointers are 4 bytes)
152
+ // struct layout: { float* data (offset 0), int timeSteps (offset 4), int nMels (offset 8) }
153
+ const dataPtr = Module.getValue(resultPtr, 'i32')
154
+ const timeSteps = Module.getValue(resultPtr + 4, 'i32')
155
+ const resultNMels = Module.getValue(resultPtr + 8, 'i32')
156
+
157
+ if (!dataPtr || timeSteps <= 0 || resultNMels <= 0) {
158
+ Module._mel_spectrogram_free(resultPtr)
159
+ throw new Error(
160
+ 'mel_spectrogram_compute returned invalid result struct'
161
+ )
162
+ }
163
+
164
+ // Copy spectrogram data to JS arrays
165
+ const spectrogram: number[][] = []
166
+ const heapOffset = dataPtr >> 2 // float32 offset into HEAPF32
167
+ for (let t = 0; t < timeSteps; t++) {
168
+ const row = new Array(resultNMels)
169
+ for (let m = 0; m < resultNMels; m++) {
170
+ row[m] = Module.HEAPF32[heapOffset + t * resultNMels + m]
171
+ }
172
+ spectrogram.push(row)
173
+ }
174
+
175
+ // Free the C result
176
+ Module._mel_spectrogram_free(resultPtr)
177
+
178
+ return spectrogram
179
+ }