@libraz/libsonare 1.7.2 → 1.8.0
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/NOTICE +178 -0
- package/README.md +26 -203
- package/dist/_chain_config.d.ts +14 -0
- package/dist/_chain_config.d.ts.map +1 -0
- package/dist/_effects_common.d.ts +6 -0
- package/dist/_effects_common.d.ts.map +1 -0
- package/dist/_feature_validation.d.ts +8 -0
- package/dist/_feature_validation.d.ts.map +1 -0
- package/dist/_fft_options.d.ts +24 -0
- package/dist/_fft_options.d.ts.map +1 -0
- package/dist/align_take.d.ts +50 -0
- package/dist/align_take.d.ts.map +1 -0
- package/dist/analysis.d.ts +29 -5840
- package/dist/analysis.d.ts.map +1 -0
- package/dist/analysis.js +873 -722
- package/dist/analysis.js.map +1 -1
- package/dist/analysis_helpers.d.ts +9 -0
- package/dist/analysis_helpers.d.ts.map +1 -0
- package/dist/audio.d.ts +163 -0
- package/dist/audio.d.ts.map +1 -0
- package/dist/clip_page_streamer.d.ts +133 -0
- package/dist/clip_page_streamer.d.ts.map +1 -0
- package/dist/codes.d.ts +44 -0
- package/dist/codes.d.ts.map +1 -0
- package/dist/effects_mastering.d.ts +23 -0
- package/dist/effects_mastering.d.ts.map +1 -0
- package/dist/effects_note_ops.d.ts +477 -0
- package/dist/effects_note_ops.d.ts.map +1 -0
- package/dist/effects_percussive.d.ts +185 -0
- package/dist/effects_percussive.d.ts.map +1 -0
- package/dist/effects_separation.d.ts +65 -0
- package/dist/effects_separation.d.ts.map +1 -0
- package/dist/effects_spectral.d.ts +28 -0
- package/dist/effects_spectral.d.ts.map +1 -0
- package/dist/effects_timepitch.d.ts +129 -0
- package/dist/effects_timepitch.d.ts.map +1 -0
- package/dist/effects_voice_change.d.ts +53 -0
- package/dist/effects_voice_change.d.ts.map +1 -0
- package/dist/errors.d.ts +51 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/feature_core.d.ts +341 -0
- package/dist/feature_core.d.ts.map +1 -0
- package/dist/feature_decompose.d.ts +278 -0
- package/dist/feature_decompose.d.ts.map +1 -0
- package/dist/feature_inverse.d.ts +128 -0
- package/dist/feature_inverse.d.ts.map +1 -0
- package/dist/feature_loudness.d.ts +66 -0
- package/dist/feature_loudness.d.ts.map +1 -0
- package/dist/feature_music.d.ts +307 -0
- package/dist/feature_music.d.ts.map +1 -0
- package/dist/feature_pitch.d.ts +108 -0
- package/dist/feature_pitch.d.ts.map +1 -0
- package/dist/feature_resample.d.ts +16 -0
- package/dist/feature_resample.d.ts.map +1 -0
- package/dist/feature_spectral.d.ts +137 -0
- package/dist/feature_spectral.d.ts.map +1 -0
- package/dist/feature_spectrogram.d.ts +198 -0
- package/dist/feature_spectrogram.d.ts.map +1 -0
- package/dist/features.d.ts +10 -0
- package/dist/features.d.ts.map +1 -0
- package/dist/hrtf/default.shrf +0 -0
- package/dist/index.d.ts +74 -7431
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3758 -1362
- package/dist/index.js.map +1 -1
- package/dist/instrument_types.d.ts +517 -0
- package/dist/instrument_types.d.ts.map +1 -0
- package/dist/live_audio.d.ts +35 -0
- package/dist/live_audio.d.ts.map +1 -0
- package/dist/mastering_chain.d.ts +213 -0
- package/dist/mastering_chain.d.ts.map +1 -0
- package/dist/mastering_core.d.ts +457 -0
- package/dist/mastering_core.d.ts.map +1 -0
- package/dist/mastering_dynamics.d.ts +80 -0
- package/dist/mastering_dynamics.d.ts.map +1 -0
- package/dist/metering.d.ts +287 -0
- package/dist/metering.d.ts.map +1 -0
- package/dist/mixer.d.ts +464 -0
- package/dist/mixer.d.ts.map +1 -0
- package/dist/mixing_assistant.d.ts +62 -0
- package/dist/mixing_assistant.d.ts.map +1 -0
- package/dist/mixing_oneshot.d.ts +40 -0
- package/dist/mixing_oneshot.d.ts.map +1 -0
- package/dist/module_state.d.ts +15 -0
- package/dist/module_state.d.ts.map +1 -0
- package/dist/opfs_clip_pages.d.ts +28 -0
- package/dist/opfs_clip_pages.d.ts.map +1 -0
- package/dist/playback_renderer.d.ts +128 -0
- package/dist/playback_renderer.d.ts.map +1 -0
- package/dist/polyphony.d.ts +202 -0
- package/dist/polyphony.d.ts.map +1 -0
- package/dist/project.d.ts +8 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project_class.d.ts +562 -0
- package/dist/project_class.d.ts.map +1 -0
- package/dist/project_internal.d.ts +194 -0
- package/dist/project_internal.d.ts.map +1 -0
- package/dist/project_synth.d.ts +74 -0
- package/dist/project_synth.d.ts.map +1 -0
- package/dist/project_types.d.ts +652 -0
- package/dist/project_types.d.ts.map +1 -0
- package/dist/public_types.d.ts +185 -0
- package/dist/public_types.d.ts.map +1 -0
- package/dist/public_types_acoustic.d.ts +215 -0
- package/dist/public_types_acoustic.d.ts.map +1 -0
- package/dist/public_types_mastering.d.ts +510 -0
- package/dist/public_types_mastering.d.ts.map +1 -0
- package/dist/public_types_mixing.d.ts +436 -0
- package/dist/public_types_mixing.d.ts.map +1 -0
- package/dist/public_types_music.d.ts +619 -0
- package/dist/public_types_music.d.ts.map +1 -0
- package/dist/public_types_playback.d.ts +164 -0
- package/dist/public_types_playback.d.ts.map +1 -0
- package/dist/public_types_realtime.d.ts +174 -0
- package/dist/public_types_realtime.d.ts.map +1 -0
- package/dist/public_types_repair.d.ts +424 -0
- package/dist/public_types_repair.d.ts.map +1 -0
- package/dist/public_types_spectral.d.ts +697 -0
- package/dist/public_types_spectral.d.ts.map +1 -0
- package/dist/quick_analysis.d.ts +445 -0
- package/dist/quick_analysis.d.ts.map +1 -0
- package/dist/realtime_engine.d.ts +850 -0
- package/dist/realtime_engine.d.ts.map +1 -0
- package/dist/realtime_voice_changer.d.ts +158 -0
- package/dist/realtime_voice_changer.d.ts.map +1 -0
- package/dist/repair_dereverb.d.ts +187 -0
- package/dist/repair_dereverb.d.ts.map +1 -0
- package/dist/repair_impulsive.d.ts +186 -0
- package/dist/repair_impulsive.d.ts.map +1 -0
- package/dist/repair_noise.d.ts +239 -0
- package/dist/repair_noise.d.ts.map +1 -0
- package/dist/repair_trim.d.ts +123 -0
- package/dist/repair_trim.d.ts.map +1 -0
- package/dist/sample_bank.d.ts +84 -0
- package/dist/sample_bank.d.ts.map +1 -0
- package/dist/scale.d.ts +10 -0
- package/dist/scale.d.ts.map +1 -0
- package/dist/schemas/mixer-scene.schema.json +393 -0
- package/dist/schemas/playback-renderer-config.schema.json +392 -0
- package/dist/sonare-analysis.d.ts +8 -0
- package/dist/sonare-analysis.js +2 -2
- package/dist/sonare-analysis.wasm +0 -0
- package/dist/sonare.d.ts +3909 -0
- package/dist/sonare.js +2 -2
- package/dist/sonare.wasm +0 -0
- package/dist/stream_analyzer.d.ts +163 -0
- package/dist/stream_analyzer.d.ts.map +1 -0
- package/dist/stream_types.d.ts +214 -0
- package/dist/stream_types.d.ts.map +1 -0
- package/dist/streaming_mixing.d.ts +6 -0
- package/dist/streaming_mixing.d.ts.map +1 -0
- package/dist/streaming_processors.d.ts +335 -0
- package/dist/streaming_processors.d.ts.map +1 -0
- package/dist/transcribe.d.ts +77 -0
- package/dist/transcribe.d.ts.map +1 -0
- package/dist/validation.d.ts +140 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/web_midi.d.ts +77 -0
- package/dist/web_midi.d.ts.map +1 -0
- package/dist/worker.d.ts +5 -48
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +94 -41
- package/dist/worker.js.map +1 -1
- package/dist/worker_client.d.ts +96 -0
- package/dist/worker_client.d.ts.map +1 -0
- package/dist/worker_protocol.d.ts +43 -0
- package/dist/worker_protocol.d.ts.map +1 -0
- package/dist/worklet/audio_types.d.ts +21 -0
- package/dist/worklet/audio_types.d.ts.map +1 -0
- package/dist/worklet/engine-automation.d.ts +29 -0
- package/dist/worklet/engine-automation.d.ts.map +1 -0
- package/dist/worklet/engine-capture-facade.d.ts +35 -0
- package/dist/worklet/engine-capture-facade.d.ts.map +1 -0
- package/dist/worklet/engine-clips.d.ts +23 -0
- package/dist/worklet/engine-clips.d.ts.map +1 -0
- package/dist/worklet/engine-markers.d.ts +40 -0
- package/dist/worklet/engine-markers.d.ts.map +1 -0
- package/dist/worklet/engine-mixer-facade.d.ts +128 -0
- package/dist/worklet/engine-mixer-facade.d.ts.map +1 -0
- package/dist/worklet/engine-node.d.ts +81 -0
- package/dist/worklet/engine-node.d.ts.map +1 -0
- package/dist/worklet/engine-offline.d.ts +81 -0
- package/dist/worklet/engine-offline.d.ts.map +1 -0
- package/dist/worklet/engine-options.d.ts +12 -0
- package/dist/worklet/engine-options.d.ts.map +1 -0
- package/dist/worklet/engine-parameter-facade.d.ts +106 -0
- package/dist/worklet/engine-parameter-facade.d.ts.map +1 -0
- package/dist/worklet/engine-processor.d.ts +68 -0
- package/dist/worklet/engine-processor.d.ts.map +1 -0
- package/dist/worklet/engine-register.d.ts +2 -0
- package/dist/worklet/engine-register.d.ts.map +1 -0
- package/dist/worklet/engine-strips.d.ts +73 -0
- package/dist/worklet/engine-strips.d.ts.map +1 -0
- package/dist/worklet/engine-sync.d.ts +37 -0
- package/dist/worklet/engine-sync.d.ts.map +1 -0
- package/dist/worklet/engine-tempo-facade.d.ts +48 -0
- package/dist/worklet/engine-tempo-facade.d.ts.map +1 -0
- package/dist/worklet/engine.d.ts +397 -0
- package/dist/worklet/engine.d.ts.map +1 -0
- package/dist/worklet/guards.d.ts +47 -0
- package/dist/worklet/guards.d.ts.map +1 -0
- package/dist/worklet/messages.d.ts +710 -0
- package/dist/worklet/messages.d.ts.map +1 -0
- package/dist/worklet/mixer-processor.d.ts +46 -0
- package/dist/worklet/mixer-processor.d.ts.map +1 -0
- package/dist/worklet/playback-processor.d.ts +62 -0
- package/dist/worklet/playback-processor.d.ts.map +1 -0
- package/dist/worklet/protocol.d.ts +323 -0
- package/dist/worklet/protocol.d.ts.map +1 -0
- package/dist/worklet/voice-changer-processor.d.ts +41 -0
- package/dist/worklet/voice-changer-processor.d.ts.map +1 -0
- package/dist/worklet.d.ts +16 -2515
- package/dist/worklet.d.ts.map +1 -0
- package/dist/worklet.js +2763 -501
- package/dist/worklet.js.map +1 -1
- package/package.json +23 -12
- package/src/_effects_common.ts +17 -0
- package/src/_feature_validation.ts +34 -0
- package/src/_fft_options.ts +39 -0
- package/src/align_take.ts +64 -0
- package/src/analysis.ts +56 -3
- package/src/analysis_helpers.ts +7 -0
- package/src/audio.ts +106 -3
- package/src/codes.ts +39 -2
- package/src/effects_mastering.ts +97 -22
- package/src/effects_note_ops.ts +635 -0
- package/src/effects_percussive.ts +217 -0
- package/src/effects_separation.ts +150 -0
- package/src/effects_spectral.ts +60 -0
- package/src/effects_timepitch.ts +377 -0
- package/src/errors.ts +23 -1
- package/src/feature_core.ts +127 -2
- package/src/feature_decompose.ts +633 -0
- package/src/feature_inverse.ts +454 -0
- package/src/feature_loudness.ts +125 -0
- package/src/feature_music.ts +107 -14
- package/src/feature_pitch.ts +96 -1
- package/src/feature_spectral.ts +16 -611
- package/src/feature_spectrogram.ts +63 -450
- package/src/features.ts +36 -22
- package/src/index.ts +282 -30
- package/src/instrument_types.ts +645 -0
- package/src/live_audio.ts +27 -1
- package/src/mastering_chain.ts +184 -0
- package/src/mastering_core.ts +346 -32
- package/src/mastering_dynamics.ts +22 -11
- package/src/metering.ts +67 -24
- package/src/mixer.ts +212 -3
- package/src/mixing_assistant.ts +138 -0
- package/src/mixing_oneshot.ts +10 -5
- package/src/module_state.ts +24 -2
- package/src/playback_renderer.ts +252 -0
- package/src/polyphony.ts +279 -0
- package/src/project.ts +61 -24
- package/src/project_class.ts +450 -27
- package/src/project_internal.ts +149 -42
- package/src/project_synth.ts +67 -1
- package/src/project_types.ts +268 -270
- package/src/public_types.ts +122 -3
- package/src/public_types_acoustic.ts +112 -3
- package/src/public_types_mastering.ts +254 -73
- package/src/public_types_mixing.ts +363 -1
- package/src/public_types_music.ts +312 -2
- package/src/public_types_playback.ts +195 -0
- package/src/public_types_realtime.ts +39 -7
- package/src/public_types_repair.ts +446 -0
- package/src/public_types_spectral.ts +487 -1
- package/src/quick_analysis.ts +203 -26
- package/src/realtime_engine.ts +711 -28
- package/src/realtime_voice_changer.ts +55 -1
- package/src/repair_dereverb.ts +299 -0
- package/src/repair_impulsive.ts +395 -0
- package/src/repair_noise.ts +425 -0
- package/src/repair_trim.ts +226 -0
- package/src/sample_bank.ts +113 -0
- package/src/sonare.js.d.ts +1122 -30
- package/src/stream_analyzer.ts +36 -4
- package/src/stream_types.ts +37 -0
- package/src/streaming_mixing.ts +1 -1
- package/src/streaming_processors.ts +194 -10
- package/src/transcribe.ts +89 -0
- package/src/validation.ts +285 -11
- package/src/web_midi.ts +1 -6
- package/src/worker.ts +18 -2
- package/src/worklet/audio_types.ts +37 -0
- package/src/worklet/engine-mixer-facade.ts +444 -10
- package/src/worklet/engine-node.ts +78 -26
- package/src/worklet/engine-offline.ts +14 -8
- package/src/worklet/engine-parameter-facade.ts +21 -0
- package/src/worklet/engine-processor.ts +272 -83
- package/src/worklet/engine-register.ts +32 -18
- package/src/worklet/engine-strips.ts +280 -9
- package/src/worklet/engine-sync.ts +14 -6
- package/src/worklet/engine.ts +365 -31
- package/src/worklet/guards.ts +140 -44
- package/src/worklet/messages.ts +227 -2
- package/src/worklet/mixer-processor.ts +109 -47
- package/src/worklet/playback-processor.ts +300 -0
- package/src/worklet/protocol.ts +53 -3
- package/src/worklet/voice-changer-processor.ts +17 -11
- package/src/worklet.ts +17 -0
- package/src/effects_transform.ts +0 -718
- package/src/mastering_repair.ts +0 -273
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libraz/libsonare",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "yarn@4.18.0",
|
|
6
6
|
"description": "Audio analysis, mastering, mixing, and MIDI synthesis in WebAssembly",
|
|
@@ -26,33 +26,42 @@
|
|
|
26
26
|
"./wasm": "./dist/sonare.wasm",
|
|
27
27
|
"./schemas/realtime-voice-changer-preset.schema.json": "./dist/schemas/realtime-voice-changer-preset.schema.json",
|
|
28
28
|
"./schemas/realtime-voice-changer-preset-pack.schema.json": "./dist/schemas/realtime-voice-changer-preset-pack.schema.json",
|
|
29
|
+
"./schemas/mixer-scene.schema.json": "./dist/schemas/mixer-scene.schema.json",
|
|
30
|
+
"./schemas/playback-renderer-config.schema.json": "./dist/schemas/playback-renderer-config.schema.json",
|
|
31
|
+
"./hrtf/default.shrf": "./dist/hrtf/default.shrf",
|
|
29
32
|
"./package.json": "./package.json"
|
|
30
33
|
},
|
|
31
34
|
"files": [
|
|
32
35
|
"dist",
|
|
33
|
-
"src"
|
|
36
|
+
"src",
|
|
37
|
+
"NOTICE",
|
|
38
|
+
"!dist/*.sources.json"
|
|
34
39
|
],
|
|
35
40
|
"sideEffects": false,
|
|
36
41
|
"scripts": {
|
|
37
42
|
"build": "yarn build:wasm && yarn build:js",
|
|
38
43
|
"build:wasm": "yarn build:wasm:full && yarn build:wasm:analysis",
|
|
39
|
-
"build:wasm:full": "mkdir -p build-wasm/em-cache && EM_NODE_JS=\"$(mise which node 2>/dev/null || command -v node)\" EM_CACHE=$PWD/build-wasm/em-cache emcmake cmake -S ../.. -B build-wasm -DBUILD_WASM=ON -DSONARE_WASM_ANALYSIS_ONLY=OFF -DSONARE_WASM_OUTPUT_NAME=sonare -DBUILD_MASTERING=ON -DBUILD_MIXING=ON -DBUILD_GRAPH=ON -DBUILD_FX=ON -DBUILD_ACOUSTIC_SIM=ON -DBUILD_PITCH_EDITOR=ON -DBUILD_VOICE_CHANGER=ON -DBUILD_ARRANGEMENT=ON -DBUILD_ASSIST=ON -DCMAKE_BUILD_TYPE=Release && EM_NODE_JS=\"$(mise which node 2>/dev/null || command -v node)\" EM_CACHE=$PWD/build-wasm/em-cache cmake --build build-wasm",
|
|
40
|
-
"build:wasm:analysis": "mkdir -p build-wasm-analysis/em-cache && EM_NODE_JS=\"$(mise which node 2>/dev/null || command -v node)\" EM_CACHE=$PWD/build-wasm-analysis/em-cache emcmake cmake -S ../.. -B build-wasm-analysis -DBUILD_WASM=ON -DSONARE_WASM_ANALYSIS_ONLY=ON -DSONARE_WASM_OUTPUT_NAME=sonare-analysis -DBUILD_MASTERING=OFF -DBUILD_MIXING=OFF -DBUILD_GRAPH=OFF -DBUILD_FX=OFF -DBUILD_ACOUSTIC_SIM=OFF -DBUILD_VOICE_CHANGER=OFF -DBUILD_ARRANGEMENT=OFF -DBUILD_ASSIST=OFF -DCMAKE_BUILD_TYPE=Release && EM_NODE_JS=\"$(mise which node 2>/dev/null || command -v node)\" EM_CACHE=$PWD/build-wasm-analysis/em-cache cmake --build build-wasm-analysis --target sonare",
|
|
44
|
+
"build:wasm:full": "mkdir -p build-wasm/em-cache && EM_NODE_JS=\"$(mise which node 2>/dev/null || command -v node)\" EM_CACHE=$PWD/build-wasm/em-cache emcmake cmake -S ../.. -B build-wasm -DBUILD_WASM=ON -DSONARE_WASM_ANALYSIS_ONLY=OFF -DSONARE_WASM_OUTPUT_NAME=sonare -DBUILD_MASTERING=ON -DBUILD_MIXING=ON -DBUILD_MIXING_ASSISTANT=ON -DBUILD_GRAPH=ON -DBUILD_FX=ON -DBUILD_ACOUSTIC_SIM=ON -DBUILD_PITCH_EDITOR=ON -DBUILD_VOICE_CHANGER=ON -DBUILD_ARRANGEMENT=ON -DBUILD_ASSIST=ON -DCMAKE_BUILD_TYPE=Release && EM_NODE_JS=\"$(mise which node 2>/dev/null || command -v node)\" EM_CACHE=$PWD/build-wasm/em-cache cmake --build build-wasm && node scripts/dist-source-manifest.mjs --write sonare",
|
|
45
|
+
"build:wasm:analysis": "mkdir -p build-wasm-analysis/em-cache && EM_NODE_JS=\"$(mise which node 2>/dev/null || command -v node)\" EM_CACHE=$PWD/build-wasm-analysis/em-cache emcmake cmake -S ../.. -B build-wasm-analysis -DBUILD_WASM=ON -DSONARE_WASM_ANALYSIS_ONLY=ON -DSONARE_WASM_OUTPUT_NAME=sonare-analysis -DBUILD_MASTERING=OFF -DBUILD_MIXING=OFF -DBUILD_MIXING_ASSISTANT=OFF -DBUILD_GRAPH=OFF -DBUILD_FX=OFF -DBUILD_ACOUSTIC_SIM=OFF -DBUILD_VOICE_CHANGER=OFF -DBUILD_ARRANGEMENT=OFF -DBUILD_ASSIST=OFF -DCMAKE_BUILD_TYPE=Release && EM_NODE_JS=\"$(mise which node 2>/dev/null || command -v node)\" EM_CACHE=$PWD/build-wasm-analysis/em-cache cmake --build build-wasm-analysis --target sonare && node scripts/dist-source-manifest.mjs --write sonare-analysis",
|
|
46
|
+
"check:dist-freshness": "node scripts/dist-source-manifest.mjs",
|
|
41
47
|
"check:wasm-size": "python3 ../../tools/check_wasm_size.py --baseline wasm-size-budget.json --artifact sonare.wasm=dist/sonare.wasm --artifact sonare-analysis.wasm=dist/sonare-analysis.wasm",
|
|
48
|
+
"check:wasm-size:record": "python3 ../../tools/check_wasm_size.py --baseline wasm-size-baseline.json --artifact sonare.wasm=dist/sonare.wasm --artifact sonare-analysis.wasm=dist/sonare-analysis.wasm --write-baseline",
|
|
42
49
|
"bench:wasm:isp": "mkdir -p build-wasm-bench/em-cache /tmp/libsonare-wasm-bench && EM_CACHE=$PWD/build-wasm-bench/em-cache emcmake cmake -S ../.. -B build-wasm-bench -DBUILD_WASM=ON -DBUILD_MASTERING=ON -DBUILD_BENCH=ON -DBUILD_TESTING=OFF -DBUILD_CLI=OFF -DCMAKE_BUILD_TYPE=Release && EM_CACHE=$PWD/build-wasm-bench/em-cache cmake --build build-wasm-bench --target sonare_mastering_isp_bench && cp build-wasm-bench/bin/sonare_mastering_isp_bench.js /tmp/libsonare-wasm-bench/sonare_mastering_isp_bench.cjs && cp build-wasm-bench/bin/sonare_mastering_isp_bench.wasm /tmp/libsonare-wasm-bench/sonare_mastering_isp_bench.wasm && node /tmp/libsonare-wasm-bench/sonare_mastering_isp_bench.cjs",
|
|
50
|
+
"bench:wasm:playback": "mkdir -p build-wasm-bench/em-cache /tmp/libsonare-wasm-bench && EM_CACHE=$PWD/build-wasm-bench/em-cache emcmake cmake -S ../.. -B build-wasm-bench -DBUILD_WASM=ON -DBUILD_MASTERING=ON -DBUILD_MIXING=ON -DBUILD_ACOUSTIC_SIM=ON -DBUILD_PLAYBACK=ON -DBUILD_BENCH=ON -DBUILD_TESTING=OFF -DBUILD_CLI=OFF -DCMAKE_BUILD_TYPE=Release && EM_CACHE=$PWD/build-wasm-bench/em-cache cmake --build build-wasm-bench --target sonare_playback_binaural_bench && cp build-wasm-bench/bin/sonare_playback_binaural_bench.js /tmp/libsonare-wasm-bench/sonare_playback_binaural_bench.cjs && cp build-wasm-bench/bin/sonare_playback_binaural_bench.wasm /tmp/libsonare-wasm-bench/sonare_playback_binaural_bench.wasm && node /tmp/libsonare-wasm-bench/sonare_playback_binaural_bench.cjs",
|
|
43
51
|
"bench:wasm:phase-vocoder": "mkdir -p build-wasm-bench/em-cache /tmp/libsonare-wasm-bench && EM_CACHE=$PWD/build-wasm-bench/em-cache emcmake cmake -S ../.. -B build-wasm-bench -DBUILD_WASM=ON -DBUILD_BENCH=ON -DBUILD_TESTING=OFF -DBUILD_CLI=OFF -DCMAKE_BUILD_TYPE=Release && EM_CACHE=$PWD/build-wasm-bench/em-cache cmake --build build-wasm-bench --target sonare_phase_vocoder_streaming_bench && cp build-wasm-bench/bin/sonare_phase_vocoder_streaming_bench.js /tmp/libsonare-wasm-bench/sonare_phase_vocoder_streaming_bench.cjs && cp build-wasm-bench/bin/sonare_phase_vocoder_streaming_bench.wasm /tmp/libsonare-wasm-bench/sonare_phase_vocoder_streaming_bench.wasm && node /tmp/libsonare-wasm-bench/sonare_phase_vocoder_streaming_bench.cjs",
|
|
44
|
-
"build:js": "tsup && node scripts/copy-schemas.mjs",
|
|
52
|
+
"build:js": "tsup && yarn build:types && node scripts/copy-schemas.mjs && node scripts/copy-hrtf.mjs && node scripts/copy-module-types.mjs && node scripts/dist-source-manifest.mjs --write bundle",
|
|
53
|
+
"build:types": "node scripts/prune-dist-declarations.mjs && tsc -p tsconfig.json --emitDeclarationOnly",
|
|
45
54
|
"clean": "rm -rf dist build-wasm build-wasm-analysis LICENSE",
|
|
46
55
|
"lint": "biome check src/ tests/",
|
|
47
|
-
"lint:fix": "
|
|
48
|
-
"format": "
|
|
56
|
+
"lint:fix": "git ls-files -z -- 'src/**' 'tests/**' | xargs -0 biome check --write",
|
|
57
|
+
"format": "git ls-files -z -- 'src/**' 'tests/**' | xargs -0 biome format --write",
|
|
49
58
|
"test": "vitest run",
|
|
50
|
-
"test:types": "tsc --noEmit --ignoreConfig --strict --module ESNext --moduleResolution bundler --target ES2020 tests/typing/analysis-entry.ts tests/typing/worklet-capture-response.ts",
|
|
59
|
+
"test:types": "tsc --noEmit --ignoreConfig --strict --module ESNext --moduleResolution bundler --target ES2020 tests/typing/analysis-entry.ts tests/typing/dist-entry-shared-types.ts tests/typing/worklet-capture-response.ts && tsc --noEmit -p tsconfig.json && tsc -p tsconfig.test.json",
|
|
51
60
|
"test:browser": "node scripts/audio-worklet-smoke.mjs",
|
|
52
61
|
"test:browser:worker": "node scripts/offline-worker-smoke.mjs",
|
|
53
62
|
"test:browser:boundary": "node scripts/boundary-smoke.mjs",
|
|
54
63
|
"test:watch": "vitest",
|
|
55
|
-
"prepublishOnly": "yarn clean && cp ../../LICENSE LICENSE && yarn build && yarn lint && yarn test && yarn test:types"
|
|
64
|
+
"prepublishOnly": "yarn clean && cp ../../LICENSE LICENSE && cp ../../NOTICE NOTICE && yarn build && yarn lint && yarn test && yarn test:types"
|
|
56
65
|
},
|
|
57
66
|
"keywords": [
|
|
58
67
|
"audio",
|
|
@@ -90,10 +99,12 @@
|
|
|
90
99
|
"node": ">=18.0.0"
|
|
91
100
|
},
|
|
92
101
|
"devDependencies": {
|
|
93
|
-
"@biomejs/biome": "^2.
|
|
94
|
-
"
|
|
102
|
+
"@biomejs/biome": "^2.5.13",
|
|
103
|
+
"@types/node": "^22.20.3",
|
|
104
|
+
"ajv": "^8.20.0",
|
|
95
105
|
"tsup": "^8.5.1",
|
|
96
106
|
"typescript": "^6.0.3",
|
|
97
|
-
"
|
|
107
|
+
"vite": "^8.3.0",
|
|
108
|
+
"vitest": "^5.0.1"
|
|
98
109
|
}
|
|
99
110
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input conversion the effect families share.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { VoicedFlags } from './public_types';
|
|
6
|
+
|
|
7
|
+
// The embind layer reads the companion voicing array as Float32Array. A flag is
|
|
8
|
+
// a decision, not a magnitude: collapse to 1/0 on truthiness, which is the same
|
|
9
|
+
// reduction the Node facade applies, so both surfaces agree on every accepted
|
|
10
|
+
// input type.
|
|
11
|
+
export function toVoicedFloat32(voiced: VoicedFlags): Float32Array {
|
|
12
|
+
const out = new Float32Array(voiced.length);
|
|
13
|
+
for (let index = 0; index < voiced.length; index += 1) {
|
|
14
|
+
out[index] = voiced[index] ? 1 : 0;
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input checks the spectrogram and inverse-transform entries share.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ValidateOptions } from './validation';
|
|
6
|
+
import { assertFiniteScalar, assertPositiveInteger } from './validation';
|
|
7
|
+
|
|
8
|
+
export type GuardedOptions = ValidateOptions;
|
|
9
|
+
|
|
10
|
+
export function validatePositiveIntegers(fnName: string, values: Record<string, number>): void {
|
|
11
|
+
for (const [name, value] of Object.entries(values)) {
|
|
12
|
+
assertPositiveInteger(fnName, value, name);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function validateMelFrequencyRange(
|
|
17
|
+
fnName: string,
|
|
18
|
+
fmin: number,
|
|
19
|
+
fmax: number,
|
|
20
|
+
sampleRate: number,
|
|
21
|
+
): void {
|
|
22
|
+
assertFiniteScalar(fnName, fmin, 'fmin');
|
|
23
|
+
assertFiniteScalar(fnName, fmax, 'fmax');
|
|
24
|
+
if (fmin < 0) {
|
|
25
|
+
throw new RangeError(`${fnName}: fmin must be non-negative`);
|
|
26
|
+
}
|
|
27
|
+
if (fmax < 0) {
|
|
28
|
+
throw new RangeError(`${fnName}: fmax must be non-negative`);
|
|
29
|
+
}
|
|
30
|
+
const effectiveFmax = fmax === 0 ? sampleRate / 2 : fmax;
|
|
31
|
+
if (effectiveFmax <= fmin) {
|
|
32
|
+
throw new RangeError(`${fnName}: fmax must be greater than fmin`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertEvenIntegerAtLeast,
|
|
3
|
+
assertIntegerValue,
|
|
4
|
+
assertPositiveInteger,
|
|
5
|
+
} from './validation.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The facade's single FFT-size/hop domain.
|
|
9
|
+
*
|
|
10
|
+
* This module is deliberately internal: sibling facade modules import it, but
|
|
11
|
+
* nothing re-exports it, so it stays out of the package entry point and out of
|
|
12
|
+
* the C-ABI parity surface (which is defined by the index's re-export closure).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Resolves and validates the `nFft` / `hopLength` pair every STFT-backed entry
|
|
17
|
+
* point takes.
|
|
18
|
+
*
|
|
19
|
+
* The core FFT is mixed-radix, so any even size transforms exactly; only the
|
|
20
|
+
* real one-sided spectrum's `n_fft / 2 + 1` bin layout needs the evenness. A
|
|
21
|
+
* power-of-two restriction rejects sizes the C ABI and the native CLI accept,
|
|
22
|
+
* which is what a second copy of this rule used to do: `hpss({ nFft: 1536 })`
|
|
23
|
+
* worked while `hpssWithResidual({ nFft: 1536 })` threw, with the message
|
|
24
|
+
* asserting a constraint this project had explicitly written down as untrue.
|
|
25
|
+
* One implementation, so the two cannot disagree again.
|
|
26
|
+
*/
|
|
27
|
+
export function resolveFftOptions(
|
|
28
|
+
fnName: string,
|
|
29
|
+
nFft: unknown,
|
|
30
|
+
hopLength: unknown,
|
|
31
|
+
): { nFft: number; hopLength: number } {
|
|
32
|
+
const resolvedNFft = nFft === undefined ? 2048 : nFft;
|
|
33
|
+
const resolvedHopLength = hopLength === undefined ? 512 : hopLength;
|
|
34
|
+
assertIntegerValue(fnName, resolvedNFft, 'nFft');
|
|
35
|
+
assertEvenIntegerAtLeast(fnName, resolvedNFft, 'nFft', 2, 2 ** 30);
|
|
36
|
+
assertIntegerValue(fnName, resolvedHopLength, 'hopLength');
|
|
37
|
+
assertPositiveInteger(fnName, resolvedHopLength, 'hopLength');
|
|
38
|
+
return { nFft: resolvedNFft, hopLength: resolvedHopLength };
|
|
39
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { projectModule } from './project_internal';
|
|
2
|
+
import type { AlignTakeToReferenceRequest, AlignTakeToReferenceResult } from './project_types';
|
|
3
|
+
import { assertSampleRate, assertSamples } from './validation';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Aligns one take to a reference timeline and returns the warp anchors that place
|
|
7
|
+
* the take under it.
|
|
8
|
+
*
|
|
9
|
+
* A chromagram is measured for each signal and the two are aligned, then the
|
|
10
|
+
* alignment is reduced to anchors {@link Project.setWarpMap} accepts: at least
|
|
11
|
+
* two finite, strictly increasing pairs. The reduction is needed rather than
|
|
12
|
+
* decorative — an alignment path advances one axis at a time, so the raw
|
|
13
|
+
* correspondence repeats a coordinate wherever one signal carries more frames
|
|
14
|
+
* than the other, and those pairs are refused as a warp map.
|
|
15
|
+
*
|
|
16
|
+
* **The anchors are oriented for the take's own clip.** `warpSample` is a
|
|
17
|
+
* position on the REFERENCE timeline and `sourceSample` the corresponding
|
|
18
|
+
* position in the TAKE, which is the direction a clip whose source is that take
|
|
19
|
+
* needs. This is why the entry point exists rather than the core alignment
|
|
20
|
+
* primitive being exposed directly: that one names its arguments the other way
|
|
21
|
+
* round, so passing the reference as its reference yields the inverse map and
|
|
22
|
+
* nothing reports it.
|
|
23
|
+
*
|
|
24
|
+
* Both signals are read at `sampleRate`; resample first if they differ, since
|
|
25
|
+
* the alignment does no I/O and no rate conversion.
|
|
26
|
+
*
|
|
27
|
+
* {@link AlignTakeToReferenceResult.alignment} is descriptive only — it says how
|
|
28
|
+
* far the path strayed from a constant rate, so a caller can tell a take the
|
|
29
|
+
* reference genuinely fits from one it does not, and supplies its own threshold.
|
|
30
|
+
*
|
|
31
|
+
* @param request - The two signals, their shared sample rate, and the chroma
|
|
32
|
+
* resolution
|
|
33
|
+
* @returns The anchors and how well the alignment was conditioned
|
|
34
|
+
* @throws {RangeError} on an empty buffer, a non-finite sample, or a `sampleRate`
|
|
35
|
+
* outside `[8000, 384000]`
|
|
36
|
+
* @throws {SonareError} `InvalidParameter` on a non-positive `hopLength` or
|
|
37
|
+
* `binsPerOctave`, on a `binsPerOctave` that is not a multiple of 12, on a
|
|
38
|
+
* signal too short to measure two chroma frames, or when the two signals produce
|
|
39
|
+
* no pair of distinct anchors — which is what an unalignable pair looks like,
|
|
40
|
+
* and is reported rather than answered with a map you cannot use
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const { anchors } = alignTakeToReference({ reference: guide, take, sampleRate });
|
|
45
|
+
* const project = new Project();
|
|
46
|
+
* const trackId = project.addTrack({ kind: 'audio' });
|
|
47
|
+
* const clipId = project.addClip({ trackId, lengthPpq: 64, audio: take, audioSampleRate: sampleRate }); // 16 bars at 4/4, in quarter notes (PPQ)
|
|
48
|
+
* project.setWarpMap({ id: 1, anchors });
|
|
49
|
+
* project.setClipWarpRef(clipId, 1);
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function alignTakeToReference(
|
|
53
|
+
request: AlignTakeToReferenceRequest,
|
|
54
|
+
): AlignTakeToReferenceResult {
|
|
55
|
+
assertSamples('alignTakeToReference', request.reference, true, 'reference');
|
|
56
|
+
assertSamples('alignTakeToReference', request.take, true, 'take');
|
|
57
|
+
assertSampleRate('alignTakeToReference', request.sampleRate);
|
|
58
|
+
return projectModule().alignTakeToReference(
|
|
59
|
+
request.reference,
|
|
60
|
+
request.take,
|
|
61
|
+
request.sampleRate,
|
|
62
|
+
request,
|
|
63
|
+
);
|
|
64
|
+
}
|
package/src/analysis.ts
CHANGED
|
@@ -12,11 +12,61 @@ import type { SonareModule } from './sonare.js';
|
|
|
12
12
|
|
|
13
13
|
export { ErrorCode, isSonareError, SonareError } from './errors';
|
|
14
14
|
export * from './feature_core';
|
|
15
|
+
// Several modules here also hold functions the analysis-only embind source set
|
|
16
|
+
// never registers, so those are re-exported by name rather than wholesale:
|
|
17
|
+
// `export *` published symbols that imported fine and then threw
|
|
18
|
+
// "is not a function" at call time, on a binary that never had them. Types stay
|
|
19
|
+
// wholesale — a type cannot fail to resolve. `analysis-entry.test.ts` guards
|
|
20
|
+
// these lists in one direction: every function the entry exports must be
|
|
21
|
+
// registered by the module it loads, so a name the analysis binary lacks fails
|
|
22
|
+
// as a test rather than at a caller's first call. The other direction is not
|
|
23
|
+
// guarded and a strict form of it would be wrong — the module also registers
|
|
24
|
+
// enums, emscripten internals and raw `_` / `Ex` variants this entry withholds
|
|
25
|
+
// deliberately — so a name dropped from a list below shrinks the published
|
|
26
|
+
// surface silently.
|
|
27
|
+
export type * from './feature_decompose';
|
|
28
|
+
export {
|
|
29
|
+
segmentAgglomerative,
|
|
30
|
+
segmentCrossSimilarity,
|
|
31
|
+
segmentLagToRecurrence,
|
|
32
|
+
segmentPathEnhance,
|
|
33
|
+
segmentRecurrenceMatrix,
|
|
34
|
+
segmentRecurrenceToLag,
|
|
35
|
+
segmentSubsegment,
|
|
36
|
+
} from './feature_decompose';
|
|
37
|
+
export type * from './feature_inverse';
|
|
38
|
+
export { griffinLim, melToAudio, melToStft, mfccToAudio, mfccToMel } from './feature_inverse';
|
|
39
|
+
export type * from './feature_loudness';
|
|
40
|
+
export { ebur128LoudnessRange, lufsInterleaved, lufsSeriesInterleaved } from './feature_loudness';
|
|
15
41
|
export * from './feature_music';
|
|
16
42
|
export * from './feature_pitch';
|
|
17
|
-
export * from './feature_resample';
|
|
18
|
-
export * from './feature_spectral';
|
|
19
|
-
export
|
|
43
|
+
export type * from './feature_resample';
|
|
44
|
+
export type * from './feature_spectral';
|
|
45
|
+
export {
|
|
46
|
+
polyFeatures,
|
|
47
|
+
rmsEnergy,
|
|
48
|
+
spectralBandwidth,
|
|
49
|
+
spectralCentroid,
|
|
50
|
+
spectralContrast,
|
|
51
|
+
spectralFlatness,
|
|
52
|
+
spectralFlux,
|
|
53
|
+
spectralRolloff,
|
|
54
|
+
zeroCrossingRate,
|
|
55
|
+
zeroCrossings,
|
|
56
|
+
} from './feature_spectral';
|
|
57
|
+
export type * from './feature_spectrogram';
|
|
58
|
+
export {
|
|
59
|
+
bassChroma,
|
|
60
|
+
chroma,
|
|
61
|
+
chromaCens,
|
|
62
|
+
chromaCqt,
|
|
63
|
+
melDelta,
|
|
64
|
+
melSpectrogram,
|
|
65
|
+
mfcc,
|
|
66
|
+
reassignedSpectrogram,
|
|
67
|
+
stft,
|
|
68
|
+
stftDb,
|
|
69
|
+
} from './feature_spectrogram';
|
|
20
70
|
export * from './metering';
|
|
21
71
|
export * from './public_types';
|
|
22
72
|
export type {
|
|
@@ -33,6 +83,8 @@ export type {
|
|
|
33
83
|
DetectChordsRequest,
|
|
34
84
|
DetectKeyRequest,
|
|
35
85
|
DynamicsAnalysisResult,
|
|
86
|
+
DynamicsResult,
|
|
87
|
+
EstimateMeterRequest,
|
|
36
88
|
MusicAnalyzeOptions,
|
|
37
89
|
MusicAnalyzeRequest,
|
|
38
90
|
RhythmAnalysisResult,
|
|
@@ -57,6 +109,7 @@ export {
|
|
|
57
109
|
detectKey,
|
|
58
110
|
detectKeyCandidates,
|
|
59
111
|
detectOnsets,
|
|
112
|
+
estimateMeter,
|
|
60
113
|
hasFfmpegSupport,
|
|
61
114
|
} from './quick_analysis';
|
|
62
115
|
|
package/src/analysis_helpers.ts
CHANGED
|
@@ -118,6 +118,7 @@ export function convertChordAnalysisResult(wasm: WasmChordAnalysisResult): Chord
|
|
|
118
118
|
quality: c.quality as ChordQuality,
|
|
119
119
|
start: c.start,
|
|
120
120
|
end: c.end,
|
|
121
|
+
duration: c.end - c.start,
|
|
121
122
|
confidence: c.confidence,
|
|
122
123
|
name: c.name,
|
|
123
124
|
})),
|
|
@@ -158,6 +159,10 @@ export function convertAnalysisResult(wasm: WasmAnalysisResult): AnalysisResult
|
|
|
158
159
|
timeSignatureCandidates: wasm.timeSignatureCandidates,
|
|
159
160
|
beatTimes,
|
|
160
161
|
beats: wasm.beats,
|
|
162
|
+
downbeatIndices: wasm.downbeatIndices,
|
|
163
|
+
downbeatPhase: wasm.downbeatPhase,
|
|
164
|
+
beatObservations: wasm.beatObservations,
|
|
165
|
+
beatLocalBpm: wasm.beatLocalBpm,
|
|
161
166
|
chords: wasm.chords.map((c) => ({
|
|
162
167
|
root: c.root as PitchClass,
|
|
163
168
|
bass: c.bass as PitchClass,
|
|
@@ -166,8 +171,10 @@ export function convertAnalysisResult(wasm: WasmAnalysisResult): AnalysisResult
|
|
|
166
171
|
quality: c.quality as ChordQuality,
|
|
167
172
|
start: c.start,
|
|
168
173
|
end: c.end,
|
|
174
|
+
duration: c.end - c.start,
|
|
169
175
|
confidence: c.confidence,
|
|
170
176
|
name: c.name,
|
|
177
|
+
romanNumeral: c.romanNumeral,
|
|
171
178
|
})),
|
|
172
179
|
sections: wasm.sections.map((s) => ({
|
|
173
180
|
type: s.type as SectionType,
|
package/src/audio.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from './effects_mastering';
|
|
18
18
|
import {
|
|
19
19
|
chroma,
|
|
20
|
+
ebur128LoudnessRange,
|
|
20
21
|
lufs,
|
|
21
22
|
melSpectrogram,
|
|
22
23
|
mfcc,
|
|
@@ -37,6 +38,26 @@ import {
|
|
|
37
38
|
trim,
|
|
38
39
|
zeroCrossingRate,
|
|
39
40
|
} from './features';
|
|
41
|
+
import type {
|
|
42
|
+
ClippingReport,
|
|
43
|
+
DynamicRangeReport,
|
|
44
|
+
MeteringDetectClippingOptions,
|
|
45
|
+
MeteringDynamicRangeOptions,
|
|
46
|
+
SpectrumOptions,
|
|
47
|
+
SpectrumReport,
|
|
48
|
+
} from './metering';
|
|
49
|
+
import {
|
|
50
|
+
meteringCrestFactorDb,
|
|
51
|
+
meteringDcOffset,
|
|
52
|
+
meteringDetectClipping,
|
|
53
|
+
meteringDynamicRange,
|
|
54
|
+
meteringPeakDb,
|
|
55
|
+
meteringRmsDb,
|
|
56
|
+
meteringSilenceRatio,
|
|
57
|
+
meteringSpectrum,
|
|
58
|
+
meteringSpectrumFrame,
|
|
59
|
+
meteringTruePeakDb,
|
|
60
|
+
} from './metering';
|
|
40
61
|
import { getSonareModule } from './module_state';
|
|
41
62
|
import type {
|
|
42
63
|
AnalysisResult,
|
|
@@ -63,6 +84,7 @@ import type {
|
|
|
63
84
|
SoloProcessor,
|
|
64
85
|
StftResult,
|
|
65
86
|
} from './public_types';
|
|
87
|
+
import type { MusicAnalyzeOptions } from './quick_analysis';
|
|
66
88
|
import {
|
|
67
89
|
analyze,
|
|
68
90
|
analyzeWithProgress,
|
|
@@ -76,6 +98,7 @@ import {
|
|
|
76
98
|
detectOnsets,
|
|
77
99
|
} from './quick_analysis';
|
|
78
100
|
import type { ProgressCallback, WasmNnlsChromaResult } from './sonare.js';
|
|
101
|
+
import type { ValidateOptions } from './validation';
|
|
79
102
|
import { validateAudioBuffer } from './validation';
|
|
80
103
|
|
|
81
104
|
// ============================================================================
|
|
@@ -146,7 +169,14 @@ async function closeCreatedContext(context: BrowserDecodeContext): Promise<void>
|
|
|
146
169
|
}
|
|
147
170
|
|
|
148
171
|
/**
|
|
149
|
-
* Wrapper around audio data that exposes
|
|
172
|
+
* Wrapper around audio data that exposes analysis and feature functions as
|
|
173
|
+
* instance methods.
|
|
174
|
+
*
|
|
175
|
+
* Not every module-level function has a method here — `analyzeBpm`,
|
|
176
|
+
* `analyzeRhythm`, `analyzeDynamics`, `analyzeTimbre`, `analyzeImpulseResponse`
|
|
177
|
+
* and `detectAcoustic` are reachable as free functions only, and the Node
|
|
178
|
+
* facade exposes them as methods as well. Where a method does exist on both, it
|
|
179
|
+
* takes the same arguments.
|
|
150
180
|
*
|
|
151
181
|
* @example
|
|
152
182
|
* ```typescript
|
|
@@ -302,8 +332,15 @@ export class Audio {
|
|
|
302
332
|
return chordFunctionalAnalysis(this._samples, keyRoot, keyMode, this._sampleRate, options);
|
|
303
333
|
}
|
|
304
334
|
|
|
305
|
-
|
|
306
|
-
|
|
335
|
+
/**
|
|
336
|
+
* Full music analysis of the held buffer.
|
|
337
|
+
*
|
|
338
|
+
* Takes the same option bag as the module-level {@link analyze} and as the
|
|
339
|
+
* Node facade's `Audio.analyze`; this method used to drop it, so the same
|
|
340
|
+
* call was tunable on one binding and fixed at the defaults on the other.
|
|
341
|
+
*/
|
|
342
|
+
analyze(options: MusicAnalyzeOptions = {}): AnalysisResult {
|
|
343
|
+
return analyze(this._samples, this._sampleRate, options);
|
|
307
344
|
}
|
|
308
345
|
|
|
309
346
|
analyzeWithProgress(onProgress: ProgressCallback): AnalysisResult {
|
|
@@ -517,4 +554,70 @@ export class Audio {
|
|
|
517
554
|
resample(targetSr: number): Float32Array {
|
|
518
555
|
return resample(this._samples, this._sampleRate, targetSr);
|
|
519
556
|
}
|
|
557
|
+
|
|
558
|
+
// -- Metering --
|
|
559
|
+
//
|
|
560
|
+
// These delegate to the module-level buffer-form functions rather than a
|
|
561
|
+
// native handle: WASM's Audio is a plain JS wrapper around a Float32Array,
|
|
562
|
+
// not an embind class, so there is no cheaper path to reach the same
|
|
563
|
+
// measurement. The methods exist for call-shape parity with Node/Python,
|
|
564
|
+
// which do hold a native handle here.
|
|
565
|
+
|
|
566
|
+
peakDb(): number {
|
|
567
|
+
return meteringPeakDb(this._samples, this._sampleRate);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
rmsDb(): number {
|
|
571
|
+
return meteringRmsDb(this._samples, this._sampleRate);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
dcOffset(): number {
|
|
575
|
+
return meteringDcOffset(this._samples, this._sampleRate);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
crestFactorDb(): number {
|
|
579
|
+
return meteringCrestFactorDb(this._samples, this._sampleRate);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
silenceRatio(thresholdDb = -45, frameLength = 1024, hopLength = 256): number {
|
|
583
|
+
return meteringSilenceRatio(
|
|
584
|
+
this._samples,
|
|
585
|
+
this._sampleRate,
|
|
586
|
+
thresholdDb,
|
|
587
|
+
frameLength,
|
|
588
|
+
hopLength,
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Inter-sample (true) peak in dBFS. `oversampleFactor` must be a power of two
|
|
594
|
+
* in [1, 16]; pass 0 to use the library default (4).
|
|
595
|
+
*/
|
|
596
|
+
truePeakDb(oversampleFactor = 4): number {
|
|
597
|
+
return meteringTruePeakDb(this._samples, this._sampleRate, oversampleFactor);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
detectClipping(options: MeteringDetectClippingOptions = {}): ClippingReport {
|
|
601
|
+
return meteringDetectClipping(this._samples, this._sampleRate, options);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
dynamicRange(options: MeteringDynamicRangeOptions = {}): DynamicRangeReport {
|
|
605
|
+
return meteringDynamicRange(this._samples, this._sampleRate, options);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
spectrum(options: SpectrumOptions & ValidateOptions = {}): SpectrumReport {
|
|
609
|
+
return meteringSpectrum(this._samples, this._sampleRate, options);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* True single-frame magnitude / power / dB spectrum starting at `frameOffset`.
|
|
614
|
+
* See {@link meteringSpectrumFrame} for the frame-validation contract.
|
|
615
|
+
*/
|
|
616
|
+
spectrumFrame(frameOffset = 0, options: SpectrumOptions & ValidateOptions = {}): SpectrumReport {
|
|
617
|
+
return meteringSpectrumFrame(this._samples, this._sampleRate, frameOffset, options);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
ebur128LoudnessRange(): number {
|
|
621
|
+
return ebur128LoudnessRange(this._samples, this._sampleRate);
|
|
622
|
+
}
|
|
520
623
|
}
|
package/src/codes.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ProjectAutomationCurve } from './project_types';
|
|
2
|
+
import type {
|
|
3
|
+
AutomationCurve,
|
|
4
|
+
MeterTap,
|
|
5
|
+
PanLawInput,
|
|
6
|
+
PanMode,
|
|
7
|
+
SendTiming,
|
|
8
|
+
SidechainSourceKind,
|
|
9
|
+
} from './public_types';
|
|
2
10
|
|
|
3
11
|
/** Resolve a numeric ordinal in an inclusive range without coercion. */
|
|
4
12
|
export function resolveOrdinalInRange(
|
|
@@ -41,12 +49,30 @@ export function resolveEnumOrdinal(
|
|
|
41
49
|
throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
|
|
42
50
|
}
|
|
43
51
|
|
|
44
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Automation curve spellings and their `SonareAutomationCurve` ordinals.
|
|
54
|
+
*
|
|
55
|
+
* Single source of truth for the vocabulary: {@link AutomationCurve} and
|
|
56
|
+
* {@link ProjectAutomationCurve} are derived from these keys, so a spelling
|
|
57
|
+
* cannot be documented without resolving, or resolve without being documented.
|
|
58
|
+
*/
|
|
59
|
+
export const AUTOMATION_CURVE_VALUES = {
|
|
45
60
|
linear: 0,
|
|
46
61
|
exponential: 1,
|
|
47
62
|
hold: 2,
|
|
48
63
|
's-curve': 3,
|
|
49
64
|
} as const;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The Project facade additionally accepts the legacy `'scurve'` spelling for
|
|
68
|
+
* compatibility with project data written before `'s-curve'` was canonical.
|
|
69
|
+
* The Node package declares the same pair of tables, so a breakpoint accepted
|
|
70
|
+
* by one facade resolves to the same ordinal on the other.
|
|
71
|
+
*/
|
|
72
|
+
export const PROJECT_AUTOMATION_CURVE_VALUES = {
|
|
73
|
+
...AUTOMATION_CURVE_VALUES,
|
|
74
|
+
scurve: 3,
|
|
75
|
+
} as const;
|
|
50
76
|
const PAN_LAW_VALUES: Readonly<Record<string, number>> = {
|
|
51
77
|
const3db: 0,
|
|
52
78
|
'const-3db': 0,
|
|
@@ -72,12 +98,18 @@ const PAN_MODE_VALUES = {
|
|
|
72
98
|
} as const;
|
|
73
99
|
const METER_TAP_VALUES = { preFader: 0, postFader: 1 } as const;
|
|
74
100
|
const SEND_TIMING_VALUES = { postFader: 0, preFader: 1 } as const;
|
|
101
|
+
const SIDECHAIN_SOURCE_KIND_VALUES = { track: 0, bus: 1 } as const;
|
|
75
102
|
const TRACK_MONITOR_MODE_VALUES = { off: 0, pfl: 1, afl: 2 } as const;
|
|
76
103
|
|
|
77
104
|
export function automationCurveCode(curve: AutomationCurve): number {
|
|
78
105
|
return resolveEnumOrdinal(curve, AUTOMATION_CURVE_VALUES, 'automation curve');
|
|
79
106
|
}
|
|
80
107
|
|
|
108
|
+
/** Resolve a Project automation breakpoint curve, legacy spellings included. */
|
|
109
|
+
export function projectAutomationCurveCode(curve: ProjectAutomationCurve | undefined): number {
|
|
110
|
+
return resolveEnumOrdinal(curve ?? 'linear', PROJECT_AUTOMATION_CURVE_VALUES, 'automation curve');
|
|
111
|
+
}
|
|
112
|
+
|
|
81
113
|
export function panLawCode(panLaw: PanLawInput): number {
|
|
82
114
|
const normalized = typeof panLaw === 'string' ? panLaw.toLowerCase().replace(/_/g, '-') : panLaw;
|
|
83
115
|
return resolveEnumOrdinal(normalized, PAN_LAW_VALUES, 'pan law');
|
|
@@ -101,6 +133,11 @@ export function sendTimingCode(timing: SendTiming | number): number {
|
|
|
101
133
|
return resolveEnumOrdinal(timing, SEND_TIMING_VALUES, 'send timing');
|
|
102
134
|
}
|
|
103
135
|
|
|
136
|
+
/** Resolve a sidechain source kind to its `SonareSidechainSourceKind` ordinal. */
|
|
137
|
+
export function sidechainSourceKindCode(kind: SidechainSourceKind | number): number {
|
|
138
|
+
return resolveEnumOrdinal(kind, SIDECHAIN_SOURCE_KIND_VALUES, 'sidechain source kind');
|
|
139
|
+
}
|
|
140
|
+
|
|
104
141
|
/** Resolve a per-track PFL/AFL monitor mode to its C-ABI ordinal. */
|
|
105
142
|
export function trackMonitorModeCode(mode: unknown): number {
|
|
106
143
|
return resolveEnumOrdinal(mode, TRACK_MONITOR_MODE_VALUES, 'track monitor mode');
|