@siteed/audio-studio 3.0.2 → 3.0.4

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 (89) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/android/src/main/java/net/siteed/audiostudio/AudioRecorderManager.kt +41 -35
  3. package/android/src/main/java/net/siteed/audiostudio/AudioStudioModule.kt +500 -479
  4. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
  5. package/build/cjs/AudioAnalysis/audioFeaturesWasm.js +10 -7
  6. package/build/cjs/AudioAnalysis/audioFeaturesWasm.js.map +1 -1
  7. package/build/cjs/AudioAnalysis/audioFeaturesWasm.web.js +78 -97
  8. package/build/cjs/AudioAnalysis/audioFeaturesWasm.web.js.map +1 -1
  9. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js +15 -12
  10. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js.map +1 -1
  11. package/build/cjs/AudioAnalysis/extractAudioData.js +144 -2
  12. package/build/cjs/AudioAnalysis/extractAudioData.js.map +1 -1
  13. package/build/cjs/AudioAnalysis/melSpectrogramWasm.web.js +9 -56
  14. package/build/cjs/AudioAnalysis/melSpectrogramWasm.web.js.map +1 -1
  15. package/build/cjs/AudioAnalysis/wasmConfig.js +4 -4
  16. package/build/cjs/AudioAnalysis/wasmConfig.js.map +1 -1
  17. package/build/cjs/AudioAnalysis/wasmLoader.web.js +79 -0
  18. package/build/cjs/AudioAnalysis/wasmLoader.web.js.map +1 -0
  19. package/build/cjs/AudioStudioModule.js +4 -599
  20. package/build/cjs/AudioStudioModule.js.map +1 -1
  21. package/build/cjs/trimAudio.js +227 -0
  22. package/build/cjs/trimAudio.js.map +1 -1
  23. package/build/cjs/utils/encodeCompressedAudio.web.js +65 -0
  24. package/build/cjs/utils/encodeCompressedAudio.web.js.map +1 -0
  25. package/build/cjs/utils/resampleAudioBuffer.web.js +25 -0
  26. package/build/cjs/utils/resampleAudioBuffer.web.js.map +1 -0
  27. package/build/esm/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
  28. package/build/esm/AudioAnalysis/audioFeaturesWasm.js +8 -5
  29. package/build/esm/AudioAnalysis/audioFeaturesWasm.js.map +1 -1
  30. package/build/esm/AudioAnalysis/audioFeaturesWasm.web.js +76 -62
  31. package/build/esm/AudioAnalysis/audioFeaturesWasm.web.js.map +1 -1
  32. package/build/esm/AudioAnalysis/extractAudioAnalysis.js +15 -12
  33. package/build/esm/AudioAnalysis/extractAudioAnalysis.js.map +1 -1
  34. package/build/esm/AudioAnalysis/extractAudioData.js +144 -2
  35. package/build/esm/AudioAnalysis/extractAudioData.js.map +1 -1
  36. package/build/esm/AudioAnalysis/melSpectrogramWasm.web.js +9 -23
  37. package/build/esm/AudioAnalysis/melSpectrogramWasm.web.js.map +1 -1
  38. package/build/esm/AudioAnalysis/wasmConfig.js +4 -4
  39. package/build/esm/AudioAnalysis/wasmConfig.js.map +1 -1
  40. package/build/esm/AudioAnalysis/wasmLoader.web.js +43 -0
  41. package/build/esm/AudioAnalysis/wasmLoader.web.js.map +1 -0
  42. package/build/esm/AudioStudioModule.js +4 -596
  43. package/build/esm/AudioStudioModule.js.map +1 -1
  44. package/build/esm/trimAudio.js +227 -0
  45. package/build/esm/trimAudio.js.map +1 -1
  46. package/build/esm/utils/encodeCompressedAudio.web.js +62 -0
  47. package/build/esm/utils/encodeCompressedAudio.web.js.map +1 -0
  48. package/build/esm/utils/resampleAudioBuffer.web.js +22 -0
  49. package/build/esm/utils/resampleAudioBuffer.web.js.map +1 -0
  50. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts +11 -0
  51. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts.map +1 -1
  52. package/build/types/AudioAnalysis/audioFeaturesWasm.d.ts +5 -9
  53. package/build/types/AudioAnalysis/audioFeaturesWasm.d.ts.map +1 -1
  54. package/build/types/AudioAnalysis/audioFeaturesWasm.web.d.ts +35 -16
  55. package/build/types/AudioAnalysis/audioFeaturesWasm.web.d.ts.map +1 -1
  56. package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -1
  57. package/build/types/AudioAnalysis/extractAudioData.d.ts +2 -2
  58. package/build/types/AudioAnalysis/extractAudioData.d.ts.map +1 -1
  59. package/build/types/AudioAnalysis/melSpectrogramWasm.web.d.ts.map +1 -1
  60. package/build/types/AudioAnalysis/wasmLoader.web.d.ts +3 -0
  61. package/build/types/AudioAnalysis/wasmLoader.web.d.ts.map +1 -0
  62. package/build/types/AudioStudioModule.d.ts.map +1 -1
  63. package/build/types/trimAudio.d.ts.map +1 -1
  64. package/build/types/utils/encodeCompressedAudio.web.d.ts +10 -0
  65. package/build/types/utils/encodeCompressedAudio.web.d.ts.map +1 -0
  66. package/build/types/utils/resampleAudioBuffer.web.d.ts +2 -0
  67. package/build/types/utils/resampleAudioBuffer.web.d.ts.map +1 -0
  68. package/ios/AudioStreamManager.swift +135 -89
  69. package/ios/AudioStudioModule.swift +239 -216
  70. package/package.json +1 -1
  71. package/src/AudioAnalysis/AudioAnalysis.types.ts +12 -0
  72. package/src/AudioAnalysis/audioFeaturesWasm.ts +17 -22
  73. package/src/AudioAnalysis/audioFeaturesWasm.web.ts +102 -94
  74. package/src/AudioAnalysis/extractAudioAnalysis.ts +23 -20
  75. package/src/AudioAnalysis/extractAudioData.ts +186 -4
  76. package/src/AudioAnalysis/melSpectrogramWasm.web.ts +10 -27
  77. package/src/AudioAnalysis/wasmConfig.ts +4 -4
  78. package/src/AudioAnalysis/wasmLoader.web.ts +53 -0
  79. package/src/AudioStudioModule.ts +6 -854
  80. package/src/trimAudio.ts +351 -0
  81. package/src/utils/encodeCompressedAudio.web.ts +78 -0
  82. package/src/utils/resampleAudioBuffer.web.ts +39 -0
  83. package/build/cjs/AudioAnalysis/extractWaveform.js +0 -18
  84. package/build/cjs/AudioAnalysis/extractWaveform.js.map +0 -1
  85. package/build/esm/AudioAnalysis/extractWaveform.js +0 -11
  86. package/build/esm/AudioAnalysis/extractWaveform.js.map +0 -1
  87. package/build/types/AudioAnalysis/extractWaveform.d.ts +0 -8
  88. package/build/types/AudioAnalysis/extractWaveform.d.ts.map +0 -1
  89. package/src/AudioAnalysis/extractWaveform.ts +0 -22
