@allyhub/sdk 0.1.0-alpha.8 → 0.2.0-next.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 +85 -0
- package/client.d.ts +45 -1
- package/dist/anim.js +2 -75
- package/dist/define.d.ts +10 -4
- package/dist/define.js +2 -95
- package/dist/dom.d.ts +1 -1
- package/dist/dom.js +2 -457
- package/dist/fit.js +2 -60
- package/dist/free.d.ts +18 -0
- package/dist/free.js +2 -0
- package/dist/index.d.ts +28 -13
- package/dist/index.js +2 -11
- package/dist/input.d.ts +306 -0
- package/dist/input.js +2 -0
- package/dist/media.d.ts +3 -6
- package/dist/media.js +2 -27
- package/dist/messages.d.ts +3 -2
- package/dist/messages.js +2 -2
- package/dist/module.d.ts +24 -0
- package/dist/module.js +2 -0
- package/dist/noise.js +2 -233
- package/dist/parts.d.ts +97 -21
- package/dist/parts.js +2 -414
- package/dist/paths.d.ts +1 -1
- package/dist/paths.js +2 -720
- package/dist/phone.d.ts +26 -0
- package/dist/phone.js +2 -0
- package/dist/piece.d.ts +106 -35
- package/dist/piece.js +2 -38
- package/dist/props.d.ts +1 -1
- package/dist/props.js +2 -35
- package/dist/scenery.d.ts +2 -0
- package/dist/scenery.js +2 -0
- package/dist/text.js +2 -38
- package/dist/written.d.ts +12 -0
- package/dist/written.js +2 -0
- package/docs/README.md +18 -0
- package/docs/batches.md +148 -0
- package/docs/contract.md +51 -0
- package/docs/defaults.md +703 -0
- package/docs/docs.md +148 -0
- package/docs/footage.md +249 -0
- package/docs/layers.md +317 -0
- package/docs/modeling.md +143 -0
- package/docs/project.md +265 -0
- package/docs/scenery.md +308 -0
- package/docs/sheets.md +119 -0
- package/docs/slides.md +111 -0
- package/docs/sound.md +170 -0
- package/docs/speech.md +289 -0
- package/docs/video.md +265 -0
- package/node_modules/@allyhub-next/audio/dist/at-cut.d.ts +52 -0
- package/node_modules/@allyhub-next/audio/dist/at-cut.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/decode.d.ts +33 -0
- package/node_modules/@allyhub-next/audio/dist/decode.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/envelope.d.ts +37 -0
- package/node_modules/@allyhub-next/audio/dist/envelope.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/index.d.ts +17 -0
- package/node_modules/@allyhub-next/audio/dist/index.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/levels.d.ts +97 -0
- package/node_modules/@allyhub-next/audio/dist/levels.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/master.d.ts +29 -0
- package/node_modules/@allyhub-next/audio/dist/master.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/music.d.ts +11 -0
- package/node_modules/@allyhub-next/audio/dist/music.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/node/decode.d.ts +39 -0
- package/node_modules/@allyhub-next/audio/dist/node/decode.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/node/ebur128.d.ts +25 -0
- package/node_modules/@allyhub-next/audio/dist/node/ebur128.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/node/ffmpeg.d.ts +31 -0
- package/node_modules/@allyhub-next/audio/dist/node/ffmpeg.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/node/index.d.ts +8 -0
- package/node_modules/@allyhub-next/audio/dist/node/index.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/node/loudness.d.ts +18 -0
- package/node_modules/@allyhub-next/audio/dist/node/loudness.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/node/master.d.ts +42 -0
- package/node_modules/@allyhub-next/audio/dist/node/master.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/node/measure.d.ts +60 -0
- package/node_modules/@allyhub-next/audio/dist/node/measure.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/node/mix.d.ts +31 -0
- package/node_modules/@allyhub-next/audio/dist/node/mix.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/plan.d.ts +143 -0
- package/node_modules/@allyhub-next/audio/dist/plan.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recorded.d.ts +26 -0
- package/node_modules/@allyhub-next/audio/dist/recorded.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/bandwidth.d.ts +47 -0
- package/node_modules/@allyhub-next/audio/dist/recording/bandwidth.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/chain.d.ts +89 -0
- package/node_modules/@allyhub-next/audio/dist/recording/chain.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/dynamics.d.ts +64 -0
- package/node_modules/@allyhub-next/audio/dist/recording/dynamics.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/fft.d.ts +26 -0
- package/node_modules/@allyhub-next/audio/dist/recording/fft.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/filters.d.ts +42 -0
- package/node_modules/@allyhub-next/audio/dist/recording/filters.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/fit.d.ts +56 -0
- package/node_modules/@allyhub-next/audio/dist/recording/fit.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/index.d.ts +10 -0
- package/node_modules/@allyhub-next/audio/dist/recording/index.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/loudness.d.ts +12 -0
- package/node_modules/@allyhub-next/audio/dist/recording/loudness.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/measure.d.ts +67 -0
- package/node_modules/@allyhub-next/audio/dist/recording/measure.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/mic.d.ts +32 -0
- package/node_modules/@allyhub-next/audio/dist/recording/mic.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/noise.d.ts +27 -0
- package/node_modules/@allyhub-next/audio/dist/recording/noise.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/presets.d.ts +64 -0
- package/node_modules/@allyhub-next/audio/dist/recording/presets.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/room.d.ts +78 -0
- package/node_modules/@allyhub-next/audio/dist/recording/room.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/setup.d.ts +111 -0
- package/node_modules/@allyhub-next/audio/dist/recording/setup.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/recording/vec.d.ts +3 -0
- package/node_modules/@allyhub-next/audio/dist/recording/vec.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/render.d.ts +26 -0
- package/node_modules/@allyhub-next/audio/dist/render.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/sfx.d.ts +10 -0
- package/node_modules/@allyhub-next/audio/dist/sfx.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/shape.d.ts +118 -0
- package/node_modules/@allyhub-next/audio/dist/shape.js +2 -0
- package/node_modules/@allyhub-next/audio/dist/voice.d.ts +45 -0
- package/node_modules/@allyhub-next/audio/dist/voice.js +2 -0
- package/node_modules/@allyhub-next/audio/package.json +17 -0
- package/node_modules/@allyhub-next/formats/dist/data/comments.d.ts +94 -0
- package/node_modules/@allyhub-next/formats/dist/data/comments.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/config.d.ts +10 -0
- package/node_modules/@allyhub-next/formats/dist/data/config.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/edits.d.ts +28 -0
- package/node_modules/@allyhub-next/formats/dist/data/edits.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/elements.d.ts +6 -0
- package/node_modules/@allyhub-next/formats/dist/data/elements.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/faces.d.ts +38 -0
- package/node_modules/@allyhub-next/formats/dist/data/faces.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/file.d.ts +11 -0
- package/node_modules/@allyhub-next/formats/dist/data/file.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/gen.d.ts +31 -0
- package/node_modules/@allyhub-next/formats/dist/data/gen.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/messages.d.ts +34 -0
- package/node_modules/@allyhub-next/formats/dist/data/messages.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/reference.d.ts +676 -0
- package/node_modules/@allyhub-next/formats/dist/data/reference.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/script.d.ts +37 -0
- package/node_modules/@allyhub-next/formats/dist/data/script.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/sheet.d.ts +214 -0
- package/node_modules/@allyhub-next/formats/dist/data/sheet.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/data/words.d.ts +25 -0
- package/node_modules/@allyhub-next/formats/dist/data/words.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/index.d.ts +16 -0
- package/node_modules/@allyhub-next/formats/dist/index.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/items.d.ts +94 -0
- package/node_modules/@allyhub-next/formats/dist/items.js +2 -0
- package/node_modules/@allyhub-next/formats/dist/layout.d.ts +50 -0
- package/node_modules/@allyhub-next/formats/dist/layout.js +5 -0
- package/node_modules/@allyhub-next/formats/dist/schemas.d.ts +301 -0
- package/node_modules/@allyhub-next/formats/dist/schemas.js +2 -0
- package/node_modules/@allyhub-next/formats/package.json +14 -0
- package/node_modules/@allyhub-next/formats/schemas/comments.schema.json +152 -0
- package/node_modules/@allyhub-next/formats/schemas/config.schema.json +43 -0
- package/node_modules/@allyhub-next/formats/schemas/edits.schema.json +112 -0
- package/node_modules/@allyhub-next/formats/schemas/elements.schema.json +33 -0
- package/node_modules/@allyhub-next/formats/schemas/gen.schema.json +97 -0
- package/node_modules/@allyhub-next/formats/schemas/interpretation.schema.json +125 -0
- package/node_modules/@allyhub-next/formats/schemas/items.json +75 -0
- package/node_modules/@allyhub-next/formats/schemas/messages.schema.json +11 -0
- package/node_modules/@allyhub-next/formats/schemas/script.schema.json +162 -0
- package/node_modules/@allyhub-next/formats/schemas/sheet.schema.json +395 -0
- package/node_modules/@allyhub-next/formats/schemas/words.schema.json +63 -0
- package/node_modules/@allyhub-next/protocol/dist/app.d.ts +98 -0
- package/node_modules/@allyhub-next/protocol/dist/app.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/auth.d.ts +116 -0
- package/node_modules/@allyhub-next/protocol/dist/auth.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/cli.d.ts +59 -0
- package/node_modules/@allyhub-next/protocol/dist/cli.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/cloud.d.ts +272 -0
- package/node_modules/@allyhub-next/protocol/dist/cloud.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/editor.d.ts +405 -0
- package/node_modules/@allyhub-next/protocol/dist/editor.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/files.d.ts +101 -0
- package/node_modules/@allyhub-next/protocol/dist/files.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/index.d.ts +12 -0
- package/node_modules/@allyhub-next/protocol/dist/index.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/jsonrpc.d.ts +83 -0
- package/node_modules/@allyhub-next/protocol/dist/jsonrpc.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/registry.d.ts +53 -0
- package/node_modules/@allyhub-next/protocol/dist/registry.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/runtimes.d.ts +93 -0
- package/node_modules/@allyhub-next/protocol/dist/runtimes.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/teams.d.ts +67 -0
- package/node_modules/@allyhub-next/protocol/dist/teams.js +2 -0
- package/node_modules/@allyhub-next/protocol/dist/tools.d.ts +345 -0
- package/node_modules/@allyhub-next/protocol/dist/tools.js +2 -0
- package/node_modules/@allyhub-next/protocol/package.json +13 -0
- package/node_modules/@allyhub-next/runtimes/dist/bundled.d.ts +10 -0
- package/node_modules/@allyhub-next/runtimes/dist/bundled.js +2 -0
- package/node_modules/@allyhub-next/runtimes/dist/download.d.ts +15 -0
- package/node_modules/@allyhub-next/runtimes/dist/download.js +2 -0
- package/node_modules/@allyhub-next/runtimes/dist/errors.d.ts +16 -0
- package/node_modules/@allyhub-next/runtimes/dist/errors.js +2 -0
- package/node_modules/@allyhub-next/runtimes/dist/home.d.ts +2 -0
- package/node_modules/@allyhub-next/runtimes/dist/home.js +2 -0
- package/node_modules/@allyhub-next/runtimes/dist/index.d.ts +9 -0
- package/node_modules/@allyhub-next/runtimes/dist/index.js +2 -0
- package/node_modules/@allyhub-next/runtimes/dist/lock.d.ts +6 -0
- package/node_modules/@allyhub-next/runtimes/dist/lock.js +2 -0
- package/node_modules/@allyhub-next/runtimes/dist/manifest.d.ts +3 -0
- package/node_modules/@allyhub-next/runtimes/dist/manifest.js +2 -0
- package/node_modules/@allyhub-next/runtimes/dist/runtimes.d.ts +63 -0
- package/node_modules/@allyhub-next/runtimes/dist/runtimes.js +3 -0
- package/node_modules/@allyhub-next/runtimes/dist/unpack.d.ts +7 -0
- package/node_modules/@allyhub-next/runtimes/dist/unpack.js +2 -0
- package/node_modules/@allyhub-next/runtimes/manifest.json +395 -0
- package/node_modules/@allyhub-next/runtimes/package.json +14 -0
- package/node_modules/@allyhub-next/runtimes/schemas/runtimes.schema.json +153 -0
- package/node_modules/@allyhub-next/scenery/NOTICE +42 -0
- package/node_modules/@allyhub-next/scenery/dist/aim.d.ts +55 -0
- package/node_modules/@allyhub-next/scenery/dist/aim.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/bake.d.ts +203 -0
- package/node_modules/@allyhub-next/scenery/dist/bake.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/camera.d.ts +150 -0
- package/node_modules/@allyhub-next/scenery/dist/camera.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/curve.d.ts +40 -0
- package/node_modules/@allyhub-next/scenery/dist/curve.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/define.d.ts +164 -0
- package/node_modules/@allyhub-next/scenery/dist/define.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/fit.d.ts +64 -0
- package/node_modules/@allyhub-next/scenery/dist/fit.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/glass.d.ts +34 -0
- package/node_modules/@allyhub-next/scenery/dist/glass.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/handheld.d.ts +184 -0
- package/node_modules/@allyhub-next/scenery/dist/handheld.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/hull.d.ts +23 -0
- package/node_modules/@allyhub-next/scenery/dist/hull.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/index.d.ts +22 -0
- package/node_modules/@allyhub-next/scenery/dist/index.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/lens.d.ts +48 -0
- package/node_modules/@allyhub-next/scenery/dist/lens.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/moire.d.ts +136 -0
- package/node_modules/@allyhub-next/scenery/dist/moire.js +93 -0
- package/node_modules/@allyhub-next/scenery/dist/motion.d.ts +48 -0
- package/node_modules/@allyhub-next/scenery/dist/motion.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/move.d.ts +260 -0
- package/node_modules/@allyhub-next/scenery/dist/move.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/noise.d.ts +41 -0
- package/node_modules/@allyhub-next/scenery/dist/noise.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/phone.d.ts +34 -0
- package/node_modules/@allyhub-next/scenery/dist/phone.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/report.d.ts +677 -0
- package/node_modules/@allyhub-next/scenery/dist/report.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/screen-focus.d.ts +55 -0
- package/node_modules/@allyhub-next/scenery/dist/screen-focus.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/screen.d.ts +71 -0
- package/node_modules/@allyhub-next/scenery/dist/screen.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/solve.d.ts +82 -0
- package/node_modules/@allyhub-next/scenery/dist/solve.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/timing.d.ts +26 -0
- package/node_modules/@allyhub-next/scenery/dist/timing.js +2 -0
- package/node_modules/@allyhub-next/scenery/dist/vec.d.ts +19 -0
- package/node_modules/@allyhub-next/scenery/dist/vec.js +2 -0
- package/node_modules/@allyhub-next/scenery/package.json +13 -0
- package/node_modules/@allyhub-next/video-core/dist/anchors.d.ts +164 -0
- package/node_modules/@allyhub-next/video-core/dist/anchors.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/audio-types.d.ts +148 -0
- package/node_modules/@allyhub-next/video-core/dist/audio-types.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/backdrop.d.ts +87 -0
- package/node_modules/@allyhub-next/video-core/dist/backdrop.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/captions.d.ts +122 -0
- package/node_modules/@allyhub-next/video-core/dist/captions.js +11 -0
- package/node_modules/@allyhub-next/video-core/dist/console.d.ts +91 -0
- package/node_modules/@allyhub-next/video-core/dist/console.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/contrast.d.ts +98 -0
- package/node_modules/@allyhub-next/video-core/dist/contrast.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/cut-report.d.ts +77 -0
- package/node_modules/@allyhub-next/video-core/dist/cut-report.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/edit.d.ts +77 -0
- package/node_modules/@allyhub-next/video-core/dist/edit.js +13 -0
- package/node_modules/@allyhub-next/video-core/dist/edits.d.ts +163 -0
- package/node_modules/@allyhub-next/video-core/dist/edits.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/export.d.ts +96 -0
- package/node_modules/@allyhub-next/video-core/dist/export.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/fact.d.ts +965 -0
- package/node_modules/@allyhub-next/video-core/dist/fact.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/footage-motion.d.ts +168 -0
- package/node_modules/@allyhub-next/video-core/dist/footage-motion.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/formats.d.ts +240 -0
- package/node_modules/@allyhub-next/video-core/dist/formats.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/gen.d.ts +37 -0
- package/node_modules/@allyhub-next/video-core/dist/gen.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/index.d.ts +40 -0
- package/node_modules/@allyhub-next/video-core/dist/index.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/look.d.ts +66 -0
- package/node_modules/@allyhub-next/video-core/dist/look.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/marks.d.ts +34 -0
- package/node_modules/@allyhub-next/video-core/dist/marks.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/matrix.d.ts +289 -0
- package/node_modules/@allyhub-next/video-core/dist/matrix.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/measure.d.ts +465 -0
- package/node_modules/@allyhub-next/video-core/dist/measure.js +5 -0
- package/node_modules/@allyhub-next/video-core/dist/media.d.ts +226 -0
- package/node_modules/@allyhub-next/video-core/dist/media.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/messages.d.ts +88 -0
- package/node_modules/@allyhub-next/video-core/dist/messages.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/motion.d.ts +56 -0
- package/node_modules/@allyhub-next/video-core/dist/motion.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/music.d.ts +110 -0
- package/node_modules/@allyhub-next/video-core/dist/music.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/piece.d.ts +1146 -0
- package/node_modules/@allyhub-next/video-core/dist/piece.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/placement.d.ts +37 -0
- package/node_modules/@allyhub-next/video-core/dist/placement.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/problem.d.ts +262 -0
- package/node_modules/@allyhub-next/video-core/dist/problem.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/render-types.d.ts +49 -0
- package/node_modules/@allyhub-next/video-core/dist/render-types.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/schema.d.ts +352 -0
- package/node_modules/@allyhub-next/video-core/dist/schema.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/script-edit.d.ts +176 -0
- package/node_modules/@allyhub-next/video-core/dist/script-edit.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/script.d.ts +67 -0
- package/node_modules/@allyhub-next/video-core/dist/script.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/seams.d.ts +214 -0
- package/node_modules/@allyhub-next/video-core/dist/seams.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/slides.d.ts +37 -0
- package/node_modules/@allyhub-next/video-core/dist/slides.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/sound-under.d.ts +72 -0
- package/node_modules/@allyhub-next/video-core/dist/sound-under.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/speech.d.ts +83 -0
- package/node_modules/@allyhub-next/video-core/dist/speech.js +5 -0
- package/node_modules/@allyhub-next/video-core/dist/timeline.d.ts +616 -0
- package/node_modules/@allyhub-next/video-core/dist/timeline.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/timing.d.ts +88 -0
- package/node_modules/@allyhub-next/video-core/dist/timing.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/transcript.d.ts +288 -0
- package/node_modules/@allyhub-next/video-core/dist/transcript.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/transition.d.ts +289 -0
- package/node_modules/@allyhub-next/video-core/dist/transition.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/voice.d.ts +175 -0
- package/node_modules/@allyhub-next/video-core/dist/voice.js +2 -0
- package/node_modules/@allyhub-next/video-core/dist/words.d.ts +128 -0
- package/node_modules/@allyhub-next/video-core/dist/words.js +2 -0
- package/node_modules/@allyhub-next/video-core/package.json +14 -0
- package/package.json +52 -41
- package/README.md +0 -17
- package/dist/anim.d.ts.map +0 -1
- package/dist/anim.js.map +0 -1
- package/dist/define.d.ts.map +0 -1
- package/dist/define.js.map +0 -1
- package/dist/dom.d.ts.map +0 -1
- package/dist/dom.js.map +0 -1
- package/dist/fit.d.ts.map +0 -1
- package/dist/fit.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/media.d.ts.map +0 -1
- package/dist/media.js.map +0 -1
- package/dist/messages.d.ts.map +0 -1
- package/dist/messages.js.map +0 -1
- package/dist/noise.d.ts.map +0 -1
- package/dist/noise.js.map +0 -1
- package/dist/parts.d.ts.map +0 -1
- package/dist/parts.js.map +0 -1
- package/dist/paths.d.ts.map +0 -1
- package/dist/paths.js.map +0 -1
- package/dist/piece.d.ts.map +0 -1
- package/dist/piece.js.map +0 -1
- package/dist/props.d.ts.map +0 -1
- package/dist/props.js.map +0 -1
- package/dist/text.d.ts.map +0 -1
- package/dist/text.js.map +0 -1
- /package/{LICENSE → LICENSE.md} +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { ResolvedVoice } from "./recording/chain.js";
|
|
2
|
+
import type { FixedShape, ResolvedShape } from "./shape.js";
|
|
3
|
+
/** The rate the export mixes at, samples a second. The player mixes at its AudioContext's. */
|
|
4
|
+
export declare const SAMPLE_RATE = 48000;
|
|
5
|
+
/** A sound's two channels (a mono one given twice). */
|
|
6
|
+
export type Stereo = readonly [Float32Array, Float32Array];
|
|
7
|
+
/** A point of a gain envelope: at time t (s), gain in dB. Linear between points. */
|
|
8
|
+
export interface GainPoint {
|
|
9
|
+
t: number;
|
|
10
|
+
db: number;
|
|
11
|
+
}
|
|
12
|
+
/** A stretch of a file placed on the film's clock. */
|
|
13
|
+
export interface Segment {
|
|
14
|
+
/** Film time it starts. */
|
|
15
|
+
at: number;
|
|
16
|
+
/** File time it starts from. */
|
|
17
|
+
from: number;
|
|
18
|
+
/** Film seconds it lasts. */
|
|
19
|
+
dur: number;
|
|
20
|
+
/** File seconds per film second (footage's speed, a take's); default 1. */
|
|
21
|
+
speed?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A stretch of a voiced part's speech: of its take or its said line, at
|
|
25
|
+
* its place (a cut take is several), at its speed (pitch kept, unlike
|
|
26
|
+
* footage's), with its noise reduction; or the room tone that fills a
|
|
27
|
+
* lead or a tail, at its matched gain. `fadeIn` and `fadeOut` are seconds
|
|
28
|
+
* of equal-power fade at its start and end, where it cross-fades with the
|
|
29
|
+
* clip it overlaps (room tone into the take); absent: the mix's own 10 ms
|
|
30
|
+
* fade.
|
|
31
|
+
*/
|
|
32
|
+
export interface SpeechClip extends Segment {
|
|
33
|
+
/** The file, as the host names it (a repository path). */
|
|
34
|
+
file: string;
|
|
35
|
+
/** The part whose speech it is. */
|
|
36
|
+
part?: string;
|
|
37
|
+
gainDb: number;
|
|
38
|
+
/** Noise reduction, dB (ffmpeg's afftdn where the host decodes it). */
|
|
39
|
+
denoise?: number;
|
|
40
|
+
fadeIn?: number;
|
|
41
|
+
fadeOut?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Footage's own sound: a stretch of a file at its place, at its level
|
|
45
|
+
* where nobody speaks; `envelope` (relative dB) takes it to its
|
|
46
|
+
* under-speech level while speech plays.
|
|
47
|
+
*/
|
|
48
|
+
export interface FootageClip extends Segment {
|
|
49
|
+
file: string;
|
|
50
|
+
gainDb: number;
|
|
51
|
+
envelope?: GainPoint[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A piece of the music file the mix plays: film second `at`, file second
|
|
55
|
+
* `from`, `dur` seconds, with its equal-power fades at a seam (seconds).
|
|
56
|
+
* The runtime places them (the music's clock: its stretches, loops and
|
|
57
|
+
* seams), from the file's length.
|
|
58
|
+
*/
|
|
59
|
+
export interface MusicSegment {
|
|
60
|
+
at: number;
|
|
61
|
+
from: number;
|
|
62
|
+
dur: number;
|
|
63
|
+
fadeIn: number;
|
|
64
|
+
fadeOut: number;
|
|
65
|
+
}
|
|
66
|
+
/** The music as the film plays it. */
|
|
67
|
+
export interface MusicPlay {
|
|
68
|
+
file: string;
|
|
69
|
+
/** What it plays of the file, where: each seam's cross-fade in its fades. */
|
|
70
|
+
segments: MusicSegment[];
|
|
71
|
+
/** Its gain where nobody speaks (levelled to the mix's musicAlone). */
|
|
72
|
+
gainDb: number;
|
|
73
|
+
/** The mix's musicAlone: the level a shaped stem is levelled to, by its loudness as shaped. */
|
|
74
|
+
alone: number;
|
|
75
|
+
/** Its fade in at the film's start and out at its end, seconds (linear). */
|
|
76
|
+
fadeIn: number;
|
|
77
|
+
fadeOut: number;
|
|
78
|
+
/** Film seconds its fade out ends at (it ends on a bar); absent: the film's end. */
|
|
79
|
+
until?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Its gain over time relative to gainDb: down to the mix's music level
|
|
82
|
+
* while speech plays, further by the duck under words, and the music's
|
|
83
|
+
* own gain points.
|
|
84
|
+
*/
|
|
85
|
+
duck: GainPoint[];
|
|
86
|
+
/** How it is shaped, its bands' keys at film seconds (its filter runs when it is decoded). */
|
|
87
|
+
shape?: ResolvedShape;
|
|
88
|
+
}
|
|
89
|
+
/** A sound effect: an audio file, or a built-in synthesized one (sfx.ts). */
|
|
90
|
+
export interface SfxPlay {
|
|
91
|
+
/** Its name; a built-in sound's (`whoosh`, `tick`, `pop`) when it has no file. */
|
|
92
|
+
sound: string;
|
|
93
|
+
/** The audio file; absent: synthesized. */
|
|
94
|
+
file?: string;
|
|
95
|
+
/** When it starts (a built-in one is placed so its transient is at the cue). */
|
|
96
|
+
at: number;
|
|
97
|
+
gainDb: number;
|
|
98
|
+
/** Seeds a built-in sound. */
|
|
99
|
+
seed: number;
|
|
100
|
+
/** How it is shaped (its filter runs when it is decoded). */
|
|
101
|
+
shape?: FixedShape;
|
|
102
|
+
/**
|
|
103
|
+
* A shaped file's level as shaped: the mix's sfx level, and the cue's
|
|
104
|
+
* own gain over it; absent for a built-in sound, which keeps its level.
|
|
105
|
+
*/
|
|
106
|
+
level?: {
|
|
107
|
+
target: number;
|
|
108
|
+
gainDb: number;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** Where a part is on the film: where its recording's room tone runs. */
|
|
112
|
+
export interface PartSpan {
|
|
113
|
+
part: string;
|
|
114
|
+
start: number;
|
|
115
|
+
end: number;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* How the speech was recorded: the video's setting and each part's own,
|
|
119
|
+
* resolved over their presets (recording/), false where it plays as it
|
|
120
|
+
* is; every part of the film, in order; and the seed of the rooms and
|
|
121
|
+
* their tone (piece, output and combo key, as the runtime writes it).
|
|
122
|
+
*/
|
|
123
|
+
export interface VoicePlan {
|
|
124
|
+
video: ResolvedVoice | false;
|
|
125
|
+
parts?: Record<string, ResolvedVoice | false>;
|
|
126
|
+
spans: PartSpan[];
|
|
127
|
+
seed: string;
|
|
128
|
+
}
|
|
129
|
+
export interface MixPlan {
|
|
130
|
+
duration: number;
|
|
131
|
+
speech: SpeechClip[];
|
|
132
|
+
footage: FootageClip[];
|
|
133
|
+
music?: MusicPlay;
|
|
134
|
+
sfx: SfxPlay[];
|
|
135
|
+
/**
|
|
136
|
+
* The speech's gain after it is recorded, relative dB over the film
|
|
137
|
+
* (each part's speechGainDb, ramped where it changes); absent: none.
|
|
138
|
+
*/
|
|
139
|
+
speechGain?: GainPoint[];
|
|
140
|
+
/** How the speech is recorded; absent: every clip plays as it is. */
|
|
141
|
+
voice?: VoicePlan;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=plan.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ResolvedVoice } from "./recording/chain.js";
|
|
2
|
+
import type { Stereo } from "./plan.js";
|
|
3
|
+
import type { VoiceGroup } from "./voice.js";
|
|
4
|
+
/** The speech of a plan summed per setting, before it is recorded. */
|
|
5
|
+
export interface SpeechTracks {
|
|
6
|
+
/** Samples a second. */
|
|
7
|
+
rate: number;
|
|
8
|
+
/** Speech recorded alike, with its clips summed (not yet recorded). */
|
|
9
|
+
groups: readonly (VoiceGroup & {
|
|
10
|
+
dry: Stereo;
|
|
11
|
+
})[];
|
|
12
|
+
/** Speech whose setting is false, summed: played as it is. */
|
|
13
|
+
plain: Stereo;
|
|
14
|
+
}
|
|
15
|
+
/** All the speech summed before any of it is recorded: each setting's track and what plays as it is. */
|
|
16
|
+
export declare function drySpeech(tracks: SpeechTracks): Stereo;
|
|
17
|
+
/**
|
|
18
|
+
* All the speech as the mix records it: each setting's track recorded
|
|
19
|
+
* through its setting (or, for the group at `swap.index`, through
|
|
20
|
+
* `swap.voice`), with what plays as it is.
|
|
21
|
+
*/
|
|
22
|
+
export declare function recordedSpeech(tracks: SpeechTracks, swap?: {
|
|
23
|
+
index: number;
|
|
24
|
+
voice: ResolvedVoice;
|
|
25
|
+
}): Stereo;
|
|
26
|
+
//# sourceMappingURL=recorded.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
import{recordVoice as d}from"./recording/chain.js";function f(o,e){for(let r=0;r<2;r++){const n=o[r],c=e[r];if(!(!n||!c))for(let t=0;t<n.length;t++)n[t]=(n[t]??0)+(c[t]??0)}}const i=o=>[Float32Array.from(o[0]),Float32Array.from(o[1])];export function drySpeech(o){const e=i(o.plain);for(const r of o.groups)f(e,r.dry);return e}export function recordedSpeech(o,e){const r=i(o.plain);return o.groups.forEach((n,c)=>{const t=i(n.dry),u=e?.index===c?e.voice:n.voice;d(t,u,o.rate,n.seed,n.spans),f(r,t)}),r}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface BandwidthOptions {
|
|
2
|
+
/** The level is read at this frequency, Hz. */
|
|
3
|
+
ref: number;
|
|
4
|
+
/** How far under the level at `ref` the sound may fall and still reach, dB, each. */
|
|
5
|
+
drops: number[];
|
|
6
|
+
/** Levels are averaged over this share of an octave around each frequency. */
|
|
7
|
+
smooth: number;
|
|
8
|
+
/** Steps are looked for from this frequency, Hz… */
|
|
9
|
+
stepsFrom: number;
|
|
10
|
+
/** …as falls over spans of this share of an octave… */
|
|
11
|
+
stepSpan: number;
|
|
12
|
+
/** …at least this deep, dB, the deepest this many. */
|
|
13
|
+
stepMin: number;
|
|
14
|
+
steps: number;
|
|
15
|
+
/** A frame is in the average when its level is over this, dBFS (the frames picked, or all). */
|
|
16
|
+
floor: number;
|
|
17
|
+
}
|
|
18
|
+
export declare const BANDWIDTH_DEFAULTS: BandwidthOptions;
|
|
19
|
+
export interface Bandwidth {
|
|
20
|
+
/** The frames averaged. */
|
|
21
|
+
frames: number;
|
|
22
|
+
/** The highest frequency the sound is within each drop of its level at `ref`, Hz; null where it never is. */
|
|
23
|
+
reach: {
|
|
24
|
+
drop: number;
|
|
25
|
+
hz: number | null;
|
|
26
|
+
}[];
|
|
27
|
+
/** The frequencies under which 95 % and 99 % of the power above `ref` lies, Hz. */
|
|
28
|
+
rolloff95: number | null;
|
|
29
|
+
rolloff99: number | null;
|
|
30
|
+
/**
|
|
31
|
+
* The deepest falls over `stepSpan` of an octave above `stepsFrom`
|
|
32
|
+
* (each the most of its neighbourhood), by frequency: their centre, Hz,
|
|
33
|
+
* and their depth, dB.
|
|
34
|
+
*/
|
|
35
|
+
steps: {
|
|
36
|
+
hz: number;
|
|
37
|
+
db: number;
|
|
38
|
+
}[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A sound's reach (channels at `rate`), over the frames `pick` takes (by
|
|
42
|
+
* the sample at a frame's middle; all by default) that are over `floor`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function bandwidthOf(channels: readonly Float32Array[], rate: number, opts?: Partial<BandwidthOptions> & {
|
|
45
|
+
pick?: (sample: number) => boolean;
|
|
46
|
+
}): Bandwidth;
|
|
47
|
+
//# sourceMappingURL=bandwidth.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
import{fft as I}from"./fft.js";export const BANDWIDTH_DEFAULTS={ref:1e3,drops:[30,50,70],smooth:1/12,stepsFrom:3e3,stepSpan:1/6,stepMin:3,steps:4,floor:-60};function T(c){const h=c[0]?.length??0,f=new Float32Array(h);for(const e of c)for(let s=0;s<h;s++)f[s]=(f[s]??0)+(e[s]??0)/c.length;return f}export function bandwidthOf(c,h,f={}){const e={...BANDWIDTH_DEFAULTS,...f},s=T(c),n=8192,M=new Float64Array(n/2+1),d=new Float64Array(n),b=new Float64Array(n),y=Float64Array.from({length:n},(t,o)=>.5-.5*Math.cos(2*Math.PI*o/(n-1)));let u=0;for(let t=0;t+n<=s.length;t+=n/4){if(f.pick&&!f.pick(t+n/2))continue;let o=0;for(let r=0;r<n;r++)o+=(s[t+r]??0)**2;if(!(10*Math.log10(o/n+1e-20)<=e.floor)){for(let r=0;r<n;r++)d[r]=(s[t+r]??0)*(y[r]??0),b[r]=0;I(d,b);for(let r=0;r<=n/2;r++)M[r]=(M[r]??0)+(d[r]??0)**2+(b[r]??0)**2;u++}}const z={frames:u,reach:e.drops.map(t=>({drop:t,hz:null})),rolloff95:null,rolloff99:null,steps:[]};if(u===0)return z;const a=h/n,l=new Float64Array(n/2+2);for(let t=0;t<=n/2;t++)l[t+1]=(l[t]??0)+(M[t]??0);const p=t=>{const o=Math.max(0,Math.floor(t*2**(-e.smooth/2)/a)),r=Math.min(n/2,Math.ceil(t*2**(e.smooth/2)/a)),i=((l[r+1]??0)-(l[o]??0))/Math.max(1,r-o+1);return 10*Math.log10(i/u+1e-30)},k=p(e.ref),S=h/2,D=e.drops.map(t=>{for(let o=n/2;o*a>e.ref;o--)if(p(o*a)>=k-t)return{drop:t,hz:Math.round(o*a)};return{drop:t,hz:null}}),w=Math.ceil(e.ref/a),F=(l[n/2+1]??0)-(l[w]??0),g=t=>{if(F<=0)return null;for(let o=w;o<=n/2;o++)if((l[o+1]??0)-(l[w]??0)>=t*F)return Math.round(o*a);return null},A=2**(e.stepSpan/2),m=[];for(let t=e.stepsFrom;t*A<S;t*=2**(1/96))m.push({hz:t,db:p(t/A)-p(t*A)});const x=Math.max(1,Math.round(96*e.stepSpan/2)),v=m.filter((t,o)=>{if(t.db<e.stepMin)return!1;for(let r=Math.max(0,o-x);r<=Math.min(m.length-1,o+x);r++){const i=m[r];if(i&&(i.db>t.db||i.db===t.db&&r<o))return!1}return!0}).sort((t,o)=>o.db-t.db).slice(0,e.steps).sort((t,o)=>t.hz-o.hz).map(t=>({hz:Math.round(t.hz),db:Math.round(t.db*10)/10}));return{frames:u,reach:D,rolloff95:g(.95),rolloff99:g(.99),steps:v}}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { type FilterSpec } from "./filters.js";
|
|
2
|
+
import { type Pattern } from "./mic.js";
|
|
3
|
+
import { type NoiseShape } from "./noise.js";
|
|
4
|
+
import { type VoiceSetting, type VoiceSetup } from "./setup.js";
|
|
5
|
+
import type { CompressorOptions, DeesserOptions } from "./dynamics.js";
|
|
6
|
+
import type { Vec3 } from "./vec.js";
|
|
7
|
+
/** A room with every value. */
|
|
8
|
+
export interface ResolvedRoom {
|
|
9
|
+
size: Vec3;
|
|
10
|
+
walls: number[];
|
|
11
|
+
floor: number[];
|
|
12
|
+
ceiling: number[];
|
|
13
|
+
rt60: number;
|
|
14
|
+
talker: Vec3;
|
|
15
|
+
open?: true;
|
|
16
|
+
order: number;
|
|
17
|
+
}
|
|
18
|
+
/** One microphone with every value. */
|
|
19
|
+
export interface ResolvedPickup {
|
|
20
|
+
pattern: Pattern;
|
|
21
|
+
distance: number;
|
|
22
|
+
angle: number;
|
|
23
|
+
below: number;
|
|
24
|
+
response: (readonly [number, number])[];
|
|
25
|
+
band: readonly [number, number];
|
|
26
|
+
stereo: number | false;
|
|
27
|
+
room: ResolvedRoom | false;
|
|
28
|
+
noise: (NoiseShape & {
|
|
29
|
+
below: number;
|
|
30
|
+
}) | false;
|
|
31
|
+
agc: {
|
|
32
|
+
target: number;
|
|
33
|
+
most: number;
|
|
34
|
+
attack: number;
|
|
35
|
+
release: number;
|
|
36
|
+
window: number;
|
|
37
|
+
gate?: number;
|
|
38
|
+
} | false;
|
|
39
|
+
/** Its level in the sum, dB. */
|
|
40
|
+
gain: number;
|
|
41
|
+
/**
|
|
42
|
+
* The distance its room tone's `below` holds at (the setup's own): moved
|
|
43
|
+
* further, the voice reaches it weaker against the same room tone.
|
|
44
|
+
*/
|
|
45
|
+
toneAt: number;
|
|
46
|
+
}
|
|
47
|
+
/** A finishing chain with every value. */
|
|
48
|
+
export interface ResolvedPost {
|
|
49
|
+
highpass: number | false;
|
|
50
|
+
eq: FilterSpec[];
|
|
51
|
+
deess: DeesserOptions | false;
|
|
52
|
+
compress: CompressorOptions | false;
|
|
53
|
+
}
|
|
54
|
+
/** A voice setting with every value: what the mix and the player play it through. */
|
|
55
|
+
export interface ResolvedVoice {
|
|
56
|
+
setup: VoiceSetup;
|
|
57
|
+
source: {
|
|
58
|
+
pattern: Pattern;
|
|
59
|
+
distance: number;
|
|
60
|
+
};
|
|
61
|
+
pickups: ResolvedPickup[];
|
|
62
|
+
post: ResolvedPost | false;
|
|
63
|
+
}
|
|
64
|
+
/** A voice setting with every value from its presets; undefined: the default (studio). */
|
|
65
|
+
export declare function resolveVoice(v: VoiceSetting | undefined): ResolvedVoice | false;
|
|
66
|
+
/** Why a voice setting cannot be played, with its field; undefined when it can. */
|
|
67
|
+
export declare function voiceProblem(v: unknown, at?: string): string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* A pickup's impulse response per channel (one, or two for a stereo
|
|
70
|
+
* pair), its direct sound `lead` samples in; null where it changes
|
|
71
|
+
* nothing (a studio's flat microphone at the dry voice's own distance,
|
|
72
|
+
* no room).
|
|
73
|
+
*/
|
|
74
|
+
export declare function pickupImpulses(p: ResolvedPickup, source: ResolvedVoice["source"], rate: number, seed: number): {
|
|
75
|
+
channels: Float64Array[];
|
|
76
|
+
lead: number;
|
|
77
|
+
} | null;
|
|
78
|
+
/** Where the voice's parts play, seconds: the room tone is under them alone. */
|
|
79
|
+
export interface VoiceSpan {
|
|
80
|
+
start: number;
|
|
81
|
+
end: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Plays a voice (stereo, at the mix's speech level) through its setting,
|
|
85
|
+
* in place: what the mix and the player both call. `seed` makes the
|
|
86
|
+
* room's tail and the room tone the same every time.
|
|
87
|
+
*/
|
|
88
|
+
export declare function recordVoice(channels: readonly [Float32Array, Float32Array], voice: ResolvedVoice, rate: number, seed: number, spans: readonly VoiceSpan[]): void;
|
|
89
|
+
//# sourceMappingURL=chain.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
import{agc as oe,compress as re,deess as ie}from"./dynamics.js";import{convolve as v,minimumPhase as H}from"./fft.js";import{biquad as x,biquadGain as J,fromDb as j,runBiquads as K}from"./filters.js";import{integratedLoudness as R}from"./loudness.js";import{curveDb as fe,PATTERNS as ae,proximity as Q,talkerDb as N}from"./mic.js";import{roomTone as W}from"./noise.js";import{POST_PRESETS as U,ROOM_PRESETS as ce,SETUP_PRESETS as X,SOURCE_DEFAULTS as Y}from"./presets.js";import{MATERIALS as T,roomResponse as le,withReverberation as ue}from"./room.js";import{POSTS as q,ROOMS as I,VOICE_SETUPS as L}from"./setup.js";const B=(e,s)=>e===void 0?[...T[s]??[]]:typeof e=="string"?[...T[e]??[]]:[...e];function de(e,s){if(e===!1||e===void 0&&s===!1)return!1;const t=s===!1?{preset:"bedroom"}:typeof s=="string"?{preset:s}:s,r=typeof e=="string"?{preset:e}:e===void 0?t:e.preset===void 0?{...t,...e}:e,i=ce[r.preset??"bedroom"];return{size:r.size??i.size,walls:B(r.walls,i.walls),floor:B(r.floor,i.floor),ceiling:B(r.ceiling,i.ceiling),rt60:r.rt60??i.rt60,talker:r.talker??i.talker,...i.open?{open:!0}:{},order:i.order}}function Z(e,s,t){const r=X[s],i=e.noise===!1?!1:e.noise===void 0?r.noise:{...r.noise||{tilt:-4,rumble:8,top:16e3,below:45},...e.noise},c=e.agc===!1?!1:e.agc===void 0?r.agc:{...r.agc||{target:0,most:10,attack:.3,release:1.5,window:1},...e.agc};return{pattern:e.pattern??r.pattern,distance:e.distance??r.distance,angle:e.angle??r.angle,below:e.below??r.below,response:(e.response??r.response).map(([m,u])=>[m,u]),band:e.band??r.band,stereo:e.stereo??r.stereo,room:de(e.room,r.room),noise:i===!1?!1:{tilt:i.tilt,rumble:i.rumble,top:i.top,below:i.below,...i.hum?{hum:i.hum}:{}},agc:c===!1?!1:{target:c.target??0,most:c.most??10,attack:c.attack??.3,release:c.release??1.5,window:c.window??1,...c.gate===void 0?{}:{gate:c.gate}},gain:t,toneAt:r.distance}}function pe(e,s){if(e===!1)return!1;const t=typeof e=="string"?e:e?.preset??(s===!1?void 0:s),r=t===void 0?void 0:U[t],i=typeof e=="object"?e:{};if(!r&&typeof e!="object")return!1;const c=i.deess===!1?!1:i.deess===void 0?r?.deess??!1:{...r?.deess||U.finish.deess||{hz:5500,threshold:-12,ratio:3,attack:.002,release:.06},...i.deess},m=i.compress===!1?!1:i.compress===void 0?r?.compress??!1:{...r?.compress||U.finish.compress||{threshold:2,ratio:2,knee:6,attack:.01,release:.15,window:.01},...i.compress};return{highpass:i.highpass??r?.highpass??!1,eq:[...i.eq??r?.eq??[]],deess:c,compress:m}}export function resolveVoice(e){if(e===!1)return!1;const s=typeof e=="string"?{setup:e}:e??{},t=s.setup??"studio",r=X[t],i=Z(s,t,0);return{setup:t,source:{pattern:s.source?.pattern??Y.pattern,distance:s.source?.distance??Y.distance},pickups:[i,...(s.also??[]).map(c=>({...Z(c,c.setup??t,c.gain??-12),...c.room===void 0?{room:i.room}:{}}))],post:pe(s.post,r.post)}}export function voiceProblem(e,s="mic"){if(e===void 0||e===!1)return;if(typeof e=="string")return L.includes(e)?void 0:`${s} is "${e}": a setup is one of ${L.join(", ")}`;if(typeof e!="object"||e===null)return`${s} is a setup's name, its options, or false`;const t=e,r=(n,a,f)=>{const o=t[n];if(o!==void 0)return typeof o=="number"&&Number.isFinite(o)&&o>=a&&o<=f?void 0:`${s}.${n} is from ${String(a)} to ${String(f)}`},i=new Set(["setup","source","pattern","distance","angle","below","response","band","stereo","room","noise","agc","post","also","gain"]);for(const n of Object.keys(t))if(!i.has(n))return`${s} has no field ${n}`;if(t.setup!==void 0&&!L.includes(t.setup))return`${s}.setup is one of ${L.join(", ")}`;const c=Object.keys(ae);if(t.pattern!==void 0&&!(typeof t.pattern=="string"&&c.includes(t.pattern)))return`${s}.pattern is one of ${c.join(", ")}`;const m=r("distance",.01,20)??r("angle",-180,180)??r("below",-90,90)??r("gain",-60,20)??(t.stereo!==void 0&&t.stereo!==!1&&!(typeof t.stereo=="number"&&t.stereo>=0&&t.stereo<=1)?`${s}.stereo is a spacing from 0 to 1 m, or false`:void 0);if(m)return m;const u=t.response;if(u!==void 0&&(!Array.isArray(u)||u.some(n=>!Array.isArray(n)||n.length!==2||typeof n[0]!="number"||typeof n[1]!="number"||n[0]<10||n[0]>24e3||n[1]<-40||n[1]>24)))return`${s}.response is [Hz, dB] points, 10 to 24000 Hz, -40 to 24 dB`;const d=t.band;if(d!==void 0&&(!Array.isArray(d)||d.length!==2||typeof d[0]!="number"||typeof d[1]!="number"||!(d[0]>=10&&d[0]<d[1]&&d[1]<=24e3)))return`${s}.band is [low, high] Hz, 10 ≤ low < high ≤ 24000`;const y=t.room;if(y!==void 0&&y!==!1)if(typeof y=="string"){if(!I.includes(y))return`${s}.room is one of ${I.join(", ")}, its options, or false`}else if(typeof y=="object"&&y!==null){const n=y;for(const f of Object.keys(n))if(!["preset","size","walls","floor","ceiling","rt60","talker"].includes(f))return`${s}.room has no field ${f}`;if(n.preset!==void 0&&!I.includes(n.preset))return`${s}.room.preset is one of ${I.join(", ")}`;const a=f=>Array.isArray(f)&&f.length===3&&f.every(o=>typeof o=="number"&&Number.isFinite(o)&&o>0);if(n.size!==void 0&&!(a(n.size)&&n.size.every(f=>f>=.5&&f<=100)))return`${s}.room.size is [width, height, depth] m, each 0.5 to 100`;if(n.talker!==void 0&&!a(n.talker))return`${s}.room.talker is [x, y, z] m inside the room`;if(n.rt60!==void 0&&!(typeof n.rt60=="number"&&n.rt60>=.03&&n.rt60<=5))return`${s}.room.rt60 is from 0.03 to 5 s`;for(const f of["walls","floor","ceiling"]){const o=n[f];if(o!==void 0){if(typeof o=="string"){if(!(o in T))return`${s}.room.${f} is one of ${Object.keys(T).join(", ")}, or absorption by octave from 125 Hz`}else if(!Array.isArray(o)||o.length<1||o.length>8||o.some(l=>typeof l!="number"||l<0||l>1))return`${s}.room.${f} is a material's name or 1 to 8 absorption coefficients from 0 to 1`}}}else return`${s}.room is a room's name, its options, or false`;const h=t.noise;if(h!==void 0&&h!==!1){if(typeof h!="object"||h===null)return`${s}.noise is its options or false`;const n=h,a=(l,S,w)=>n[l]===void 0||typeof n[l]=="number"&&n[l]>=S&&n[l]<=w?void 0:`${s}.noise.${l} is from ${String(S)} to ${String(w)}`;for(const l of Object.keys(n))if(!["below","tilt","rumble","hum","top"].includes(l))return`${s}.noise has no field ${l}`;const f=a("below",0,90)??a("tilt",-12,6)??a("rumble",0,30)??a("top",1e3,24e3);if(f)return f;const o=n.hum;if(o!==void 0&&!(typeof o=="object"&&o!==null&&[50,60].includes(o.hz)&&typeof o.db=="number"&&o.db<=0&&o.db>=-60))return`${s}.noise.hum is { hz: 50 or 60, db: -60 to 0 }`}const b=t.agc;if(b!==void 0&&b!==!1){if(typeof b!="object"||b===null)return`${s}.agc is its options or false`;const n=b;for(const a of Object.keys(n))if(!["target","most","attack","release","window","gate"].includes(a))return`${s}.agc has no field ${a}`;for(const[a,f,o]of[["target",-40,20],["most",0,40],["attack",5e-4,5],["release",.001,20],["window",.01,20],["gate",-120,0]])if(n[a]!==void 0&&!(typeof n[a]=="number"&&n[a]>=f&&n[a]<=o))return`${s}.agc.${a} is from ${String(f)} to ${String(o)}`}const g=t.post;if(g!==void 0&&g!==!1)if(typeof g=="string"){if(!q.includes(g))return`${s}.post is one of ${q.join(", ")}, its options, or false`}else if(typeof g=="object"&&g!==null){const n=g;for(const f of Object.keys(n))if(!["preset","highpass","eq","deess","compress"].includes(f))return`${s}.post has no field ${f}`;if(n.preset!==void 0&&!q.includes(n.preset))return`${s}.post.preset is one of ${q.join(", ")}`;if(n.highpass!==void 0&&n.highpass!==!1&&!(typeof n.highpass=="number"&&n.highpass>=10&&n.highpass<=1e3))return`${s}.post.highpass is from 10 to 1000 Hz, or false`;const a=n.eq;if(a!==void 0&&(!Array.isArray(a)||a.some(f=>typeof f!="object"||f===null||!["highpass","lowpass","peak","lowshelf","highshelf","bandpass"].includes(f.type)||typeof f.hz!="number")))return`${s}.post.eq is a list of bands: { type: peak, lowshelf, highshelf, highpass, lowpass or bandpass, hz, db?, q? }`;for(const[f,o]of[["deess",["hz","threshold","ratio","attack","release"]],["compress",["threshold","ratio","knee","attack","release","window"]]]){const l=n[f];if(!(l===void 0||l===!1)){if(typeof l!="object"||l===null)return`${s}.post.${f} is its options or false`;for(const S of Object.keys(l))if(!o.includes(S)||typeof l[S]!="number")return`${s}.post.${f}.${S} is not one of its numbers (${o.join(", ")})`}}}else return`${s}.post is a finishing chain's name, its options, or false`;const M=t.source;if(M!==void 0){const n=M;if(typeof M!="object"||M===null)return`${s}.source is { pattern?, distance? }`;if(n.pattern!==void 0&&!(typeof n.pattern=="string"&&c.includes(n.pattern)))return`${s}.source.pattern is one of ${c.join(", ")}`;if(n.distance!==void 0&&!(typeof n.distance=="number"&&n.distance>=.01&&n.distance<=20))return`${s}.source.distance is from 0.01 to 20 m`}const $=t.also;if($!==void 0){if(!Array.isArray($)||$.length>4)return`${s}.also is a list of at most 4 more microphones`;for(let n=0;n<$.length;n++){const a=$[n];if(typeof a=="object"&&a!==null&&("also"in a||"post"in a))return`${s}.also[${String(n)}] has no also or post: the finishing is the first microphone's, on the sum`;const f=voiceProblem(a,`${s}.also[${String(n)}]`);if(f)return f}}}const V=new Map;function me(e,s,t,r){const i=e.angle*Math.PI/180,c=e.below*Math.PI/180,m=[Math.sin(i)*Math.cos(c),-Math.sin(c),Math.cos(i)*Math.cos(c)],u=(y,h)=>Math.min(Math.max(y,.05),h-.05),d=[u(s[0]+m[0]*e.distance+r,t[0]),u(s[1]+m[1]*e.distance,t[1]),u(s[2]+m[2]*e.distance,t[2])];return{mic:d,axis:[s[0]-d[0],s[1]-d[1],s[2]-d[2]]}}function he(e,s,t){let r=1;return e[0]>15&&(r*=J(x({type:"highpass",hz:e[0]},t),s,t)),e[1]<t*.45&&(r*=J(x({type:"lowpass",hz:e[1]},t),s,t)),r}const ee=new Map;function ne(e,s){const t=JSON.stringify([e.response,e.band,s]);let r=ee.get(t);return r||(r=H(i=>j(fe(e.response,i))*he(e.band,i,s),s,2048),ee.set(t,r)),r}export function pickupImpulses(e,s,t,r){const i=JSON.stringify([e.pattern,e.distance,e.angle,e.below,e.response,e.band,e.stereo,e.room,s,t,r]),c=V.get(i);if(c!==void 0)return c;const m=($,n)=>Q(e.pattern,n,$)/Q(s.pattern,s.distance,$),u=Math.cos(e.angle*Math.PI/180)*Math.cos(e.below*Math.PI/180);if(e.room===!1&&e.response.every(([,$])=>Math.abs($)<.01)&&e.band[0]<=20&&e.band[1]>=2e4&&Math.abs(m(100,e.distance)-1)<.001&&Math.abs(N(8e3,u))<.01)return V.set(i,null),null;const y=ne(e,t),h=[];let b=0;(e.stereo===!1?[0]:[-e.stereo/2,e.stereo/2]).forEach(($,n)=>{let a;if(e.room===!1)a=H(l=>m(l,e.distance)*j(N(l,u)),t,2048);else{const o=e.room,l=me(e,o.talker,o.size,$);let S={size:o.size,surfaces:[o.walls,o.walls,o.floor,o.ceiling,o.walls,o.walls],...o.open?{open:[!0,!0,!1,!0,!0,!0]}:{},talker:o.talker,facing:[0,0,1],mic:l.mic,axis:l.axis,pattern:e.pattern,source:s,order:o.order};o.open||(S=ue(S,o.rt60,t));const w=le(S,t,r+n*7919),P=w.direct.distance,p=H(k=>m(k,P)*j(N(k,w.direct.cos)),t,2048);a=Float64Array.from(w.reflections);for(let k=0;k<p.length&&w.lead+k<a.length;k++)a[w.lead+k]=(a[w.lead+k]??0)+w.direct.gain*(p[k]??0);b=w.lead}const f=v(Float32Array.from(a),y);h.push(Float64Array.from(f))});const M={channels:h,lead:b};return V.set(i,M),M}function ge(e,s,t,r){if(Math.abs(e.distance-e.toneAt)<1e-6)return 0;const i=u=>{const d=pickupImpulses(u,s,t,r)?.channels[0];if(!d)return;let y=0;for(const h of d)y+=h*h;return y},c=i(e),m=i({...e,distance:e.toneAt});return e.room===!1||c===void 0||m===void 0?20*Math.log10(e.distance/e.toneAt):10*Math.log10(m/c)}export function recordVoice(e,s,t,r,i){const[c,m]=e,u=c.length,d=R([c,m],t);if(d===void 0)return;const y=new Float32Array(u);for(let n=0;n<u;n++)y[n]=((c[n]??0)+(m[n]??0))/2;const h=new Float32Array(u),b=new Float32Array(u);s.pickups.forEach((n,a)=>{const f=pickupImpulses(n,s.source,t,r+a*104729);let o,l;if(!f)o=Float32Array.from(c),l=Float32Array.from(m);else{const p=k=>{const F=v(y,k);return Float32Array.from({length:u},(D,E)=>F[E+f.lead]??0)};o=p(f.channels[0]??new Float64Array(1)),l=f.channels[1]?p(f.channels[1]):Float32Array.from(o)}const S=R([o,l],t);if(S===void 0)return;const w=j(d-S);for(let p=0;p<u;p++)o[p]=(o[p]??0)*w,l[p]=(l[p]??0)*w;if(n.noise){const p=ne(n,t),k=A=>v(A,p).subarray(0,u),F=k(W(u,t,n.noise,r+a*31+1)),D=n.stereo===!1?F:k(W(u,t,n.noise,r+a*31+2)),E=Math.round(.05*t),_=new Float32Array(u);for(const A of i){const O=Math.max(0,Math.round(A.start*t)),C=Math.min(u,Math.round(A.end*t));for(let z=O;z<C;z++){const G=Math.min(z-O,C-1-z);_[z]=Math.max(_[z]??0,G<E?G/E:1)}}const se=R([F,D],t)??-3,te=j(d-n.noise.below+ge(n,s.source,t,r+a*104729)-se);for(let A=0;A<u;A++){const O=(_[A]??0)*te;o[A]=(o[A]??0)+(F[A]??0)*O,l[A]=(l[A]??0)+(D[A]??0)*O}}n.agc&&oe([o,l],{...n.agc,target:d+n.agc.target,...n.agc.gate===void 0?{}:{gate:d+n.agc.gate}},t);const P=j(n.gain);for(let p=0;p<u;p++)h[p]=(h[p]??0)+(o[p]??0)*P,b[p]=(b[p]??0)+(l[p]??0)*P});const g=s.post;if(g){const n=[...g.highpass===!1?[]:[x({type:"highpass",hz:g.highpass},t)],...g.eq.map(a=>x(a,t))];K(h,n),K(b,n),g.deess&&ie([h,b],{...g.deess,threshold:d+g.deess.threshold},t),g.compress&&re([h,b],{...g.compress,threshold:d+g.compress.threshold},t)}const M=R([h,b],t),$=M===void 0?1:j(d-M);for(let n=0;n<u;n++)c[n]=(h[n]??0)*$,m[n]=(b[n]??0)*$}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** A compressor's settings; levels in dBFS. */
|
|
2
|
+
export interface CompressorOptions {
|
|
3
|
+
/** Where it starts to act, dBFS. */
|
|
4
|
+
threshold: number;
|
|
5
|
+
/** Input dB over the threshold per output dB. */
|
|
6
|
+
ratio: number;
|
|
7
|
+
/** The knee's width, dB (0: hard). */
|
|
8
|
+
knee: number;
|
|
9
|
+
/** Seconds to go down, and to come back. */
|
|
10
|
+
attack: number;
|
|
11
|
+
release: number;
|
|
12
|
+
/** The level's detector: a window's RMS, seconds (0: the peak). */
|
|
13
|
+
window: number;
|
|
14
|
+
}
|
|
15
|
+
/** The gain reduction (dB, ≤ 0) of the gain computer for an input level. */
|
|
16
|
+
export declare function gainComputer(x: number, o: Pick<CompressorOptions, "threshold" | "ratio" | "knee">): number;
|
|
17
|
+
/** Compresses the channels in place. */
|
|
18
|
+
export declare function compress(channels: readonly Float32Array[], o: CompressorOptions, rate: number): void;
|
|
19
|
+
/** A de-esser's settings: the band it listens to, and how it presses it down. */
|
|
20
|
+
export interface DeesserOptions {
|
|
21
|
+
/** Where sibilance starts, Hz: the band over it is what is pressed down. */
|
|
22
|
+
hz: number;
|
|
23
|
+
/** The band's level where it starts, dBFS, and its ratio. */
|
|
24
|
+
threshold: number;
|
|
25
|
+
ratio: number;
|
|
26
|
+
attack: number;
|
|
27
|
+
release: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Presses the highs down where they are loud: split at `hz` by a
|
|
31
|
+
* fourth-order Linkwitz–Riley crossover (two Butterworth sections each
|
|
32
|
+
* way, whose sum is an all-pass: flat when nothing is pressed), the band
|
|
33
|
+
* over it given the gain its own level asks for.
|
|
34
|
+
*/
|
|
35
|
+
export declare function deess(channels: readonly Float32Array[], o: DeesserOptions, rate: number): void;
|
|
36
|
+
/** A phone's automatic gain control. */
|
|
37
|
+
export interface AgcOptions {
|
|
38
|
+
/** The level it rides toward, dBFS (the speech's level). */
|
|
39
|
+
target: number;
|
|
40
|
+
/** The most it lifts, dB; it never lowers more than `target` asks. */
|
|
41
|
+
most: number;
|
|
42
|
+
/** Seconds for the gain to come down, and to rise. */
|
|
43
|
+
attack: number;
|
|
44
|
+
release: number;
|
|
45
|
+
/**
|
|
46
|
+
* The speech's level it follows: the mean power of 50 ms windows over
|
|
47
|
+
* this many seconds, s.
|
|
48
|
+
*/
|
|
49
|
+
window: number;
|
|
50
|
+
/**
|
|
51
|
+
* Under this level (dBFS) a window is not speech: the level it follows,
|
|
52
|
+
* and so its gain, hold through it (no gate: undefined, and a pause
|
|
53
|
+
* lifts the room).
|
|
54
|
+
*/
|
|
55
|
+
gate?: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Rides the level in place toward `target`, as a device's automatic gain
|
|
59
|
+
* does: it follows the speech's level over `window` seconds (holding it
|
|
60
|
+
* through what is under `gate`) and sets the gain that brings that level
|
|
61
|
+
* to the target, at most `most` up, moving at `attack` and `release`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function agc(channels: readonly Float32Array[], o: AgcOptions, rate: number): void;
|
|
64
|
+
//# sourceMappingURL=dynamics.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
import{biquad as w,fromDb as m,runBiquads as x}from"./filters.js";export function gainComputer(a,t){const s=a-t.threshold,r=t.knee;let l;return 2*s<-r?l=a:r>0&&2*Math.abs(s)<=r?l=a+(1/t.ratio-1)*(s+r/2)**2/(2*r):l=t.threshold+s/t.ratio,l-a}function u(a,t,s){const r=a[0]?.length??0,l=new Float32Array(r);if(t<=0){for(let o=0;o<r;o++){let n=0;for(const c of a)n=Math.max(n,Math.abs(c[o]??0));l[o]=20*Math.log10(Math.max(n,1e-9))}return l}const f=Math.exp(-1/(t*s));let e=0;for(let o=0;o<r;o++){let n=0;for(const c of a)n=Math.max(n,(c[o]??0)**2);e=f*e+(1-f)*n,l[o]=10*Math.log10(Math.max(e,1e-18))}return l}function M(a,t,s,r){const l=t>0?Math.exp(-1/(t*r)):0,f=s>0?Math.exp(-1/(s*r)):0,e=new Float32Array(a.length);let o=0;for(let n=0;n<a.length;n++){const c=a[n]??0,h=c<o?l:f;o=h*o+(1-h)*c,e[n]=o}return e}export function compress(a,t,s){const r=u(a,t.window,s),l=new Float32Array(r.length);for(let e=0;e<r.length;e++)l[e]=gainComputer(r[e]??-180,t);const f=M(l,t.attack,t.release,s);for(const e of a)for(let o=0;o<e.length;o++)e[o]=(e[o]??0)*m(f[o]??0)}export function deess(a,t,s){const r=w({type:"highpass",hz:t.hz},s),l=w({type:"lowpass",hz:t.hz},s),f=h=>{const p=Float32Array.from(h);x(p,[r,r]);const i=Float32Array.from(h);return x(i,[l,l]),{low:i,high:p}},e=a.map(f),o=u(e.map(h=>h.high),.005,s),n=new Float32Array(o.length);for(let h=0;h<o.length;h++)n[h]=gainComputer(o[h]??-180,{...t,knee:6});const c=M(n,t.attack,t.release,s);a.forEach((h,p)=>{const i=e[p];if(i)for(let g=0;g<h.length;g++)h[g]=(i.low[g]??0)+(i.high[g]??0)*m(c[g]??0)})}export function agc(a,t,s){const r=u(a,.05,s),l=new Float32Array(r.length),f=Math.exp(-1/(Math.max(t.window,.001)*s));let e=-1;for(let n=0;n<r.length;n++){const c=r[n]??-180;if(t.gate===void 0||c>=t.gate){const h=10**(c/10);e=e<0?h:f*e+(1-f)*h}l[n]=e<0?0:Math.min(t.most,t.target-10*Math.log10(Math.max(e,1e-18)))}const o=M(l,t.attack,t.release,s);for(const n of a)for(let c=0;c<n.length;c++)n[c]=(n[c]??0)*m(o[c]??0)}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** The least power of two at or above n. */
|
|
2
|
+
export declare function nextPow2(n: number): number;
|
|
3
|
+
/**
|
|
4
|
+
* In place: the discrete Fourier transform of re + i·im (`inverse`: its
|
|
5
|
+
* inverse, divided by n). n is a power of two.
|
|
6
|
+
*/
|
|
7
|
+
export declare function fft(re: Float64Array, im: Float64Array, inverse?: boolean): void;
|
|
8
|
+
/**
|
|
9
|
+
* `x` convolved with `h`, as long as `x` (what rings on past its end is
|
|
10
|
+
* cut): overlap-add in blocks, two real signals per complex transform.
|
|
11
|
+
*/
|
|
12
|
+
export declare function convolve(x: Float32Array, h: Float32Array | Float64Array): Float32Array;
|
|
13
|
+
/**
|
|
14
|
+
* The magnitude of a filter's response at `n / 2 + 1` frequencies from 0
|
|
15
|
+
* to half the rate, of an impulse response `h` (n a power of two ≥ its
|
|
16
|
+
* length).
|
|
17
|
+
*/
|
|
18
|
+
export declare function magnitudes(h: Float32Array | Float64Array, n: number): Float64Array;
|
|
19
|
+
/**
|
|
20
|
+
* A minimum-phase impulse response of `taps` taps whose magnitude is
|
|
21
|
+
* `gain(frequency in Hz)` (linear) at `rate`: by the real cepstrum folded
|
|
22
|
+
* onto positive quefrencies (the homomorphic method), its end faded by a
|
|
23
|
+
* half Hann window.
|
|
24
|
+
*/
|
|
25
|
+
export declare function minimumPhase(gain: (hz: number) => number, rate: number, taps?: number): Float64Array;
|
|
26
|
+
//# sourceMappingURL=fft.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
const b=new Map;function P(e){let o=b.get(e);if(!o){const a=new Float64Array(e/2),n=new Float64Array(e/2);for(let s=0;s<e/2;s++)a[s]=Math.cos(2*Math.PI*s/e),n[s]=-Math.sin(2*Math.PI*s/e);o={cos:a,sin:n},b.set(e,o)}return o}export function nextPow2(e){let o=1;for(;o<e;)o*=2;return o}export function fft(e,o,a=!1){const n=e.length;if(n<=1)return;for(let c=1,t=0;c<n;c++){let r=n>>1;for(;t&r;r>>=1)t^=r;if(t^=r,c<t){const i=e[c]??0;e[c]=e[t]??0,e[t]=i;const l=o[c]??0;o[c]=o[t]??0,o[t]=l}}const{cos:s,sin:f}=P(n),g=a?-1:1;for(let c=2;c<=n;c<<=1){const t=n/c,r=c/2;for(let i=0;i<n;i+=c)for(let l=0;l<r;l++){const h=s[l*t]??1,u=(f[l*t]??0)*g,w=i+l,M=w+r,y=e[M]??0,A=o[M]??0,F=y*h-A*u,p=y*u+A*h,d=e[w]??0,k=o[w]??0;e[M]=d-F,o[M]=k-p,e[w]=d+F,o[w]=k+p}}if(a)for(let c=0;c<n;c++)e[c]=(e[c]??0)/n,o[c]=(o[c]??0)/n}export function convolve(e,o){const a=new Float32Array(e.length);if(o.length===0||e.length===0)return a;if(o.length<=64){for(let r=0;r<e.length;r++){let i=0;const l=Math.min(o.length,r+1);for(let h=0;h<l;h++)i+=(o[h]??0)*(e[r-h]??0);a[r]=i}return a}const n=nextPow2(2*o.length),s=n-o.length+1,f=new Float64Array(n),g=new Float64Array(n);for(let r=0;r<o.length;r++)f[r]=o[r]??0;fft(f,g);const c=new Float64Array(n),t=new Float64Array(n);for(let r=0;r<e.length;r+=2*s){c.fill(0),t.fill(0);const i=r+s;for(let l=0;l<s;l++)c[l]=e[r+l]??0,t[l]=e[i+l]??0;fft(c,t);for(let l=0;l<n;l++){const h=c[l]??0,u=t[l]??0,w=f[l]??0,M=g[l]??0;c[l]=h*w-u*M,t[l]=h*M+u*w}fft(c,t,!0);for(let l=0;l<n;l++){const h=r+l;h<a.length&&(a[h]=(a[h]??0)+(c[l]??0));const u=i+l;u<a.length&&(a[u]=(a[u]??0)+(t[l]??0))}}return a}export function magnitudes(e,o){const a=new Float64Array(o),n=new Float64Array(o);for(let f=0;f<Math.min(o,e.length);f++)a[f]=e[f]??0;fft(a,n);const s=new Float64Array(o/2+1);for(let f=0;f<=o/2;f++)s[f]=Math.hypot(a[f]??0,n[f]??0);return s}export function minimumPhase(e,o,a=4096){const n=nextPow2(a*4),s=new Float64Array(n),f=new Float64Array(n);for(let t=0;t<=n/2;t++){const r=Math.max(e(t*o/n),1e-6);s[t]=Math.log(r),t>0&&t<n/2&&(s[n-t]=s[t]??0)}fft(s,f,!0);for(let t=1;t<n/2;t++)s[t]=2*(s[t]??0),f[t]=0;f[0]=0,f[n/2]=0;for(let t=n/2+1;t<n;t++)s[t]=0,f[t]=0;fft(s,f);for(let t=0;t<n;t++){const r=Math.exp(s[t]??0),i=f[t]??0;s[t]=r*Math.cos(i),f[t]=r*Math.sin(i)}fft(s,f,!0);const g=new Float64Array(a),c=Math.max(1,Math.floor(a/4));for(let t=0;t<a;t++){const r=t-(a-c),i=r>0?.5*(1+Math.cos(Math.PI*r/c)):1;g[t]=(s[t]??0)*i}return g}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** A biquad's coefficients, a0 divided out. */
|
|
2
|
+
export interface Biquad {
|
|
3
|
+
b0: number;
|
|
4
|
+
b1: number;
|
|
5
|
+
b2: number;
|
|
6
|
+
a1: number;
|
|
7
|
+
a2: number;
|
|
8
|
+
}
|
|
9
|
+
/** One band of an equalizer or a pass, as the cookbook names them. */
|
|
10
|
+
export type FilterSpec = {
|
|
11
|
+
type: "highpass" | "lowpass";
|
|
12
|
+
hz: number;
|
|
13
|
+
q?: number;
|
|
14
|
+
} | {
|
|
15
|
+
type: "peak";
|
|
16
|
+
hz: number;
|
|
17
|
+
db: number;
|
|
18
|
+
q?: number;
|
|
19
|
+
} | {
|
|
20
|
+
type: "lowshelf" | "highshelf";
|
|
21
|
+
hz: number;
|
|
22
|
+
db: number;
|
|
23
|
+
slope?: number;
|
|
24
|
+
} | {
|
|
25
|
+
type: "bandpass";
|
|
26
|
+
hz: number;
|
|
27
|
+
q?: number;
|
|
28
|
+
};
|
|
29
|
+
/** A Butterworth's Q: the flattest pass band. */
|
|
30
|
+
export declare const BUTTERWORTH_Q: number;
|
|
31
|
+
/** A cookbook biquad at `rate`. */
|
|
32
|
+
export declare function biquad(spec: FilterSpec, rate: number): Biquad;
|
|
33
|
+
/** A biquad's gain at `hz` (linear), at `rate`. */
|
|
34
|
+
export declare function biquadGain(b: Biquad, hz: number, rate: number): number;
|
|
35
|
+
/** Filters `x` in place through the biquads in turn. */
|
|
36
|
+
export declare function runBiquads(x: Float32Array, chain: readonly Biquad[]): void;
|
|
37
|
+
/** The gain of a chain of filter specs at `hz` (linear). */
|
|
38
|
+
export declare function chainGain(specs: readonly FilterSpec[], hz: number, rate: number): number;
|
|
39
|
+
/** dB of a linear gain, and the way back. */
|
|
40
|
+
export declare const toDb: (g: number) => number;
|
|
41
|
+
export declare const fromDb: (db: number) => number;
|
|
42
|
+
//# sourceMappingURL=filters.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
export const BUTTERWORTH_Q=Math.SQRT1_2;export function biquad(o,b){const h=Math.min(Math.max(o.hz,1),b*.49),c=2*Math.PI*h/b,s=Math.cos(c),e=Math.sin(c);let a,n,r,l,f,p;switch(o.type){case"lowpass":case"highpass":case"bandpass":{const t=o.q??BUTTERWORTH_Q,i=e/(2*t);l=1+i,f=-2*s,p=1-i,o.type==="lowpass"?(a=(1-s)/2,n=1-s,r=(1-s)/2):o.type==="highpass"?(a=(1+s)/2,n=-(1+s),r=(1+s)/2):(a=i,n=0,r=-i);break}case"peak":{const t=10**(o.db/40),i=e/(2*(o.q??1));a=1+i*t,n=-2*s,r=1-i*t,l=1+i/t,f=-2*s,p=1-i/t;break}case"lowshelf":case"highshelf":{const t=10**(o.db/40),i=o.slope??1,u=e/2*Math.sqrt((t+1/t)*(1/i-1)+2),M=2*Math.sqrt(t)*u;o.type==="lowshelf"?(a=t*(t+1-(t-1)*s+M),n=2*t*(t-1-(t+1)*s),r=t*(t+1-(t-1)*s-M),l=t+1+(t-1)*s+M,f=-2*(t-1+(t+1)*s),p=t+1+(t-1)*s-M):(a=t*(t+1+(t-1)*s+M),n=-2*t*(t-1+(t+1)*s),r=t*(t+1+(t-1)*s-M),l=t+1-(t-1)*s+M,f=2*(t-1-(t+1)*s),p=t+1-(t-1)*s-M);break}}return{b0:a/l,b1:n/l,b2:r/l,a1:f/l,a2:p/l}}export function biquadGain(o,b,h){const c=2*Math.PI*b/h,s=Math.cos(c),e=Math.sin(c),a=Math.cos(2*c),n=Math.sin(2*c),r=o.b0+o.b1*s+o.b2*a,l=-(o.b1*e+o.b2*n),f=1+o.a1*s+o.a2*a,p=-(o.a1*e+o.a2*n);return Math.hypot(r,l)/Math.hypot(f,p)}export function runBiquads(o,b){for(const h of b){let c=0,s=0;for(let e=0;e<o.length;e++){const a=o[e]??0,n=h.b0*a+c;c=h.b1*a-h.a1*n+s,s=h.b2*a-h.a2*n,o[e]=n}}}export function chainGain(o,b,h){let c=1;for(const s of o)c*=biquadGain(biquad(s,h),b,h);return c}export const toDb=o=>20*Math.log10(Math.max(o,1e-12)),fromDb=o=>10**(o/20);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type ResolvedVoice } from "./chain.js";
|
|
2
|
+
import { type RecordingMeasureOptions, type RecordingMeasurement } from "./measure.js";
|
|
3
|
+
import type { VoiceOptions, VoiceSetting } from "./setup.js";
|
|
4
|
+
/** How a setting is fitted. */
|
|
5
|
+
export interface VoiceFitOptions {
|
|
6
|
+
/** Rounds of recording, measuring and moving. */
|
|
7
|
+
rounds: number;
|
|
8
|
+
/** The response moves at most this many dB at any band. */
|
|
9
|
+
most: number;
|
|
10
|
+
/** The bands the response is fitted over, Hz. */
|
|
11
|
+
from: number;
|
|
12
|
+
to: number;
|
|
13
|
+
/** The room's reverberation time stays within these, s. */
|
|
14
|
+
rt60: readonly [number, number];
|
|
15
|
+
/** How both voices are measured. */
|
|
16
|
+
measure: RecordingMeasureOptions;
|
|
17
|
+
}
|
|
18
|
+
export declare const VOICE_FIT_DEFAULTS: VoiceFitOptions;
|
|
19
|
+
/** How far a voice's measurement is from the reference's. */
|
|
20
|
+
export interface FitDistance {
|
|
21
|
+
/** RMS of the spectrum's difference over the fitted bands, dB. */
|
|
22
|
+
spectrum: number;
|
|
23
|
+
/** The decay's difference (piece minus reference), s; absent where either is missing. */
|
|
24
|
+
decay?: number;
|
|
25
|
+
/** The room tone's level under the voice, piece minus reference, LU. */
|
|
26
|
+
tone?: number;
|
|
27
|
+
/** The tone's tilt, piece minus reference, dB per octave. */
|
|
28
|
+
tilt?: number;
|
|
29
|
+
}
|
|
30
|
+
/** A setting fitted to a reference. */
|
|
31
|
+
export interface VoiceFit {
|
|
32
|
+
/** The piece's setting with the numbers moved. */
|
|
33
|
+
setting: VoiceOptions;
|
|
34
|
+
/** The fields that moved. */
|
|
35
|
+
moved: string[];
|
|
36
|
+
/** The piece's voice before and after, and how far each is from the reference. */
|
|
37
|
+
before: RecordingMeasurement;
|
|
38
|
+
after: RecordingMeasurement;
|
|
39
|
+
distance: {
|
|
40
|
+
before: FitDistance;
|
|
41
|
+
after: FitDistance;
|
|
42
|
+
};
|
|
43
|
+
/** The bands where the response reached `most`, Hz. */
|
|
44
|
+
limited: number[];
|
|
45
|
+
/** What the reference shows that the setup does not record, and what could not be measured. */
|
|
46
|
+
notes: string[];
|
|
47
|
+
}
|
|
48
|
+
/** The distance of one measurement from another. */
|
|
49
|
+
export declare function fitDistance(piece: RecordingMeasurement, reference: RecordingMeasurement, from?: number, to?: number): FitDistance;
|
|
50
|
+
/**
|
|
51
|
+
* Fits a voice's setting to a reference's measurement. `record` plays the
|
|
52
|
+
* piece's speech through a resolved setting and returns its channels at
|
|
53
|
+
* `rate` (the whole voice, as the measurement should hear it).
|
|
54
|
+
*/
|
|
55
|
+
export declare function fitVoice(setting: VoiceSetting | undefined, record: (voice: ResolvedVoice) => readonly Float32Array[], reference: RecordingMeasurement, rate: number, options?: Partial<VoiceFitOptions>): VoiceFit;
|
|
56
|
+
//# sourceMappingURL=fit.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
import{resolveVoice as j}from"./chain.js";import{measureRecording as K,RECORDING_MEASURE_DEFAULTS as P}from"./measure.js";import{curveDb as Q}from"./mic.js";export const VOICE_FIT_DEFAULTS={rounds:4,most:12,from:100,to:12500,rt60:[.08,2.5],measure:P};const T=o=>Math.round(o*10)/10,_=o=>Math.round(o*100)/100,C=o=>Math.round(o*2)/2,z=(o,l,e)=>Math.min(e,Math.max(l,o));function W(o){return o===void 0||o===!1?{}:typeof o=="string"?{setup:o}:o}export function fitDistance(o,l,e=VOICE_FIT_DEFAULTS.from,F=VOICE_FIT_DEFAULTS.to){const k=new Map(l.spectrum.map(d=>[d.hz,d.db]));let n=0,c=0;for(const d of o.spectrum){const s=k.get(d.hz);s===void 0||d.hz<e||d.hz>F||(n+=(d.db-s)**2,c++)}return{spectrum:T(Math.sqrt(n/Math.max(c,1))),..."t60"in o.decay&&"t60"in l.decay?{decay:_(o.decay.t60-l.decay.t60)}:{},..."below"in o.tone&&"below"in l.tone?{tone:T(o.tone.below-l.tone.below),tilt:T(o.tone.tilt-l.tone.tilt)}:{}}}export function fitVoice(o,l,e,F,k={}){const n={...VOICE_FIT_DEFAULTS,...k},c=W(o),d=j(c);if(d===!1)throw new Error("A voice played as it is has no setting to fit.");const s=d.pickups[0];if(!s)throw new Error("A voice setting has a microphone.");const I=i=>K(l(i),F,n.measure),w=e.spectrum.map(i=>i.hz).filter(i=>i>=n.from&&i<=n.to),y=new Map(w.map(i=>[i,0]));let r=[s.band[0],s.band[1]],p=s.room&&"t60"in e.decay?s.room.rt60:void 0;const m=s.noise&&"below"in e.tone?{below:s.noise.below,tilt:s.noise.tilt}:void 0,v=[],L=()=>{const i=w.filter(h=>h>=r[0]&&h<=r[1]).map(h=>[h,C(Q(s.response,h)+(y.get(h)??0))]),E=p===void 0?void 0:typeof c.room=="string"?{preset:c.room,rt60:_(p)}:{...typeof c.room=="object"?c.room:{},rt60:_(p)},x=m?{...typeof c.noise=="object"?c.noise:{},below:C(m.below),tilt:T(m.tilt)}:void 0;return{...c,...i.length>0?{response:i}:{},...r[0]!==s.band[0]||r[1]!==s.band[1]?{band:[Math.round(r[0]),Math.round(r[1])]}:{},...E?{room:E}:{},...x?{noise:x}:{}}},f=I(d);let u=f;for(let i=0;i<n.rounds;i++){const E=new Map(e.spectrum.map(t=>[t.hz,t.db])),x=new Map;for(const t of u.spectrum){const a=E.get(t.hz);a!==void 0&&y.has(t.hz)&&x.set(t.hz,a-t.db)}const h=t=>(x.get(t)??0)<-n.most,B=[...w].reverse();let D=-1;for(const t of B){if(t<2e3||!h(t))break;D=t}D>0&&(r=[r[0],Math.min(r[1],D/2**(1/6))]);let O=-1;for(const t of w){if(t>400||!h(t))break;O=t}O>0&&(r=[Math.max(r[0],O*2**(1/6)),r[1]]);for(const[t,a]of w.entries()){if(a<r[0]||a>r[1]){y.set(a,0);continue}const b=g=>x.get(w[g]??-1),N=[[b(t-1)??NaN,.25],[b(t)??NaN,.5],[b(t+1)??NaN,.25]].filter(([g])=>Number.isFinite(g)),$=N.reduce((g,[,U])=>g+U,0),H=$>0?N.reduce((g,[U,J])=>g+U*J,0)/$:0;y.set(a,z((y.get(a)??0)+H,-n.most,n.most))}if(p!==void 0&&"t60"in u.decay&&"t60"in e.decay){v.push([Math.log(p),Math.log(u.decay.t60)]);const t=Math.log(e.decay.t60),a=v[v.length-1],b=v[v.length-2];let R=1;if(a&&b&&Math.abs(a[0]-b[0])>.001){const $=(a[1]-b[1])/(a[0]-b[0]);$>.1&&(R=$)}const N=z((t-(a?.[1]??t))/R,-Math.log(3),Math.log(3));p=z(Math.exp((a?.[0]??Math.log(p))+N),n.rt60[0],n.rt60[1])}m&&"below"in u.tone&&"below"in e.tone&&(m.below=z(m.below+(e.tone.below-u.tone.below),10,90),m.tilt=z(m.tilt+(e.tone.tilt-u.tone.tilt),-12,6));const V=j(L());if(V===!1)break;u=I(V)}const A=L(),q=[...A.response?["response"]:[],...A.band?["band"]:[],...p!==void 0?["room.rt60"]:[],...m?["noise.below","noise.tilt"]:[]],M=[],S=d.setup;"missing"in e.decay?M.push(`The reference's room was not measured: ${e.decay.missing}.`):!s.room&&("missing"in f.decay||e.decay.t60>f.decay.t60*1.25)?M.push(`The reference's voice falls away over ${e.decay.t60.toFixed(2)} s where the piece's ${"t60"in f.decay?`does over ${f.decay.t60.toFixed(2)} s`:"stops dead"}, and the setup ${S} records no room: a setup with one, or room: "bedroom" (any room), lets the fit set its reverberation.`):"missing"in f.decay&&s.room&&M.push(`The piece's room was not measured: ${f.decay.missing}.`),"missing"in e.tone?M.push(`The reference's room tone was not measured: ${e.tone.missing}.`):s.noise||M.push(`The reference's pauses hold a room tone ${e.tone.below.toFixed(1)} LU under its voice, and the setup ${S} records none: noise: {} adds one the fit can set.`);const G=w.filter(i=>Math.abs(y.get(i)??0)>=n.most-1e-9);return{setting:A,moved:q,before:f,after:u,distance:{before:fitDistance(f,e,n.from,n.to),after:fitDistance(u,e,n.from,n.to)},limited:G,notes:M}}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { pickupImpulses, recordVoice, resolveVoice, voiceProblem, type ResolvedPickup, type ResolvedPost, type ResolvedRoom, type ResolvedVoice, type VoiceSpan, } from "./chain.js";
|
|
2
|
+
export { fitDistance, fitVoice, VOICE_FIT_DEFAULTS, type FitDistance, type VoiceFit, type VoiceFitOptions, } from "./fit.js";
|
|
3
|
+
export { bandwidthOf, BANDWIDTH_DEFAULTS, type Bandwidth, type BandwidthOptions, } from "./bandwidth.js";
|
|
4
|
+
export { integratedLoudness, steadyLoudness } from "./loudness.js";
|
|
5
|
+
export { measureRecording, RECORDING_MEASURE_DEFAULTS, THIRD_OCTAVES, type RecordingMeasureOptions, type RecordingMeasurement, } from "./measure.js";
|
|
6
|
+
export { PATTERNS, type Pattern } from "./mic.js";
|
|
7
|
+
export { POST_PRESETS, ROOM_PRESETS, SETUP_PRESETS, SOURCE_DEFAULTS, type PostPreset, type RoomPreset, type SetupPreset, } from "./presets.js";
|
|
8
|
+
export { MATERIALS } from "./room.js";
|
|
9
|
+
export { POSTS, ROOMS, VOICE_SETUPS, type AgcSettings, type NoiseOptions, type PostName, type PostOptions, type RoomName, type RoomOptions, type Surface, type VoiceOptions, type VoiceSetting, type VoiceSetup, } from "./setup.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
export{pickupImpulses,recordVoice,resolveVoice,voiceProblem}from"./chain.js";export{fitDistance,fitVoice,VOICE_FIT_DEFAULTS}from"./fit.js";export{bandwidthOf,BANDWIDTH_DEFAULTS}from"./bandwidth.js";export{integratedLoudness,steadyLoudness}from"./loudness.js";export{measureRecording,RECORDING_MEASURE_DEFAULTS,THIRD_OCTAVES}from"./measure.js";export{PATTERNS}from"./mic.js";export{POST_PRESETS,ROOM_PRESETS,SETUP_PRESETS,SOURCE_DEFAULTS}from"./presets.js";export{MATERIALS}from"./room.js";export{POSTS,ROOMS,VOICE_SETUPS}from"./setup.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integrated loudness, LUFS, of channels at `rate` (each weighted 1, as
|
|
3
|
+
* left and right are); undefined when everything is under the gate.
|
|
4
|
+
*/
|
|
5
|
+
export declare function integratedLoudness(channels: readonly Float32Array[], rate: number): number | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* The K-weighted level of everything, LUFS, with no gate: for a steady
|
|
8
|
+
* sound too quiet for the integrated loudness's -70 LUFS gate (a room's
|
|
9
|
+
* tone); undefined for digital silence.
|
|
10
|
+
*/
|
|
11
|
+
export declare function steadyLoudness(channels: readonly Float32Array[], rate: number): number | undefined;
|
|
12
|
+
//# sourceMappingURL=loudness.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
+
import{biquad as y,runBiquads as m}from"./filters.js";function x(a){const f=1681.974450955533,u=3.999843853973347,e=.7071752369554196,t=Math.tan(Math.PI*f/a),h=10**(u/20),s=h**.4996667741545416,o=1+t/e+t*t,l={b0:(h+s*t/e+t*t)/o,b1:2*(t*t-h)/o,b2:(h-s*t/e+t*t)/o,a1:2*(t*t-1)/o,a2:(1-t/e+t*t)/o},i=y({type:"highpass",hz:38.13547087602444,q:.5003270373238773},a),d={b0:1,b1:-2,b2:1,a1:i.a1,a2:i.a2};return[l,d]}export function integratedLoudness(a,f){const u=a[0]?.length??0,e=Math.round(.4*f),t=Math.round(.1*f);if(u<e)return;const h=x(f),s=Math.floor(u/t),o=new Float64Array(s);for(const n of a){const c=Float32Array.from(n);m(c,h);for(let r=0;r<s;r++){let M=0;for(let p=r*t;p<(r+1)*t;p++)M+=(c[p]??0)**2;o[r]=(o[r]??0)+M}}const l=[],i=Math.round(e/t);for(let n=0;n+i<=s;n++){let c=0;for(let r=0;r<i;r++)c+=o[n+r]??0;l.push(c/(i*t))}const d=n=>-.691+10*Math.log10(Math.max(n,1e-20)),b=l.filter(n=>d(n)>-70);if(b.length===0)return;const k=b.reduce((n,c)=>n+c,0)/b.length,g=b.filter(n=>d(n)>d(k)-10);if(g.length!==0)return d(g.reduce((n,c)=>n+c,0)/g.length)}export function steadyLoudness(a,f){const u=x(f);let e=0,t=0;for(const h of a){const s=Float32Array.from(h);m(s,u);let o=0;for(const l of s)o+=l*l;e+=o/Math.max(1,s.length),t=Math.max(t,s.length)}if(!(t===0||e<=1e-20))return-.691+10*Math.log10(e)}
|