@openclaw/whatsapp 2026.5.31-beta.2 → 2026.5.31-beta.3
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/dist/api.js +7 -7
- package/dist/{channel-DA2BAIo5.js → channel-DigzkmDO.js} +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-Q1LZDB5s.js → channel.runtime-BzDa8nVv.js} +2 -2
- package/dist/{channel.setup-DHXOo4h5.js → channel.setup-BRev7Qpj.js} +1 -1
- package/dist/login-qr-runtime.js +4 -4
- package/dist/{monitor-BVRq04Dt.js → monitor-D-vg4gJF.js} +9 -9
- package/dist/runtime-api.js +1 -1
- package/dist/{setup-core-OvPMaAsx.js → setup-core-D0ncRoh8.js} +5 -5
- package/dist/{setup-finalize-Dk23pfKc.js → setup-finalize-BdztDwTy.js} +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-F-jVrH8u.js → setup-surface-DLueEnfx.js} +1 -1
- package/node_modules/audio-buffer/.eslintrc.json +44 -0
- package/node_modules/audio-buffer/.github/workflows/node.js.yml +31 -0
- package/node_modules/audio-buffer/.travis.yml +7 -0
- package/node_modules/{@audio/decode-opus → audio-buffer}/LICENSE +2 -5
- package/node_modules/audio-buffer/index.js +76 -0
- package/node_modules/audio-buffer/package.json +37 -0
- package/node_modules/audio-buffer/readme.md +56 -0
- package/node_modules/audio-decode/.eslintrc.json +43 -0
- package/node_modules/audio-decode/.github/workflows/test.js.yml +20 -11
- package/node_modules/audio-decode/.travis.yml +13 -0
- package/node_modules/audio-decode/audio-decode.d.ts +10 -48
- package/node_modules/audio-decode/audio-decode.js +77 -193
- package/node_modules/audio-decode/package.json +21 -49
- package/node_modules/audio-decode/readme.md +29 -129
- package/node_modules/audio-decode/tea.yaml +6 -0
- package/node_modules/audio-decode/test-case.js +11 -0
- package/node_modules/audio-decode/test.html +10 -29
- package/node_modules/audio-decode/test.js +107 -0
- package/node_modules/node-wav/README.md +35 -0
- package/node_modules/node-wav/file.wav +0 -0
- package/node_modules/node-wav/index.js +291 -0
- package/node_modules/node-wav/package.json +29 -0
- package/node_modules/node-wav/tests/file1.wav +0 -0
- package/node_modules/node-wav/tests/test.js +66 -0
- package/node_modules/node-wav/x.js +12 -0
- package/node_modules/node-wav/x.json +86702 -0
- package/node_modules/node-wav/x.js~ +13 -0
- package/npm-shrinkwrap.json +32 -149
- package/package.json +5 -5
- package/node_modules/@audio/decode-aac/LICENSE +0 -9
- package/node_modules/@audio/decode-aac/README.md +0 -60
- package/node_modules/@audio/decode-aac/decode-aac.d.ts +0 -16
- package/node_modules/@audio/decode-aac/decode-aac.js +0 -391
- package/node_modules/@audio/decode-aac/package.json +0 -47
- package/node_modules/@audio/decode-aac/src/aac.wasm.cjs +0 -0
- package/node_modules/@audio/decode-aiff/LICENSE +0 -21
- package/node_modules/@audio/decode-aiff/README.md +0 -53
- package/node_modules/@audio/decode-aiff/decode-aiff.d.ts +0 -16
- package/node_modules/@audio/decode-aiff/decode-aiff.js +0 -583
- package/node_modules/@audio/decode-aiff/package.json +0 -42
- package/node_modules/@audio/decode-amr/LICENSE +0 -191
- package/node_modules/@audio/decode-amr/README.md +0 -65
- package/node_modules/@audio/decode-amr/decode-amr.d.ts +0 -16
- package/node_modules/@audio/decode-amr/decode-amr.js +0 -159
- package/node_modules/@audio/decode-amr/package.json +0 -48
- package/node_modules/@audio/decode-amr/src/amr.wasm.cjs +0 -0
- package/node_modules/@audio/decode-caf/LICENSE +0 -21
- package/node_modules/@audio/decode-caf/README.md +0 -55
- package/node_modules/@audio/decode-caf/decode-caf.d.ts +0 -16
- package/node_modules/@audio/decode-caf/decode-caf.js +0 -190
- package/node_modules/@audio/decode-caf/package.json +0 -43
- package/node_modules/@audio/decode-flac/LICENSE +0 -25
- package/node_modules/@audio/decode-flac/README.md +0 -23
- package/node_modules/@audio/decode-flac/decode-flac.d.ts +0 -16
- package/node_modules/@audio/decode-flac/decode-flac.js +0 -2994
- package/node_modules/@audio/decode-flac/meta.js +0 -115
- package/node_modules/@audio/decode-flac/package.json +0 -49
- package/node_modules/@audio/decode-mp3/LICENSE +0 -25
- package/node_modules/@audio/decode-mp3/README.md +0 -23
- package/node_modules/@audio/decode-mp3/decode-mp3.d.ts +0 -16
- package/node_modules/@audio/decode-mp3/decode-mp3.js +0 -868
- package/node_modules/@audio/decode-mp3/meta.js +0 -143
- package/node_modules/@audio/decode-mp3/package.json +0 -50
- package/node_modules/@audio/decode-opus/README.md +0 -23
- package/node_modules/@audio/decode-opus/decode-opus.d.ts +0 -16
- package/node_modules/@audio/decode-opus/decode-opus.js +0 -3179
- package/node_modules/@audio/decode-opus/package.json +0 -47
- package/node_modules/@audio/decode-qoa/LICENSE +0 -25
- package/node_modules/@audio/decode-qoa/README.md +0 -21
- package/node_modules/@audio/decode-qoa/decode-qoa.d.ts +0 -16
- package/node_modules/@audio/decode-qoa/decode-qoa.js +0 -278
- package/node_modules/@audio/decode-qoa/package.json +0 -46
- package/node_modules/@audio/decode-vorbis/LICENSE +0 -25
- package/node_modules/@audio/decode-vorbis/README.md +0 -23
- package/node_modules/@audio/decode-vorbis/decode-vorbis.d.ts +0 -16
- package/node_modules/@audio/decode-vorbis/decode-vorbis.js +0 -2984
- package/node_modules/@audio/decode-vorbis/package.json +0 -47
- package/node_modules/@audio/decode-wav/decode-wav.js +0 -104
- package/node_modules/@audio/decode-wav/meta.js +0 -114
- package/node_modules/@audio/decode-wav/package.json +0 -27
- package/node_modules/@audio/decode-webm/LICENSE +0 -21
- package/node_modules/@audio/decode-webm/README.md +0 -57
- package/node_modules/@audio/decode-webm/decode-webm.d.ts +0 -16
- package/node_modules/@audio/decode-webm/decode-webm.js +0 -3964
- package/node_modules/@audio/decode-webm/package.json +0 -51
- package/node_modules/@audio/decode-wma/LICENSE +0 -12
- package/node_modules/@audio/decode-wma/README.md +0 -76
- package/node_modules/@audio/decode-wma/decode-wma.d.ts +0 -33
- package/node_modules/@audio/decode-wma/decode-wma.js +0 -525
- package/node_modules/@audio/decode-wma/package.json +0 -47
- package/node_modules/@audio/decode-wma/src/wma.wasm.cjs +0 -0
- package/node_modules/audio-decode/.claude/settings.json +0 -204
- package/node_modules/audio-decode/.gitmodules +0 -9
- package/node_modules/audio-decode/meta.js +0 -11
- package/node_modules/audio-decode/stream.d.ts +0 -15
- package/node_modules/audio-decode/stream.js +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
|
|
2
|
+
import decodeAudio, { decoders } from './audio-decode.js';
|
|
3
|
+
import wav from 'audio-lena/wav.js';
|
|
4
|
+
import mp3 from 'audio-lena/mp3.js';
|
|
5
|
+
import ogg from 'audio-lena/ogg.js';
|
|
6
|
+
import flac from 'audio-lena/flac.js';
|
|
7
|
+
import opus from 'audio-lena/opus.js';
|
|
8
|
+
import t, { is, throws } from 'tst';
|
|
9
|
+
import b64 from 'base64-arraybuffer'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
//as a callback
|
|
13
|
+
t('wav buffer', async function (t) {
|
|
14
|
+
console.time('wav first')
|
|
15
|
+
await decoders.wav()
|
|
16
|
+
console.timeEnd('wav first')
|
|
17
|
+
|
|
18
|
+
console.time('wav second')
|
|
19
|
+
let audioBuffer = await decodeAudio(wav)
|
|
20
|
+
console.timeEnd('wav second')
|
|
21
|
+
is(audioBuffer.duration | 0, 12, 'wav duration')
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
t('mp3 buffer', async function (t) {
|
|
25
|
+
console.time('mp3 first')
|
|
26
|
+
await decoders.mp3()
|
|
27
|
+
console.timeEnd('mp3 first')
|
|
28
|
+
|
|
29
|
+
console.time('mp3 second')
|
|
30
|
+
let audioBuffer = await decodeAudio(mp3)
|
|
31
|
+
console.timeEnd('mp3 second')
|
|
32
|
+
is(audioBuffer.duration | 0, 12, 'mp3 duration')
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
t('ogg buffer', async function (t) {
|
|
36
|
+
console.time('ogg first')
|
|
37
|
+
let audioBuffer = await decodeAudio(ogg)
|
|
38
|
+
console.timeEnd('ogg first')
|
|
39
|
+
is(audioBuffer.duration | 0, 12, 'ogg duration')
|
|
40
|
+
|
|
41
|
+
console.time('ogg second')
|
|
42
|
+
audioBuffer = await decodeAudio(ogg)
|
|
43
|
+
console.timeEnd('ogg second')
|
|
44
|
+
is(audioBuffer.duration | 0, 12, 'ogg duration')
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
t('flac buffer', async function (t) {
|
|
48
|
+
console.time('flac first')
|
|
49
|
+
let audioBuffer = await decodeAudio(flac)
|
|
50
|
+
console.timeEnd('flac first')
|
|
51
|
+
is(audioBuffer.duration | 0, 12, 'flac duration')
|
|
52
|
+
|
|
53
|
+
console.time('flac second')
|
|
54
|
+
audioBuffer = await decodeAudio(flac)
|
|
55
|
+
console.timeEnd('flac second')
|
|
56
|
+
is(audioBuffer.duration | 0, 12, 'flac duration')
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
t('opus buffer', async function (t) {
|
|
60
|
+
console.time('opus first')
|
|
61
|
+
let audioBuffer = await decodeAudio(opus)
|
|
62
|
+
console.timeEnd('opus first')
|
|
63
|
+
is(audioBuffer.duration | 0, 12, 'opus duration')
|
|
64
|
+
|
|
65
|
+
console.time('opus second')
|
|
66
|
+
audioBuffer = await decodeAudio(opus)
|
|
67
|
+
console.timeEnd('opus second')
|
|
68
|
+
is(audioBuffer.duration | 0, 12, 'opus duration')
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
t('qoa buffer', async function (t) {
|
|
72
|
+
const qoa = b64.decode(`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X3a67RrprrpprrbbFtttsttssNgONBfwBa04JhCKKCCKKSQQGCBBBBBBBJIYkgkkAgkEEBSSCQQQSCCSFBFBAAgBEAoPmU3ySkzWBAv9eBrLEIZdBcWMcHZUPTQCGFshFtlJAQR2SOW2lT20BxbbbabbbSIQEEUUgiiggAyi2UyQKGbrBTIAhYDvtc8DX3SL/3Rb/wcD9pDv//fFA+vi738BU0AJokRJBFFFNgyU22uumwQGDZKKaTaIabYEAttKntklFA0kCEEmhR2xA1gJt+sGu1sLxT/2m/7wzQ/7Xf945o77Btc+sRCmxRoLHosottttJBCCKCSSCCQQFBJJJIIJBBIUkggkggggggm2202m22aGDaBSbTJKZJIEAJIK6mL76Qa59Dt/v9otD91Bj3givgwGimCgkAUppARW0RQmWgRyCAAIKbJPLYQAptI08kggkAiQYce87oAtD0t+++1+//8SSWWSy2WWWxbZZZZZZZbLEtttlltssssP/+7//b//+Qb//Jd/9rr/D+21+/hj30EBVw0gmw0yWQrYTHFTVf/bC3/uv///2/8SwwyyyWWyyQ///v///9t/FhhllkklllkWWWWWWWSSSQ/VH94rfPbaAQC7gBQACBgAAAAFAAQAA+3RDv3eIxoxBiktOAByaBAFoogEtIplpg2UO2yik2yRDTZZaabSYbYNJFttAttssg220k2220m2DIKbbabbbLYQggggkkggghCCCSQSSSSQIAAAAAAAAAAUEkkkkkkkkhSSSCSSSSSSFBBIIIIJBBAUEggEEAAAAAy022yym2ykCbZJbbbLTbQMstNpEttpJg22SGmmUUGWBIYaKFBaZJYNIIEFFCigkATFQCpbBZtvB2/++3v//38WWWWW2yyyyxLLLZZZZbLLIkkkkkkkkkkSyyyyy2222xbbLLZZZZZZFllsssstllkWWGGGGGGWWQ/P//f//9vvD/u3///u//0Db/7W37aaOQrtNdvbFFdoBqnssNjhgJoGAEgiAtIEpAkQQSigWGUiAJLSKSbbRbYNpNNttpNttAi02iU22mWmDTKSTSZTTaIBJtMoppEhhAUUCUkQSi0iBSaQIJRQQJIMEghIoUIsEAik0SUUkWGWDZQabTKLTKIJNNplNtlFJgmkU22EkmWUBRZJNOPOVPAIAQAEQSAgQwDBQYoAAYYKANdVMtmmhisKWW3XwxXSQwVXFTVVRQCIBoQJowYYwRQBDBBIM4MskASkUCGWSUEGBIAIQwopKEEAggAAEo448wzTDjlVTjTDAgJqpgIAMAAAxRU1TSwS2wdFFFBQDVTQBNdEJphoxpoDBAgAEkAUEgBDAADYqZLHBWENtmrrihgK+e7bb627bQtNNtZDNFYoDnuljm192/8KaXXa3b/a2wrrrDLbDTVFANEssMElhogGKGnGGQESGAaADVRRBJBTBVeONMWOAAAEkigAgg04YQRAKCIYQRAAAJIgoIIBopAAQEEkAIlAkgSkSUk0SUUkBRSaZRSaaSYJtpJJJhDhlAUU02mW20y0CbSLTbbbbbYItNtttNtpJgm2UWmmGWmmBSTTRYZaaLQNpEotMscMoAgSSiSEUjjQAQJxwJEBppgGWCiCKnGGWAYbdrdHbrrrD20cd20123sG6+/bbffXaw7vHfv9fvv/Cv3+9+/+930P3z337ae/XwHdttNPdbZrB1sUVmhks0MFV11ZVQwAiAIACJFTQaaIBABoKCJRSSIEpJFFJNMotAmky0mUSyykBKLRRSSRQRYJIpJNMsNJEggiUQg0ygSEARBKRQJBJQQAkokAkkkY8QgABCCIIQQAAOONMAIpqy4GmmiACWQCWAqqYopJFHXFAU10tut1tu0LTT3X333/ew9/trtvtbrtB00cd1t121sHb3W6662zXQdbbddNHddNAU1kgsUMElsGGqGWWmKGAABBDjTJaaYYBgAANXNEgowCiEEEAAkkgASSCKcCRQSSCBBJRIJKLCIFlkklhhAlFAUSSigQUUSSAZaKLLLCJRQIIMssspNMIgkWGEUkiUWWBRKLSRZaTCIJJIopJIlJMgykWkiUkyyiDLLGHDKRRZYIpJplhhlhAgUUUCUUCCSSBBBKCGGCCBAIIgE4YEABAgIaaADTQAIYBpzzyxhhlhgKKGGKKWCWWAqopbLFNLFVAU0MNttlt10GKOKWy2622wrbLLNHlTJYBgMUVMMsUMEGWGmGWWGKKgaYYqaADTjTAFhpiihhltkCmqiAAASAEwVjjTVDRAacBwogBIJxpCAAjBCmmCgAUASCKKAQIIQQAABBAIQJIIQBAgnAkAAhAgASCAIIAIJBBNMMNEEEONMAwwWW2Sy22QJbbLJZbFVDBmhhuut111sGa622W26KXQNbbddddd77Cu222v29110LXTbba6+++QprrrbddZbdBuiimlkUUtkC22WCGGGiiAKCCQQSiQSUBRJKKJJLDKIFJJIspJlFpAyykk0y022mCabTSbbaabYNtNNtptNtpg2222m22m02DbTbbaabbbQNNttNtttttg202222m22mDTbbSbbTSaYNJJMtJFlpIAiiSSSUQRQgCBIJJIooIpoGnGmCU1V1UwDLLDDLYqpbAsstuls01ugO7XXbfe6++wtdr77r79tdC222v3199+8Lbb/7fff/7wv/979/vvv9Dvv3+9+++20L77a/fb37ew7rttrrtvbbC088c910110G6Oa2y222KgpbDDNHDYppBhhlkNVUMkgGGGimmAUQwwRRIaaKaaAQAAgBFNOOFFEIEgAAgAQAEQVTRQAASQAIAoAAgAAggIIAAAgAQUEAAAQgCKCAAAQgAIoJAAIJIAIEkEUgkAAEIAQQSSCEUGeCCKRJRRQQYZQIossopJMspAkkkWWki02kDLLTLLTaTLQJtMtNtNNNtA0022002002DbaabbaaaaYJNNpJlptMtA2kk000mk0kCSSSRRZSKJQIsIYIkghBjAKCCCAQgjjhBAAghFNNFAECGmqKWyKuKAYo66qopoorB001uutt11sKee663z3W7Qtdddfdb77tA2vuuvvuuu0Ha2666y3a2wdbrrbrrrrrCutt11stt0sC3W22222WOArZbrbbJbbZBmttlt0thigKKmGxVQxxVQVDLDTDLVlVANNMMMAhksEAQw00SSQQRQVjAYYIBDBBABqooEEAoqoKmmmGiA1U0QQIKKIYYcaYAgAANNAAgAAEAQEAAAAgAQACAAAQQQCEAIIoJAAIIIAEIEggoIEEIAhQECQQCggSAJRQJKKJJRQFAkolBEopBAEiiSUiiUUiCKDDKKKSSRIIsoklFEklFAiSUiiEEiSSBKKCCKJJJKIBALuAFAAIGAACAAMABQAF8fkSz+MTHu8IIFFEEkokhACiSCCQQCCSAIIJRIJJJBAEkkEEkkEEkgCCEECCEECCAJIIBIQooJAEUUgggEIEAACCKaKABABRAAgAIggAAEEAAGqmmmGCAQBBABDTTRDBAEAhpppqppoGCCAAwQCCSQABDBBBDBBBAMEEEMEEEMMA0ww00ww00wDDTTDIaaqq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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAu4AOBwW4AAEAAQABAAH0shPQ5kAgKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKaIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU0QCAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAACigKKKKKKKKKKAopxoggAAAEE0QGmiA00QAIIAAAKaIAAAAAFNEAppooCCAAACAACmgaIAIKKIBBAAAgAAgEAoooCiiiAAACmiAIBTRBAAABBBFFEAAAEAAEE40QAQUUUUQRRTjRAAAKaAgFNEApogEAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACmiAAIAAIBAKIBTBNNNNNNNNNME000000000wRBBAaaaaIIAggggggAFNEAAQQACCnGiAAAAAKaIAKaAgAAAAApogAAAAAAAAAU0QAABTRAIAAKAgAAAgoopogAQQCmiCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU0QAU0QBBAaaaaIBBAAgggggNNNME000000000wTTTTTRBBAKBpppogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==`)
|
|
73
|
+
|
|
74
|
+
console.time('qoa first')
|
|
75
|
+
let audioBuffer = await decodeAudio(qoa)
|
|
76
|
+
console.timeEnd('qoa first')
|
|
77
|
+
|
|
78
|
+
console.time('qoa second')
|
|
79
|
+
audioBuffer = await decodeAudio(qoa)
|
|
80
|
+
console.timeEnd('qoa second')
|
|
81
|
+
is(Math.floor(audioBuffer.duration * 100) / 100, 0.82, 'qoa duration')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
t('malformed data', async t => {
|
|
85
|
+
let log = []
|
|
86
|
+
try {
|
|
87
|
+
let x = await decodeAudio(new Float32Array(10))
|
|
88
|
+
} catch (e) { log.push('arr') }
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
let x = await decodeAudio(null)
|
|
92
|
+
} catch (e) { log.push('null') }
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
let x = await decodeAudio(Promise.resolve())
|
|
96
|
+
} catch (e) { log.push('nonbuf') }
|
|
97
|
+
|
|
98
|
+
is(log, ['arr', 'null', 'nonbuf'])
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
t.skip('sequence #38', async t => {
|
|
102
|
+
let flacBuffer = await decoders.flac(new Uint8Array(flac))
|
|
103
|
+
is(flacBuffer.duration | 0, 12, 'flac duration')
|
|
104
|
+
|
|
105
|
+
let mp3Buffer = await decoders.mp3(new Uint8Array(mp3))
|
|
106
|
+
is(mp3Buffer.duration | 0, 12, 'mp3 duration')
|
|
107
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
node-wav
|
|
2
|
+
========
|
|
3
|
+
|
|
4
|
+
High performance WAV decoder and encoder. The decoder is up to 750x faster than
|
|
5
|
+
the 'wav-decoder' npm module.
|
|
6
|
+
|
|
7
|
+
In addition, in contrast to 'wav-decoder' the result is returned directly instead
|
|
8
|
+
of with a promise.
|
|
9
|
+
|
|
10
|
+
This module combines the functionality of 'wav-decoder' and 'wav-encoder'.
|
|
11
|
+
|
|
12
|
+
Usage
|
|
13
|
+
-----
|
|
14
|
+
|
|
15
|
+
let fs = require('fs');
|
|
16
|
+
let wav = require('node-wav');
|
|
17
|
+
|
|
18
|
+
let buffer = fs.readFileSync('file.wav');
|
|
19
|
+
let result = wav.decode(buffer);
|
|
20
|
+
console.log(result.sampleRate);
|
|
21
|
+
console.log(result.channelData); // array of Float32Arrays
|
|
22
|
+
|
|
23
|
+
wav.encode(result.channelData, { sampleRate: result.sampleRate, float: true, bitDepth: 32 });
|
|
24
|
+
|
|
25
|
+
Data format
|
|
26
|
+
-----------
|
|
27
|
+
|
|
28
|
+
Data is always returned as Float32Arrays. While reading and writing 64-bit float
|
|
29
|
+
WAV files is supported, data is truncated to 32-bit floats.
|
|
30
|
+
|
|
31
|
+
Endianness
|
|
32
|
+
----------
|
|
33
|
+
|
|
34
|
+
This module assumes a little endian CPU, which is true for pretty much every processor
|
|
35
|
+
these days (in particular Intel and ARM).
|
|
Binary file
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
2
|
+
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
|
3
|
+
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const data_decoders = {
|
|
7
|
+
pcm8: (buffer, offset, output, channels, samples) => {
|
|
8
|
+
let input = new Uint8Array(buffer, offset);
|
|
9
|
+
let pos = 0;
|
|
10
|
+
for (let i = 0; i < samples; ++i) {
|
|
11
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
12
|
+
let data = input[pos++] - 128;
|
|
13
|
+
output[ch][i] = data < 0 ? data / 128 : data / 127;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
pcm16: (buffer, offset, output, channels, samples) => {
|
|
18
|
+
let input = new Int16Array(buffer, offset);
|
|
19
|
+
let pos = 0;
|
|
20
|
+
for (let i = 0; i < samples; ++i) {
|
|
21
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
22
|
+
let data = input[pos++];
|
|
23
|
+
output[ch][i] = data < 0 ? data / 32768 : data / 32767;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
pcm24: (buffer, offset, output, channels, samples) => {
|
|
28
|
+
let input = new Uint8Array(buffer, offset);
|
|
29
|
+
let pos = 0;
|
|
30
|
+
for (let i = 0; i < samples; ++i) {
|
|
31
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
32
|
+
let x0 = input[pos++];
|
|
33
|
+
let x1 = input[pos++];
|
|
34
|
+
let x2 = input[pos++];
|
|
35
|
+
let xx = (x0 + (x1 << 8) + (x2 << 16));
|
|
36
|
+
let data = xx > 0x800000 ? xx - 0x1000000 : xx;
|
|
37
|
+
output[ch][i] = data < 0 ? data / 8388608 : data / 8388607;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
pcm32: (buffer, offset, output, channels, samples) => {
|
|
42
|
+
let input = new Int32Array(buffer, offset);
|
|
43
|
+
let pos = 0;
|
|
44
|
+
for (let i = 0; i < samples; ++i) {
|
|
45
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
46
|
+
let data = input[pos++];
|
|
47
|
+
output[ch][i] = data < 0 ? data / 2147483648 : data / 2147483647;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
pcm32f: (buffer, offset, output, channels, samples) => {
|
|
52
|
+
let input = new Float32Array(buffer, offset);
|
|
53
|
+
let pos = 0;
|
|
54
|
+
for (let i = 0; i < samples; ++i) {
|
|
55
|
+
for (let ch = 0; ch < channels; ++ch)
|
|
56
|
+
output[ch][i] = input[pos++];
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
pcm64f: (buffer, offset, output, channels, samples) => {
|
|
60
|
+
let input = new Float64Array(buffer, offset);
|
|
61
|
+
let pos = 0;
|
|
62
|
+
for (let i = 0; i < samples; ++i) {
|
|
63
|
+
for (let ch = 0; ch < channels; ++ch)
|
|
64
|
+
output[ch][i] = input[pos++];
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const data_encoders = {
|
|
70
|
+
pcm8: (buffer, offset, input, channels, samples) => {
|
|
71
|
+
let output = new Uint8Array(buffer, offset);
|
|
72
|
+
let pos = 0;
|
|
73
|
+
for (let i = 0; i < samples; ++i) {
|
|
74
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
75
|
+
let v = Math.max(-1, Math.min(input[ch][i], 1));
|
|
76
|
+
v = ((v * 0.5 + 0.5) * 255) | 0;
|
|
77
|
+
output[pos++] = v;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
pcm16: (buffer, offset, input, channels, samples) => {
|
|
82
|
+
let output = new Int16Array(buffer, offset);
|
|
83
|
+
let pos = 0;
|
|
84
|
+
for (let i = 0; i < samples; ++i) {
|
|
85
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
86
|
+
let v = Math.max(-1, Math.min(input[ch][i], 1));
|
|
87
|
+
v = ((v < 0) ? v * 32768 : v * 32767) | 0;
|
|
88
|
+
output[pos++] = v;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
pcm24: (buffer, offset, input, channels, samples) => {
|
|
93
|
+
let output = new Uint8Array(buffer, offset);
|
|
94
|
+
let pos = 0;
|
|
95
|
+
for (let i = 0; i < samples; ++i) {
|
|
96
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
97
|
+
let v = Math.max(-1, Math.min(input[ch][i], 1));
|
|
98
|
+
v = ((v < 0) ? 0x1000000 + v * 8388608 : v * 8388607) | 0;
|
|
99
|
+
output[pos++] = (v >> 0) & 0xff;
|
|
100
|
+
output[pos++] = (v >> 8) & 0xff;
|
|
101
|
+
output[pos++] = (v >> 16) & 0xff;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
pcm32: (buffer, offset, input, channels, samples) => {
|
|
106
|
+
let output = new Int32Array(buffer, offset);
|
|
107
|
+
let pos = 0;
|
|
108
|
+
for (let i = 0; i < samples; ++i) {
|
|
109
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
110
|
+
let v = Math.max(-1, Math.min(input[ch][i], 1));
|
|
111
|
+
v = ((v < 0) ? v * 2147483648 : v * 2147483647) | 0;
|
|
112
|
+
output[pos++] = v;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
pcm32f: (buffer, offset, input, channels, samples) => {
|
|
117
|
+
let output = new Float32Array(buffer, offset);
|
|
118
|
+
let pos = 0;
|
|
119
|
+
for (let i = 0; i < samples; ++i) {
|
|
120
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
121
|
+
let v = Math.max(-1, Math.min(input[ch][i], 1));
|
|
122
|
+
output[pos++] = v;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
pcm64f: (buffer, offset, input, channels, samples) => {
|
|
127
|
+
let output = new Float64Array(buffer, offset);
|
|
128
|
+
let pos = 0;
|
|
129
|
+
for (let i = 0; i < samples; ++i) {
|
|
130
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
131
|
+
let v = Math.max(-1, Math.min(input[ch][i], 1));
|
|
132
|
+
output[pos++] = v;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
function lookup(table, bitDepth, floatingPoint) {
|
|
139
|
+
let name = 'pcm' + bitDepth + (floatingPoint ? 'f' : '');
|
|
140
|
+
let fn = table[name];
|
|
141
|
+
if (!fn)
|
|
142
|
+
throw new TypeError('Unsupported data format: ' + name);
|
|
143
|
+
return fn;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function decode(buffer) {
|
|
147
|
+
let pos = 0, end = 0;
|
|
148
|
+
if (buffer.buffer) {
|
|
149
|
+
// If we are handed a typed array or a buffer, then we have to consider the
|
|
150
|
+
// offset and length into the underlying array buffer.
|
|
151
|
+
pos = buffer.byteOffset;
|
|
152
|
+
end = buffer.length;
|
|
153
|
+
buffer = buffer.buffer;
|
|
154
|
+
} else {
|
|
155
|
+
// If we are handed a straight up array buffer, start at offset 0 and use
|
|
156
|
+
// the full length of the buffer.
|
|
157
|
+
pos = 0;
|
|
158
|
+
end = buffer.byteLength;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let v = new DataView(buffer);
|
|
162
|
+
|
|
163
|
+
function u8() {
|
|
164
|
+
let x = v.getUint8(pos);
|
|
165
|
+
pos++;
|
|
166
|
+
return x;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function u16() {
|
|
170
|
+
let x = v.getUint16(pos, true);
|
|
171
|
+
pos += 2;
|
|
172
|
+
return x;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function u32() {
|
|
176
|
+
let x = v.getUint32(pos, true);
|
|
177
|
+
pos += 4;
|
|
178
|
+
return x;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function string(len) {
|
|
182
|
+
let str = '';
|
|
183
|
+
for (let i = 0; i < len; ++i)
|
|
184
|
+
str += String.fromCharCode(u8());
|
|
185
|
+
return str;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (string(4) !== 'RIFF')
|
|
189
|
+
throw new TypeError('Invalid WAV file');
|
|
190
|
+
u32();
|
|
191
|
+
if (string(4) !== 'WAVE')
|
|
192
|
+
throw new TypeError('Invalid WAV file');
|
|
193
|
+
|
|
194
|
+
let fmt;
|
|
195
|
+
|
|
196
|
+
while (pos < end) {
|
|
197
|
+
let type = string(4);
|
|
198
|
+
let size = u32();
|
|
199
|
+
let next = pos + size;
|
|
200
|
+
switch (type) {
|
|
201
|
+
case 'fmt ':
|
|
202
|
+
let formatId = u16();
|
|
203
|
+
if (formatId !== 0x0001 && formatId !== 0x0003)
|
|
204
|
+
throw new TypeError('Unsupported format in WAV file: ' + formatId.toString(16));
|
|
205
|
+
fmt = {
|
|
206
|
+
format: 'lpcm',
|
|
207
|
+
floatingPoint: formatId === 0x0003,
|
|
208
|
+
channels: u16(),
|
|
209
|
+
sampleRate: u32(),
|
|
210
|
+
byteRate: u32(),
|
|
211
|
+
blockSize: u16(),
|
|
212
|
+
bitDepth: u16(),
|
|
213
|
+
};
|
|
214
|
+
break;
|
|
215
|
+
case 'data':
|
|
216
|
+
if (!fmt)
|
|
217
|
+
throw new TypeError('Missing "fmt " chunk.');
|
|
218
|
+
let samples = Math.floor(size / fmt.blockSize);
|
|
219
|
+
let channels = fmt.channels;
|
|
220
|
+
let sampleRate = fmt.sampleRate;
|
|
221
|
+
let channelData = [];
|
|
222
|
+
for (let ch = 0; ch < channels; ++ch)
|
|
223
|
+
channelData[ch] = new Float32Array(samples);
|
|
224
|
+
lookup(data_decoders, fmt.bitDepth, fmt.floatingPoint)(buffer, pos, channelData, channels, samples);
|
|
225
|
+
return {
|
|
226
|
+
sampleRate: sampleRate,
|
|
227
|
+
channelData: channelData
|
|
228
|
+
};
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
pos = next;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function encode(channelData, opts) {
|
|
236
|
+
let sampleRate = opts.sampleRate || 16000;
|
|
237
|
+
let floatingPoint = !!(opts.float || opts.floatingPoint);
|
|
238
|
+
let bitDepth = floatingPoint ? 32 : ((opts.bitDepth | 0) || 16);
|
|
239
|
+
let channels = channelData.length;
|
|
240
|
+
let samples = channelData[0].length;
|
|
241
|
+
let buffer = new ArrayBuffer(44 + (samples * channels * (bitDepth >> 3)));
|
|
242
|
+
|
|
243
|
+
let v = new DataView(buffer);
|
|
244
|
+
let pos = 0;
|
|
245
|
+
|
|
246
|
+
function u8(x) {
|
|
247
|
+
v.setUint8(pos++, x);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function u16(x) {
|
|
251
|
+
v.setUint16(pos, x, true);
|
|
252
|
+
pos += 2;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function u32(x) {
|
|
256
|
+
v.setUint32(pos, x, true);
|
|
257
|
+
pos += 4;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function string(s) {
|
|
261
|
+
for (var i = 0; i < s.length; ++i)
|
|
262
|
+
u8(s.charCodeAt(i));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// write header
|
|
266
|
+
string('RIFF');
|
|
267
|
+
u32(buffer.byteLength - 8);
|
|
268
|
+
string('WAVE');
|
|
269
|
+
|
|
270
|
+
// write 'fmt ' chunk
|
|
271
|
+
string('fmt ');
|
|
272
|
+
u32(16);
|
|
273
|
+
u16(floatingPoint ? 0x0003 : 0x0001);
|
|
274
|
+
u16(channels);
|
|
275
|
+
u32(sampleRate);
|
|
276
|
+
u32(sampleRate * channels * (bitDepth >> 3));
|
|
277
|
+
u16(channels * (bitDepth >> 3));
|
|
278
|
+
u16(bitDepth);
|
|
279
|
+
|
|
280
|
+
// write 'data' chunk
|
|
281
|
+
string('data');
|
|
282
|
+
u32(buffer.byteLength - 44);
|
|
283
|
+
lookup(data_encoders, bitDepth, floatingPoint)(buffer, pos, channelData, channels, samples);
|
|
284
|
+
|
|
285
|
+
return Buffer(buffer);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
module.exports = {
|
|
289
|
+
decode: decode,
|
|
290
|
+
encode: encode,
|
|
291
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "node-wav",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "High performance WAV file decoder and encoder",
|
|
5
|
+
"main": "./index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "./node_modules/nodeunit/bin/nodeunit ./tests/test.js"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/andreasgal/node-wav.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"wav",
|
|
15
|
+
"decode"
|
|
16
|
+
],
|
|
17
|
+
"author": "Andreas Gal",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"homepage": "https://github.com/andreasgal/node-wav",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=4.4.0"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"nodeunit": "^0.9.1",
|
|
26
|
+
"wav-decoder": "^1.1.0",
|
|
27
|
+
"wav-encoder": "^1.1.0"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
2
|
+
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
|
3
|
+
|
|
4
|
+
"use strict";
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const encoder = require('wav-encoder');
|
|
8
|
+
const decoder = require('wav-decoder');
|
|
9
|
+
const wav = require('../index');
|
|
10
|
+
|
|
11
|
+
function make_test_data(channels, samples) {
|
|
12
|
+
let data = [];
|
|
13
|
+
for (let ch = 0; ch < channels; ++ch) {
|
|
14
|
+
data[ch] = new Float32Array(samples);
|
|
15
|
+
for (let n = 0; n < samples; ++n)
|
|
16
|
+
data[ch][n] = Math.random();
|
|
17
|
+
}
|
|
18
|
+
return data;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
exports.test_wav = test => {
|
|
22
|
+
test.expect(25);
|
|
23
|
+
let samples = 10;
|
|
24
|
+
let channels = 2;
|
|
25
|
+
let data = make_test_data(channels, samples);
|
|
26
|
+
Promise.all([8, 16, 24, 32, '32f'].map(bitDepth => new Promise((resolve, reject) => {
|
|
27
|
+
let floatingPoint = false;
|
|
28
|
+
if (bitDepth == '32f') {
|
|
29
|
+
bitDepth = 32;
|
|
30
|
+
floatingPoint = true;
|
|
31
|
+
}
|
|
32
|
+
let audioData = {
|
|
33
|
+
length: samples,
|
|
34
|
+
numberOfChannels: channels,
|
|
35
|
+
sampleRate: 16000,
|
|
36
|
+
channelData: data
|
|
37
|
+
};
|
|
38
|
+
let opts = {
|
|
39
|
+
floatingPoint: floatingPoint,
|
|
40
|
+
bitDepth: bitDepth,
|
|
41
|
+
};
|
|
42
|
+
encoder.encode(audioData, opts).then(buffer => {
|
|
43
|
+
let encoded = wav.encode(audioData.channelData, opts);
|
|
44
|
+
test.equal(new Buffer(buffer).toString('hex'), encoded.toString('hex'), 'our encoder should match wav-encoder');
|
|
45
|
+
let decoded = wav.decode(buffer);
|
|
46
|
+
decoder.decode(buffer).then(reference => {
|
|
47
|
+
test.equal(reference.length, decoded.channelData[0].length, 'number of samples should match');
|
|
48
|
+
test.equal(reference.numberOfChannels, decoded.channelData.length, 'number of channels should match');
|
|
49
|
+
test.equal(reference.sampleRate, decoded.sampleRate, 'sample rate should match');
|
|
50
|
+
test.deepEqual(reference.channelData, decoded.channelData, 'data should match');
|
|
51
|
+
resolve();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}))).then(() => test.done());
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
exports.test_buffer_offset = test => {
|
|
58
|
+
test.expect(1);
|
|
59
|
+
let files = ["./tests/file1.wav"];
|
|
60
|
+
files.forEach(file => {
|
|
61
|
+
let buffer = fs.readFileSync(file);
|
|
62
|
+
let decoded = wav.decode(buffer);
|
|
63
|
+
test.equal(decoded.sampleRate, 16000);
|
|
64
|
+
test.done();
|
|
65
|
+
});
|
|
66
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
let fs = require('fs');
|
|
2
|
+
let wav = require('./index');
|
|
3
|
+
|
|
4
|
+
//let files = JSON.parse(fs.readFileSync('x.json'));
|
|
5
|
+
|
|
6
|
+
let files = ["../train/data//other/0005932e-db17-4a21-b99f-5e10f84a9e74.wav"];
|
|
7
|
+
|
|
8
|
+
files.forEach(file => {
|
|
9
|
+
console.log(file);
|
|
10
|
+
let buffer = fs.readFileSync(file);
|
|
11
|
+
let w = wav.decode(buffer);
|
|
12
|
+
});
|