package/src/trimAudio.ts CHANGED
@@ -1,16 +1,65 @@
1
1
  import { LegacyEventEmitter, type EventSubscription } from 'expo-modules-core'
2
2
 
3
3
  import {
4
+ BitDepth,
4
5
  TrimAudioOptions,
5
6
  TrimAudioResult,
6
7
  TrimProgressEvent,
7
8
  } from './AudioStudio.types'
8
9
  import AudioStudioModule from './AudioStudioModule'
10
+ import { isWeb } from './constants'
11
+ import { processAudioBuffer } from './utils/audioProcessing'
9
12
  import { cleanNativeOptions } from './utils/cleanNativeOptions'
13
+ import { encodeCompressedAudio } from './utils/encodeCompressedAudio.web'
14
+ import { resampleAudioBuffer } from './utils/resampleAudioBuffer.web'
15
+ import { writeWavHeader } from './utils/writeWavHeader'
10
16
 
11
17
  // Create a single emitter instance
12
18
  const emitter = new LegacyEventEmitter(AudioStudioModule)
13
19
 
20
+ function sliceAudioBuffer(
21
+ src: AudioBuffer,
22
+ ctx: AudioContext,
23
+ startMs: number,
24
+ endMs: number
25
+ ): AudioBuffer {
26
+ const sr = src.sampleRate
27
+ const start = Math.floor((startMs / 1000) * sr)
28
+ const end = Math.min(Math.ceil((endMs / 1000) * sr), src.length)
29
+ const length = Math.max(0, end - start)
30
+ const out = ctx.createBuffer(src.numberOfChannels, length, sr)
31
+ for (let c = 0; c < src.numberOfChannels; c++) {
32
+ out.getChannelData(c).set(src.getChannelData(c).subarray(start, end))
33
+ }
34
+ return out
35
+ }
36
+
37
+ function encodeBufferToWav(
38
+ buffer: AudioBuffer,
39
+ bitDepth: BitDepth
40
+ ): ArrayBuffer {
41
+ const { length, numberOfChannels, sampleRate } = buffer
42
+ const channels: Float32Array[] = []
43
+ for (let c = 0; c < numberOfChannels; c++) {
44
+ channels.push(buffer.getChannelData(c))
45
+ }
46
+ const interleavedData = new Int16Array(length * numberOfChannels)
47
+ for (let i = 0; i < length; i++) {
48
+ for (let c = 0; c < numberOfChannels; c++) {
49
+ const clamped = Math.max(-1, Math.min(1, channels[c][i]))
50
+ interleavedData[i * numberOfChannels + c] = Math.round(
51
+ clamped * 32767
52
+ )
53
+ }
54
+ }
55
+ return writeWavHeader({
56
+ buffer: interleavedData.buffer as ArrayBuffer,
57
+ sampleRate,
58
+ numChannels: numberOfChannels,
59
+ bitDepth,
60
+ })
61
+ }
62
+
14
63
  /**
15
64
  * Trims an audio file based on the provided options.
16
65
  *
@@ -52,6 +101,308 @@ export async function trimAudio(
52
101
  )
53
102
  }
54
103
 
104
+ if (isWeb) {
105
+ try {
106
+ const startTime = performance.now()
107
+ const {
108
+ fileUri,
109
+ startTimeMs,
110
+ endTimeMs,
111
+ ranges,
112
+ outputFileName,
113
+ outputFormat,
114
+ } = options
115
+
116
+ // Create AudioContext
117
+ const audioContext = new (window.AudioContext ||
118
+ (window as any).webkitAudioContext)()
119
+
120
+ // First, load the entire audio file to get its properties
121
+ const response = await fetch(fileUri)
122
+ const arrayBuffer = await response.arrayBuffer()
123
+ const originalAudioBuffer =
124
+ await audioContext.decodeAudioData(arrayBuffer)
125
+
126
+ // Get original audio properties
127
+ const originalSampleRate = originalAudioBuffer.sampleRate
128
+ const originalChannels = originalAudioBuffer.numberOfChannels
129
+
130
+ // Determine output format - use original values as defaults if not specified
131
+ let format = outputFormat?.format || 'wav'
132
+ const targetSampleRate =
133
+ outputFormat?.sampleRate || originalSampleRate
134
+ const targetChannels = outputFormat?.channels || originalChannels
135
+ const targetBitDepth = outputFormat?.bitDepth || 16
136
+
137
+ // Get file info from the URL
138
+ const filename =
139
+ outputFileName ||
140
+ fileUri.split('/').pop() ||
141
+ 'trimmed-audio.wav'
142
+
143
+ // Process based on mode
144
+ let resultBuffer: AudioBuffer
145
+
146
+ // Report initial progress
147
+ progressCallback?.({ progress: 10 })
148
+
149
+ if (mode === 'single') {
150
+ // Single mode: extract a single range
151
+ // Use original sample rate and channels for extraction to preserve quality
152
+ const { buffer } = await processAudioBuffer({
153
+ fileUri,
154
+ targetSampleRate, // Use the requested sample rate
155
+ targetChannels,
156
+ normalizeAudio: false,
157
+ startTimeMs,
158
+ endTimeMs,
159
+ audioContext,
160
+ })
161
+
162
+ resultBuffer = buffer
163
+
164
+ // If we need to change sample rate or channels, do it after extraction
165
+ if (
166
+ targetSampleRate !== originalSampleRate ||
167
+ targetChannels !== originalChannels
168
+ ) {
169
+ resultBuffer = await resampleAudioBuffer(
170
+ buffer,
171
+ targetSampleRate,
172
+ targetChannels
173
+ )
174
+ }
175
+ } else {
176
+ // For keep or remove modes
177
+ const fullDuration = originalAudioBuffer.duration * 1000 // in ms
178
+
179
+ type ProcessSegment = {
180
+ startTimeMs: number
181
+ endTimeMs: number
182
+ }
183
+
184
+ let segmentsToProcess: ProcessSegment[] = []
185
+
186
+ if (mode === 'keep') {
187
+ // For keep mode, use the ranges directly
188
+ segmentsToProcess = ranges!
189
+ } else {
190
+ // mode === 'remove'
191
+ // For remove mode, invert the ranges
192
+ const sortedRanges = [...ranges!].sort(
193
+ (a, b) => a.startTimeMs - b.startTimeMs
194
+ )
195
+
196
+ // Add segment from start to first range if needed
197
+ if (
198
+ sortedRanges.length > 0 &&
199
+ sortedRanges[0].startTimeMs > 0
200
+ ) {
201
+ segmentsToProcess.push({
202
+ startTimeMs: 0,
203
+ endTimeMs: sortedRanges[0].startTimeMs,
204
+ })
205
+ }
206
+
207
+ // Add segments between ranges
208
+ for (let i = 0; i < sortedRanges.length - 1; i++) {
209
+ segmentsToProcess.push({
210
+ startTimeMs: sortedRanges[i].endTimeMs,
211
+ endTimeMs: sortedRanges[i + 1].startTimeMs,
212
+ })
213
+ }
214
+
215
+ // Add segment from last range to end if needed
216
+ if (
217
+ sortedRanges.length > 0 &&
218
+ sortedRanges[sortedRanges.length - 1].endTimeMs <
219
+ fullDuration
220
+ ) {
221
+ segmentsToProcess.push({
222
+ startTimeMs:
223
+ sortedRanges[sortedRanges.length - 1].endTimeMs,
224
+ endTimeMs: fullDuration,
225
+ })
226
+ }
227
+ }
228
+
229
+ // Filter out empty or invalid segments
230
+ segmentsToProcess = segmentsToProcess.filter(
231
+ (segment) =>
232
+ segment.startTimeMs < segment.endTimeMs &&
233
+ segment.endTimeMs - segment.startTimeMs > 1
234
+ ) // 1ms minimum
235
+
236
+ if (segmentsToProcess.length === 0) {
237
+ throw new Error(
238
+ 'No valid segments to process after filtering ranges'
239
+ )
240
+ }
241
+
242
+ // Process each segment using original sample rate and channels
243
+ const segmentBuffers: AudioBuffer[] = []
244
+
245
+ for (let i = 0; i < segmentsToProcess.length; i++) {
246
+ const segment = segmentsToProcess[i]
247
+
248
+ // Report progress for each segment
249
+ progressCallback?.({
250
+ progress:
251
+ 10 +
252
+ Math.round((i / segmentsToProcess.length) * 40),
253
+ })
254
+
255
+ // Slice from the already-decoded buffer (avoids N re-fetches)
256
+ const segmentBuffer = sliceAudioBuffer(
257
+ originalAudioBuffer,
258
+ audioContext,
259
+ segment.startTimeMs,
260
+ segment.endTimeMs
261
+ )
262
+
263
+ segmentBuffers.push(segmentBuffer)
264
+ }
265
+
266
+ // Concatenate all segments
267
+ const totalSamples = segmentBuffers.reduce(
268
+ (sum, buffer) => sum + buffer.length,
269
+ 0
270
+ )
271
+
272
+ // Create buffer with original properties first
273
+ const concatenatedBuffer = audioContext.createBuffer(
274
+ originalChannels,
275
+ totalSamples,
276
+ originalSampleRate
277
+ )
278
+
279
+ let offset = 0
280
+ for (const segmentBuffer of segmentBuffers) {
281
+ for (
282
+ let channel = 0;
283
+ channel < originalChannels;
284
+ channel++
285
+ ) {
286
+ const outputData =
287
+ concatenatedBuffer.getChannelData(channel)
288
+ const segmentData =
289
+ segmentBuffer.getChannelData(channel)
290
+
291
+ for (let i = 0; i < segmentBuffer.length; i++) {
292
+ outputData[offset + i] = segmentData[i]
293
+ }
294
+ }
295
+ offset += segmentBuffer.length
296
+ }
297
+
298
+ resultBuffer = concatenatedBuffer
299
+
300
+ // If we need to change sample rate or channels, do it after concatenation
301
+ if (
302
+ targetSampleRate !== originalSampleRate ||
303
+ targetChannels !== originalChannels
304
+ ) {
305
+ resultBuffer = await resampleAudioBuffer(
306
+ concatenatedBuffer,
307
+ targetSampleRate,
308
+ targetChannels
309
+ )
310
+ }
311
+ }
312
+
313
+ // Report progress (50% - processing complete)
314
+ progressCallback?.({ progress: 50 })
315
+
316
+ // Encode the result based on the requested format
317
+ let outputData: ArrayBuffer
318
+ let outputMimeType: string
319
+ let compressionInfo: TrimAudioResult['compression'] = undefined
320
+
321
+ // AAC is not reliably supported in browsers; fall back to opus
322
+ if (format === 'aac') {
323
+ console.warn(
324
+ 'AAC format is not supported on web platforms. Falling back to OPUS format.'
325
+ )
326
+ format = 'opus'
327
+ }
328
+
329
+ if (format === 'wav') {
330
+ outputData = encodeBufferToWav(
331
+ resultBuffer,
332
+ targetBitDepth as BitDepth
333
+ )
334
+ outputMimeType = 'audio/wav'
335
+ } else if (format === 'opus') {
336
+ try {
337
+ const { data, bitrate } = await encodeCompressedAudio(
338
+ resultBuffer,
339
+ format,
340
+ outputFormat?.bitrate
341
+ )
342
+ outputData = data
343
+ outputMimeType = 'audio/webm'
344
+ compressionInfo = { format, bitrate, size: data.byteLength }
345
+ } catch (error) {
346
+ console.warn(
347
+ `Failed to encode to ${format}, falling back to WAV: ${error}`
348
+ )
349
+ outputData = encodeBufferToWav(
350
+ resultBuffer,
351
+ targetBitDepth as BitDepth
352
+ )
353
+ outputMimeType = 'audio/wav'
354
+ }
355
+ } else {
356
+ // Default to WAV for unsupported formats
357
+ console.warn(
358
+ `Format ${format} not supported on web, using WAV instead`
359
+ )
360
+ outputData = encodeBufferToWav(
361
+ resultBuffer,
362
+ targetBitDepth as BitDepth
363
+ )
364
+ outputMimeType = 'audio/wav'
365
+ }
366
+
367
+ // Report progress (90% - encoding complete)
368
+ progressCallback?.({ progress: 90 })
369
+
370
+ // Create a blob and URL for the result
371
+ const blob = new Blob([outputData], { type: outputMimeType })
372
+ const outputUri = URL.createObjectURL(blob)
373
+
374
+ // Calculate processing time
375
+ const processingTimeMs = performance.now() - startTime
376
+
377
+ // Report progress (100% - complete)
378
+ progressCallback?.({ progress: 100 })
379
+
380
+ // Create result object
381
+ const result: TrimAudioResult = {
382
+ uri: outputUri,
383
+ filename,
384
+ durationMs: Math.round(resultBuffer.duration * 1000),
385
+ size: outputData.byteLength,
386
+ sampleRate: resultBuffer.sampleRate,
387
+ channels: resultBuffer.numberOfChannels,
388
+ bitDepth: targetBitDepth,
389
+ mimeType: outputMimeType,
390
+ processingInfo: {
391
+ durationMs: processingTimeMs,
392
+ },
393
+ }
394
+
395
+ if (compressionInfo) {
396
+ result.compression = compressionInfo
397
+ }
398
+
399
+ return result
400
+ } catch (error) {
401
+ console.error('Error in trimAudio:', error)
402
+ throw error
403
+ }
404
+ }
405
+
55
406
  // Set up progress event listener if callback is provided
56
407
  let subscription: EventSubscription | undefined
57
408
  if (progressCallback) {
@@ -0,0 +1,78 @@
1
+ /**
2
+ * NOTE: Encodes audio in real-time via AudioContext + MediaRecorder playback.
3
+ * A 60-second clip takes ~60 seconds to encode — this is a known Web Audio API
4
+ * limitation; there is no offline API for Opus/AAC encoding in browsers.
5
+ */
6
+ export function encodeCompressedAudio(
7
+ buffer: AudioBuffer,
8
+ format: 'opus' | 'aac',
9
+ bitrate?: number
10
+ ): Promise<{ data: ArrayBuffer; bitrate: number }> {
11
+ return new Promise((resolve, reject) => {
12
+ try {
13
+ // On web, always use opus if aac is requested (browser aac support is rare)
14
+ const actualFormat = format === 'aac' ? 'opus' : format
15
+
16
+ // Check if MediaRecorder supports the requested format
17
+ const mimeType =
18
+ actualFormat === 'opus' ? 'audio/webm;codecs=opus' : 'audio/aac'
19
+ if (!MediaRecorder.isTypeSupported(mimeType)) {
20
+ throw new Error(`MediaRecorder does not support ${mimeType}`)
21
+ }
22
+
23
+ // Create a new AudioContext and source
24
+ const ctx = new (window.AudioContext ||
25
+ (window as any).webkitAudioContext)()
26
+ const source = ctx.createBufferSource()
27
+ source.buffer = buffer
28
+
29
+ // Create a MediaStreamDestination to capture the audio
30
+ const destination = ctx.createMediaStreamDestination()
31
+ source.connect(destination)
32
+
33
+ // Create a MediaRecorder with the requested format
34
+ const recorder = new MediaRecorder(destination.stream, {
35
+ mimeType,
36
+ audioBitsPerSecond:
37
+ bitrate || (actualFormat === 'opus' ? 32000 : 64000),
38
+ })
39
+
40
+ const chunks: Blob[] = []
41
+
42
+ recorder.ondataavailable = (e) => {
43
+ if (e.data.size > 0) {
44
+ chunks.push(e.data)
45
+ }
46
+ }
47
+
48
+ recorder.onstop = async () => {
49
+ try {
50
+ const blob = new Blob(chunks, { type: mimeType })
51
+ const arrayBuffer = await blob.arrayBuffer()
52
+
53
+ // Get the actual bitrate used
54
+ const actualBitrate = Math.round(
55
+ (arrayBuffer.byteLength * 8) / buffer.duration
56
+ )
57
+
58
+ resolve({
59
+ data: arrayBuffer,
60
+ bitrate: actualBitrate / 1000, // Convert to kbps
61
+ })
62
+
63
+ // Clean up
64
+ ctx.close()
65
+ } catch (error) {
66
+ reject(error)
67
+ }
68
+ }
69
+
70
+ // Start recording and playback; stop recorder when playback ends
71
+ recorder.start()
72
+ source.onended = () => recorder.stop()
73
+ source.start(0)
74
+ } catch (error) {
75
+ reject(error)
76
+ }
77
+ })
78
+ }
@@ -0,0 +1,39 @@
1
+ export async function resampleAudioBuffer(
2
+ buffer: AudioBuffer,
3
+ targetSampleRate: number,
4
+ targetChannels: number
5
+ ): Promise<AudioBuffer> {
6
+ // If no change needed, return the original buffer
7
+ if (
8
+ buffer.sampleRate === targetSampleRate &&
9
+ buffer.numberOfChannels === targetChannels
10
+ ) {
11
+ return buffer
12
+ }
13
+
14
+ // Calculate the new length based on the sample rate change
15
+ const newLength = Math.round(
16
+ (buffer.length * targetSampleRate) / buffer.sampleRate
17
+ )
18
+
19
+ // Create an offline context for resampling
20
+ const offlineContext = new OfflineAudioContext(
21
+ targetChannels,
22
+ newLength,
23
+ targetSampleRate
24
+ )
25
+
26
+ // Create a source node
27
+ const source = offlineContext.createBufferSource()
28
+ source.buffer = buffer
29
+
30
+ // The OfflineAudioContext was created with targetChannels; the Web Audio API
31
+ // applies its built-in speaker downmix/upmix rules automatically.
32
+ source.connect(offlineContext.destination)
33
+
34
+ // Start rendering
35
+ source.start(0)
36
+ const resampledBuffer = await offlineContext.startRendering()
37
+
38
+ return resampledBuffer
39
+ }
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.extractWaveform = void 0;
7
- const AudioStudioModule_1 = __importDefault(require("../AudioStudioModule"));
8
- const extractWaveform = async ({ fileUri, numberOfSamples, offset = 0, length, }) => {
9
- const res = await AudioStudioModule_1.default.extractAudioAnalysis({
10
- fileUri,
11
- numberOfSamples,
12
- offset,
13
- length,
14
- });
15
- return res;
16
- };
17
- exports.extractWaveform = extractWaveform;
18
- //# sourceMappingURL=extractWaveform.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extractWaveform.js","sourceRoot":"","sources":["../../../src/AudioAnalysis/extractWaveform.ts"],"names":[],"mappings":";;;;;;AAAA,6EAAoD;AAQ7C,MAAM,eAAe,GAAG,KAAK,EAAE,EAClC,OAAO,EACP,eAAe,EACf,MAAM,GAAG,CAAC,EACV,MAAM,GACa,EAAoB,EAAE;IACzC,MAAM,GAAG,GAAG,MAAM,2BAAiB,CAAC,oBAAoB,CAAC;QACrD,OAAO;QACP,eAAe;QACf,MAAM;QACN,MAAM;KACT,CAAC,CAAA;IACF,OAAO,GAAG,CAAA;AACd,CAAC,CAAA;AAbY,QAAA,eAAe,mBAa3B","sourcesContent":["import AudioStudioModule from '../AudioStudioModule'\n\nexport interface ExtractWaveformProps {\n fileUri: string\n numberOfSamples: number\n offset?: number\n length?: number\n}\nexport const extractWaveform = async ({\n fileUri,\n numberOfSamples,\n offset = 0,\n length,\n}: ExtractWaveformProps): Promise<unknown> => {\n const res = await AudioStudioModule.extractAudioAnalysis({\n fileUri,\n numberOfSamples,\n offset,\n length,\n })\n return res\n}\n"]}
@@ -1,11 +0,0 @@
1
- import AudioStudioModule from '../AudioStudioModule';
2
- export const extractWaveform = async ({ fileUri, numberOfSamples, offset = 0, length, }) => {
3
- const res = await AudioStudioModule.extractAudioAnalysis({
4
- fileUri,
5
- numberOfSamples,
6
- offset,
7
- length,
8
- });
9
- return res;
10
- };
11
- //# sourceMappingURL=extractWaveform.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extractWaveform.js","sourceRoot":"","sources":["../../../src/AudioAnalysis/extractWaveform.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,MAAM,sBAAsB,CAAA;AAQpD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,EAClC,OAAO,EACP,eAAe,EACf,MAAM,GAAG,CAAC,EACV,MAAM,GACa,EAAoB,EAAE;IACzC,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,oBAAoB,CAAC;QACrD,OAAO;QACP,eAAe;QACf,MAAM;QACN,MAAM;KACT,CAAC,CAAA;IACF,OAAO,GAAG,CAAA;AACd,CAAC,CAAA","sourcesContent":["import AudioStudioModule from '../AudioStudioModule'\n\nexport interface ExtractWaveformProps {\n fileUri: string\n numberOfSamples: number\n offset?: number\n length?: number\n}\nexport const extractWaveform = async ({\n fileUri,\n numberOfSamples,\n offset = 0,\n length,\n}: ExtractWaveformProps): Promise<unknown> => {\n const res = await AudioStudioModule.extractAudioAnalysis({\n fileUri,\n numberOfSamples,\n offset,\n length,\n })\n return res\n}\n"]}
@@ -1,8 +0,0 @@
1
- export interface ExtractWaveformProps {
2
- fileUri: string;
3
- numberOfSamples: number;
4
- offset?: number;
5
- length?: number;
6
- }
7
- export declare const extractWaveform: ({ fileUri, numberOfSamples, offset, length, }: ExtractWaveformProps) => Promise<unknown>;
8
- //# sourceMappingURL=extractWaveform.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extractWaveform.d.ts","sourceRoot":"","sources":["../../../src/AudioAnalysis/extractWaveform.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AACD,eAAO,MAAM,eAAe,GAAU,+CAKnC,oBAAoB,KAAG,OAAO,CAAC,OAAO,CAQxC,CAAA"}
@@ -1,22 +0,0 @@
1
- import AudioStudioModule from '../AudioStudioModule'
2
-
3
- export interface ExtractWaveformProps {
4
- fileUri: string
5
- numberOfSamples: number
6
- offset?: number
7
- length?: number
8
- }
9
- export const extractWaveform = async ({
10
- fileUri,
11
- numberOfSamples,
12
- offset = 0,
13
- length,
14
- }: ExtractWaveformProps): Promise<unknown> => {
15
- const res = await AudioStudioModule.extractAudioAnalysis({
16
- fileUri,
17
- numberOfSamples,
18
- offset,
19
- length,
20
- })
21
- return res
22
- }