diff --git a/packages/preprocessor/.gitignore b/packages/preprocessor/.gitignore index a651e27..fb1ab4d 100644 --- a/packages/preprocessor/.gitignore +++ b/packages/preprocessor/.gitignore @@ -1,3 +1,4 @@ +/target # Logs logs *.log @@ -24,7 +25,7 @@ dist-ssr *.sw? # public samples -public/samples/* -public/media/* -src/song_list.ts -src/db.js +# public/samples/* +# public/media/* +# src/song_list.ts +# src/db.js diff --git a/packages/preprocessor/@types/lib.rs/config.ts b/packages/preprocessor/@types/lib.rs/config.ts new file mode 100644 index 0000000..b939e94 --- /dev/null +++ b/packages/preprocessor/@types/lib.rs/config.ts @@ -0,0 +1,11 @@ +import { LoaderConfig, T } from "hyperimport"; +export default { + buildCommand: ["rustc", "--crate-type", "cdylib", "/home/djkato/Code PF/euterpe-preprocessor/src/lib.rs", "--out-dir", "build/lib.rs"], + outDir: "build/lib.rs", + symbols: { + get_fft_data: { + args: [], + returns: T.cstring + }, + } +} satisfies LoaderConfig.Main; diff --git a/packages/preprocessor/@types/lib.rs/lastModified b/packages/preprocessor/@types/lib.rs/lastModified new file mode 100644 index 0000000..bf538e5 --- /dev/null +++ b/packages/preprocessor/@types/lib.rs/lastModified @@ -0,0 +1 @@ +1697374218769 \ No newline at end of file diff --git a/packages/preprocessor/@types/lib.rs/types.d.ts b/packages/preprocessor/@types/lib.rs/types.d.ts new file mode 100644 index 0000000..a059cfc --- /dev/null +++ b/packages/preprocessor/@types/lib.rs/types.d.ts @@ -0,0 +1,4 @@ +declare module "*/lib.rs" { + const symbols: import("bun:ffi").ConvertFns; + export = symbols; +} \ No newline at end of file diff --git a/packages/preprocessor/Cargo.lock b/packages/preprocessor/Cargo.lock new file mode 100644 index 0000000..98bb324 --- /dev/null +++ b/packages/preprocessor/Cargo.lock @@ -0,0 +1,161 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "euterpe-preprocessor" +version = "0.1.0" +dependencies = [ + "anyhow", + "hound", + "rayon", + "walkdir", +] + +[[package]] +name = "hound" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/packages/preprocessor/Cargo.toml b/packages/preprocessor/Cargo.toml new file mode 100644 index 0000000..7e15ce6 --- /dev/null +++ b/packages/preprocessor/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "euterpe-preprocessor" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.75" +hound = "3.5.1" +rayon = "1.8.0" +walkdir = "2.4.0" diff --git a/packages/preprocessor/README.md b/packages/preprocessor/README.md new file mode 100644 index 0000000..ee49b31 --- /dev/null +++ b/packages/preprocessor/README.md @@ -0,0 +1,14 @@ +# How to use +To extend the Rust library, make sure the functions you're exporting have `#[no_mangle]` derived +and they `extern "C"`. To use, just import `{func} from "./lib.rs"`. +To make sure args and return types match, go to `@types/lib.rs/config.ts` +and change the types of args and returns. + +``` +bun i +bun dev +``` + +``` +open http://localhost:3000 +``` diff --git a/packages/preprocessor/build/lib.rs/liblib.so b/packages/preprocessor/build/lib.rs/liblib.so new file mode 100755 index 0000000..ca8898b Binary files /dev/null and b/packages/preprocessor/build/lib.rs/liblib.so differ diff --git a/packages/preprocessor/bun.lockb b/packages/preprocessor/bun.lockb new file mode 100755 index 0000000..e43b76f Binary files /dev/null and b/packages/preprocessor/bun.lockb differ diff --git a/packages/preprocessor/bunfig.toml b/packages/preprocessor/bunfig.toml new file mode 100644 index 0000000..699cad1 --- /dev/null +++ b/packages/preprocessor/bunfig.toml @@ -0,0 +1,4 @@ +preload = ["./node_modules/hyperimport/preload.ts"] + +[hyperimport] +loaders = ["rs"] diff --git a/packages/preprocessor/index.html b/packages/preprocessor/index.html deleted file mode 100644 index 6de99d0..0000000 --- a/packages/preprocessor/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - FFT generator - - - - -
- -
- - -
-
- -

Upload DB

-
- Download DB -
-
-
- -
- - - - \ No newline at end of file diff --git a/packages/preprocessor/package.json b/packages/preprocessor/package.json index 4c463e5..bae46d3 100644 --- a/packages/preprocessor/package.json +++ b/packages/preprocessor/package.json @@ -1,22 +1,15 @@ { - "name": "@euterpe.js/preprocessor", - "private": true, - "version": "0.0.0", + "name": "euterpe-preprocessor", + "module": "src/index.ts", "type": "module", "scripts": { - "crawl": "cd src && node crawler.mjs", - "process": "npm run crawl && vite", - "media-process": "cd src && node media_process.js", - "serve": "vite", - "build": "tsc && vite build", - "preview": "vite preview" - }, - "devDependencies": { - "typescript": "^5.0.2", - "vite": "^4.4.0" + "dev": "bun run --hot src/index.ts" }, "dependencies": { - "@euterpe.js/music-library": "*", - "filehound": "^1.17.6" + "hono": "^3.7.2", + "hyperimport": "^0.1.0" + }, + "devDependencies": { + "bun-types": "^0.6.2" } } diff --git a/packages/preprocessor/project.json b/packages/preprocessor/project.json index 89e1059..ec75719 100644 --- a/packages/preprocessor/project.json +++ b/packages/preprocessor/project.json @@ -1,70 +1,70 @@ { - "name": "@euterpe.js/preprocessor", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "packages/preprocessor/src", - "tags": [], - "targets": { - "build": { - "executor": "@nx/vite:build", - "outputs": [ - "{options.outputPath}" - ], - "defaultConfiguration": "production", - "options": { - "outputPath": "dist/packages/preprocessor" - }, - "configurations": { - "development": { - "mode": "development" - }, - "production": { - "mode": "production" - } - } - }, - "serve": { - "executor": "@nx/vite:dev-server", - "defaultConfiguration": "development", - "options": { - "buildTarget": "preprocessor:build" - }, - "configurations": { - "development": { - "buildTarget": "preprocessor:build:development", - "hmr": true - }, - "production": { - "buildTarget": "preprocessor:build:production", - "hmr": false - } - } - }, - "preview": { - "executor": "@nx/vite:preview-server", - "defaultConfiguration": "development", - "options": { - "buildTarget": "preprocessor:build" - }, - "configurations": { - "development": { - "buildTarget": "preprocessor:build:development" - }, - "production": { - "buildTarget": "preprocessor:build:production" - } - } - }, - "lint": { - "executor": "@nx/linter:eslint", - "outputs": [ - "{options.outputFile}" - ], - "options": { - "lintFilePatterns": [ - "packages/preprocessor/**/*.ts" - ] - } - } - } -} \ No newline at end of file + "name": "@euterpe.js/preprocessor", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "packages/preprocessor/src", + "tags": [], + "targets": { + "build": { + "executor": "bun:build", + "outputs": [ + "{options.outputPath}" + ], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/packages/preprocessor" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "serve": { + "executor": "bun:dev", + "defaultConfiguration": "development", + "options": { + "buildTarget": "preprocessor:build" + }, + "configurations": { + "development": { + "buildTarget": "preprocessor:build:development", + "hmr": true + }, + "production": { + "buildTarget": "preprocessor:build:production", + "hmr": false + } + } + }, + "preview": { + "executor": "bun:start", + "defaultConfiguration": "development", + "options": { + "buildTarget": "preprocessor:build" + }, + "configurations": { + "development": { + "buildTarget": "preprocessor:build:development" + }, + "production": { + "buildTarget": "preprocessor:build:production" + } + } + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": [ + "{options.outputFile}" + ], + "options": { + "lintFilePatterns": [ + "packages/preprocessor/**/*.ts" + ] + } + } + } +} diff --git a/packages/preprocessor/public/vite.svg b/packages/preprocessor/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/packages/preprocessor/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/preprocessor/src/client/index.html b/packages/preprocessor/src/client/index.html new file mode 100644 index 0000000..d1e766c --- /dev/null +++ b/packages/preprocessor/src/client/index.html @@ -0,0 +1,72 @@ + + + + + + + FFT generator + + + + +
+ +
+ +
+ +

Upload DB

+
+ Download DB +
+
+ +
+ + + + diff --git a/packages/preprocessor/src/client/main.js b/packages/preprocessor/src/client/main.js new file mode 100644 index 0000000..0c83102 --- /dev/null +++ b/packages/preprocessor/src/client/main.js @@ -0,0 +1,33 @@ +document.getElementById("regenerate").addEventListener("click", async (ev) => { + result = await analyze() + download(JSON.stringify(result.db), "db.json", "text/plain") +}) + +document.getElementById("upload").addEventListener("change", (ev) => { + /* + audioContext.resume() + const fileReader = new FileReader() + fileReader.readAsText(ev.target.files[0]) + fileReader.onload = event => { + let str = JSON.parse(event.target.result) + let new_db = from_json(str) + //-infinity get stringified to null, undo that + for (const song of new_db.songs) { + if (song.fft_data) { + for (let i = 0; i < song.fft_data.length; i++) { + if (song.fft_data[i] === null || song.fft_data[i] === undefined) song.fft_data[i] = -Infinity + } + } + } + result = { db: new_db, analyzer_node: audioContextAnalyser } + } + */ +}) + +function download(content, fileName, contentType) { + var a = document.querySelector("#download"); + var file = new Blob([content], { type: contentType }); + a.href = URL.createObjectURL(file); + a.download = fileName; + // a.click(); +} diff --git a/packages/preprocessor/src/crawler.mjs b/packages/preprocessor/src/crawler.mjs deleted file mode 100644 index 6e84a80..0000000 --- a/packages/preprocessor/src/crawler.mjs +++ /dev/null @@ -1,4 +0,0 @@ -import filehound from "filehound" -import fs from "fs" -const songs = filehound.create().path("../public/samples").ext(["ogg"]).findSync() -fs.writeFile('songs_list.ts', `export const songs = ` + JSON.stringify(songs), 'utf8', () => { 1 + 1 }) \ No newline at end of file diff --git a/packages/preprocessor/src/generate_db.ts b/packages/preprocessor/src/generate_db.ts deleted file mode 100644 index 8246948..0000000 --- a/packages/preprocessor/src/generate_db.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Collection, Ref, RefTo, Song, DB, } from "@euterpe.js/music-library" -import { songs } from "./songs_list" - -export function generate_db() { - console.log(songs) - // construct db - let db = new DB - let collections: string[] = new Array() - let new_songs = [] - - //create collections by folder names - for (let i = 0; i < songs.length; i++) { - const song = songs[i] - const last_i = song.lastIndexOf("\\") - const collection_name = song.slice(song.slice(0, last_i).lastIndexOf("\\") + 1, last_i) - /* - const foreforelast_i = song.slice(0, forelast_i - 1) - const foreforeforelast_i = song.slice(0, foreforelast_i - 1).lastIndexOf("\\") - */ - if (!collections.includes(collection_name)) { - console.log(`creating collection ${collection_name}`) - db.add([new Collection({ - name: collection_name, - songs: [], - artists: [], - })]) - collections.push(collection_name) - } - - let col = db.collections.find(col => col.name == collection_name)! - let col_id = col.id - new_songs.push({ song: song, collection_id: col_id! }) - } - - //create songs - for (let i = 0; i < new_songs.length; i++) { - let song = new_songs[i] - const last_i = song.song.lastIndexOf("\\") - - const name = song.song.slice(last_i + 1) - const song_url = song.song.slice(song.song.indexOf("public\\") + 7) - const db_song = new Song({ - name: name.slice(0, name.lastIndexOf(".")), - artists: [], - url: new URL(`${window.location.href}${song_url}`.replaceAll("\\", "/")), - duration: 0, - remix_artists: [], - in_collection: new Ref(RefTo.Collections, song.collection_id) - }) - db.add([db_song]) - } - console.log(db) - return db -} diff --git a/packages/preprocessor/src/index.ts b/packages/preprocessor/src/index.ts new file mode 100644 index 0000000..31df275 --- /dev/null +++ b/packages/preprocessor/src/index.ts @@ -0,0 +1,14 @@ +import { Hono } from 'hono' +import { get_fft_data } from "./lib.rs" +import { serveStatic } from 'hono/cloudflare-workers' + +const app = new Hono() + +app.use("/media", serveStatic({ root: "./public/media" })) +app.use("/samples", serveStatic({ root: "./public/samples" })) +app.use('/', serveStatic({ root: "./client" })) +app.get("/api/generate", (c) => { + let res = get_fft_data() + return c.json({ res }) +}) +export default app diff --git a/packages/preprocessor/src/lib.rs b/packages/preprocessor/src/lib.rs new file mode 100644 index 0000000..7c76662 --- /dev/null +++ b/packages/preprocessor/src/lib.rs @@ -0,0 +1,104 @@ +use std::{ + ffi::{c_char, CString}, + path::PathBuf, +}; + +use anyhow::{bail, Context}; +use walkdir::WalkDir; + +// Actually returns JSON but ye... +#[no_mangle] +pub extern "C" fn get_fft_data() -> *mut c_char { + let files = crawl_and_analyze(PathBuf::from("../public/media")); + let SVG::from(""); + return CString::new("Hello!").unwrap().into_raw(); +} + +struct File { + pub svg: Option, + pub samples: Vec, + pub path_buf: PathBuf, +} + +struct Points { + pub x: i16, + pub y: i16, +} + +struct ViewBox { + pub h_0: i16, + pub h_max: i16, + pub w_0: i16, + pub w_max: i16, +} +impl ViewBox { + pub fn default() -> Self { + ViewBox { + h_0: 0, + w_0: 0, + h_max: 500, + w_max: 500, + } + } +} + +struct SVG { + view_box: ViewBox, + points: Points, + path: Option, +} + +impl SVG { + fn from(samples: Vec) -> Self {} + fn mutate_points(&mut self) {} + + fn catmull_rom_smooth(&mut self) {} + + fn normalize(&mut self) { + // Set lowest sample value to 0, max to 1 and make it linear instead of logarythmic + } +} + +fn crawl_and_analyze(root: PathBuf) -> anyhow::Result> { + // Find all WAV files, return their paths + let file_paths = crawl(root)?; + let files = file_paths.into_iter().map(|p| File { + samples: get_file_samples(p).unwrap(), + svg: None, + path_buf: p, + }); + bail!("") +} + +fn crawl(root: PathBuf) -> anyhow::Result> { + let mut file_paths = vec![]; + for path in WalkDir::new(root).max_depth(5) { + if let Ok(path) = path { + if path.file_type().is_file() { + if let Some(ext) = path.path().extension() { + if ext == "wav" { + file_paths.push(path.path().to_path_buf()); + } + } + } + } + } + Ok(file_paths) +} + +fn get_file_samples(path: PathBuf) -> anyhow::Result> { + // Read wav file, return its samples + bail!("") +} + +/* +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +}*/ diff --git a/packages/preprocessor/src/main.ts b/packages/preprocessor/src/main.ts deleted file mode 100644 index 359bbac..0000000 --- a/packages/preprocessor/src/main.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { DB, from_json } from "@euterpe.js/music-library" -import { generate_db } from "./generate_db" -import { AudioVisualBuilder, SmoothingAlgorythm, ShapeType, WaveformOrientation, WaveformShape } from "@euterpe.js/visualizer" - -let result: AnalyzeReturn | undefined; - -let db = generate_db() -//Create all audio nodes -const audioEl = document.querySelector("#audio") as HTMLAudioElement -const audioContext = new AudioContext() -const track = audioContext.createMediaElementSource(audioEl) -const gain = audioContext.createGain() -gain.gain.value = 0 -const audioContextAnalyser = audioContext.createAnalyser() -audioContextAnalyser.fftSize = 32 -audioContextAnalyser.smoothingTimeConstant = 0 -const analyserBufferLength = audioContextAnalyser.frequencyBinCount -const FFTDataArray = new Float32Array(analyserBufferLength) -//Connect all audio Nodes -track.connect(audioContextAnalyser).connect(gain).connect(audioContext.destination) - - -document.getElementById("analyze")!.addEventListener("click", async (ev) => { - audioContext.resume() - result = await analyze() - download(JSON.stringify(result.db), "db.json", "text/plain") -}) - -document.getElementById("create-svg")!.addEventListener("click", (ev) => { - audioContext.resume() - svg() -}) - -document.getElementById("upload")!.addEventListener("change", (ev) => { - audioContext.resume() - const fileReader = new FileReader() - fileReader.readAsText(ev.target.files[0]) - fileReader.onload = event => { - let str = JSON.parse(event.target.result) - let new_db = from_json(str) - //-infinity get stringified to null, undo that - for (const song of new_db.songs) { - if (song.fft_data) { - for (let i = 0; i < song.fft_data.length; i++) { - if (song.fft_data[i] === null || song.fft_data[i] === undefined) song.fft_data[i] = -Infinity - } - } - } - result = { db: new_db, analyzer_node: audioContextAnalyser } - } - -}) - -async function svg() { - if (!result) { - alert("not analyzed yet!") - return - } - console.log("Creating svgs...") - const canvas_wrapper = document.querySelector(".canvas-wrapper") as HTMLElement - - const waveform_canvas = document.querySelector("#waveform-canvas")?.cloneNode() as SVGSVGElement - - canvas_wrapper.childNodes.forEach((c) => c.remove()) - canvas_wrapper.appendChild(waveform_canvas) - - for (const song of result.db.songs) { - console.log("creating waveform for -> " + song.name) - const curr_waveform_canvas = waveform_canvas.cloneNode() as SVGSVGElement - waveform_canvas.parentElement?.append(curr_waveform_canvas) - const waveform_visual_builder = new AudioVisualBuilder(result.analyzer_node, curr_waveform_canvas) - .set_fft_data_tresholds({ point_count_i: 100, fft_multiplier_i: .9, fft_offset_i: -65 }) - .set_fft_time_smoothing(0.8) - .set_smoothing_algorythm(SmoothingAlgorythm.CatmullRom) - const waveform_visual = waveform_visual_builder.build(ShapeType.Waveform, true, { fft_data: new Float32Array(new Float64Array(song.fft_data!)), orientation: WaveformOrientation.Horizontal, shape_type: WaveformShape.LineLike }) - waveform_visual.draw_once() - // await new Promise((done) => setTimeout(() => done(), 500)) - // @ts-ignore - song.metadata[0] = curr_waveform_canvas.children[0].getAttribute("d") - song.fft_data = [] - } - waveform_canvas.remove() - console.dir(result.db, { depth: null }) - download(JSON.stringify(result.db), "db.json", "text/plain") - -} -async function analyze(): Promise { - console.clear() - const audioEl = document.querySelector("#audio") as HTMLAudioElement - console.log("analysing...") - const samplingRate = 100 - - // db.songs.splice(0, 10) - // db.songs.splice(2) - console.log(db) - for (const song of db.songs) { - // const song = db.songs[db.songs.length - 1] - console.log(`Analyzing ${song.name}, ${db.songs.indexOf(song) + 1}/${db.songs.length}`) - //if not loaded yet keep trying - audioEl.src = song.url.href - await awaitLoad(audioEl) - song.duration = audioEl.duration - let currentFFTData = [] - for (let curSecond = 0; curSecond < song.duration; curSecond += song.duration / samplingRate) { - console.log("working...") - audioEl.currentTime = curSecond - await audioEl.play() - await new Promise((done) => setTimeout(() => done(), 100)) - audioContextAnalyser.getFloatFrequencyData(FFTDataArray) - let volume = 0 - FFTDataArray.forEach((element) => { - volume += element - }) - currentFFTData.push(Math.round((volume / FFTDataArray.length) * 100) / 100) - } - song.fft_data = currentFFTData - console.log(song.fft_data) - } - console.log("Analyzation finished!") - const result: AnalyzeReturn = { analyzer_node: audioContextAnalyser, db: db } - return result -} -function download(content: BlobPart, fileName: string, contentType: string) { - var a = document.querySelector("#download") as HTMLAnchorElement; - var file = new Blob([content], { type: contentType }); - a.href = URL.createObjectURL(file); - a.download = fileName; - // a.click(); -} -type AnalyzeReturn = { - analyzer_node: AnalyserNode, - db: DB -} -function awaitLoad(audioEl: HTMLAudioElement) { - return new Promise((resolve, reject) => { - audioEl.addEventListener("loadeddata", function () { - if (audioEl.readyState >= 4) { - resolve() - } - }) - }) -} diff --git a/packages/preprocessor/src/media_process.js b/packages/preprocessor/src/media_process.js deleted file mode 100644 index 20ceca2..0000000 --- a/packages/preprocessor/src/media_process.js +++ /dev/null @@ -1,113 +0,0 @@ -/** - * TODO: - * -add back -metadata - * - */ - -import filehound from "filehound" -import { execSync, exec } from 'child_process' -import { fstat, unlinkSync } from "fs" - -function generate_new_photo_sizes(file, currentExtention) { - exec(`start ffmpeg -y -i "${file}.${currentExtention}" -lossless 0 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_ogw.webp" -vf scale=1000:-1 -lossless 0 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_1000w.webp" -vf scale=800:-1 -lossless 0 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_800w.webp" -vf scale=500:-1 -lossless 0 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_500w.webp" -vf scale=320:-1 -lossless 0 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_320w.webp" -vf scale=-1:64,gblur=sigma=10:steps=2 -lossless 0 -compression_level 6 -quality 85 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_placeholder.webp"`) -} -function generate_new_anim_photo_sizes(file, currentExtention) { - exec(`start ffmpeg -y -i "${file}.${currentExtention}" -lossless 0 -frames:v 1 -r 1 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_ogw_static.webp" -vf scale=1000:-1 -lossless 0 -frames:v 1 -r 1 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_1000w_static.webp" -vf scale=800:-1 -lossless 0 -frames:v 1 -r 1 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_800w_static.webp" -vf scale=500:-1 -lossless 0 -frames:v 1 -r 1 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_500w_static.webp" -vf scale=320:-1 -lossless 0 -frames:v 1 -r 1 -quality 85 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_320w_static.webp" -vf scale=-1:64,gblur=sigma=10:steps=2 -lossless 0 -frames:v 1 -r 1 -compression_level 6 -quality 85 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_placeholder_static.webp"`) - exec(`start ffmpeg -y -i "${file}.${currentExtention}" -lossless 0 -quality 85 -loop 0 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_ogw.webp" -vf scale=1000:-1 -lossless 0 -quality 85 -loop 0 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_1000w.webp" -vf scale=800:-1 -lossless 0 -quality 85 -loop 0 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_800w.webp" -vf scale=500:-1 -lossless 0 -quality 85 -loop 0 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_500w.webp" -vf scale=320:-1 -lossless 0 -quality 85 -loop 0 -compression_level 6 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_320w.webp" -vf scale=-1:64,gblur=sigma=10:steps=2 -frames:v 1 -lossless 0 -c:v libwebp -compression_level 6 -quality 85 -metadata author="Djkáťo" -metadata copyright="https://djkato.net" "${file}_placeholder.webp"`) -} -function generate_new_sounds_ogg(file, currentExtention) { - const path = file.substring(0, file.lastIndexOf("\\")) - file = file.substring(file.lastIndexOf("\\") + 1) - - let command = "" - command += `cd "${path}" && start cmd /k "` - command += `ffmpeg -y -i "${file}.${currentExtention}" ` - command += `-c:a libopus -b:a 96k "${file}.ogg"` - command += ` && exit"` - exec(command) - // console.log(command) -} -function generate_new_sounds_mp3(file, currentExtention) { - const path = file.substring(0, file.lastIndexOf("\\")) - file = file.substring(file.lastIndexOf("\\") + 1) - - let command = "" - command += `cd "${path}" && start cmd /k "` - command += `ffmpeg -y -i "${file}.${currentExtention}" ` - command += `-b:a 160k "${file}.mp3"` - command += ` && exit"` - exec(command) - // console.log(command) -} -function generateNewVideoSizes(file, currentExtention, width_resolutions) { - const path = file.substring(0, file.lastIndexOf("\\")) - file = file.substring(file.lastIndexOf("\\") + 1) - - let command = "" - command += `cd "${path}" && ` - command += `del ffmpeg2pass-0.log && ` - command += `ffmpeg -y -i "${file}.${currentExtention}" ` - command += `-vcodec libvpx-vp9 -cpu-used 0 -deadline good -quality good -g 240 -crf 42 -b:v 0 -c:a libopus -row-mt 1 -tile-rows 2 -tile-columns 4 -threads 16 -auto-alt-ref 6 ` - command += `-pass 1 -f webm NUL && exit` - - exec(command).once("exit", () => { - for (const resolution of width_resolutions) { - let res_command = "" - res_command += `start cmd /k "` - res_command += `cd "${path}" && ` - res_command += `ffmpeg -y -i "${file}.${currentExtention}" ` - res_command += `-vcodec libvpx-vp9 -cpu-used 0 -deadline good -quality good -g 240 -vf scale=${resolution}:-1 -crf 42 -b:v 0 -c:a libopus -row-mt 1 -tile-rows 2 -tile-columns 4 -threads 16 -auto-alt-ref 6 -pass 2 "${file}_${resolution}p.webm"` - res_command += "&& exit\"" - exec(res_command) - } - }) -} -let dirs = filehound.create() - .path("../public/samples") - .directory() - .findSync() -console.log(dirs) - -for (let i = 0; i < dirs.length; i++) { - //gets current name file+ext - let current_folder_files = filehound.create() - .path(`${dirs[i]}`) - .findSync() - - if (current_folder_files[0] != undefined) { - //if previous encode was cancelled and 2pass log not removed, remove it :) - if (current_folder_files[0].includes("ffmpeg2pass-0.log")) { - try { unlinkSync(`${dirs[i]}/ffmpeg2pass-0.log`) } catch (err) { } - current_folder_files = current_folder_files.slice(1) - } - for (let current_media of current_folder_files) { - current_media = [current_media.substring(0, current_media.lastIndexOf(".")), current_media.substring(current_media.lastIndexOf(".") + 1)] - if (current_media[1] == "wav") { - console.log(`${current_media[0]}.${current_media[1]}\n`) - - generate_new_sounds_ogg(`${current_media[0]}`, `${current_media[1]}`) - generate_new_sounds_mp3(`${current_media[0]}`, `${current_media[1]}`) - } - continue - if (current_media[1] == "png" || current_media[1] == "jpg") { - console.log(`.\\${current_media[0]}.${current_media[1]}\n`) - - generate_new_photo_sizes(`.\\${current_media[0]}`, `${current_media[1]}`) - } - else if (current_media[1] == "gif") { - console.log(`.\\${current_media[0]}.${current_media[1]}\n`) - - generate_new_anim_photo_sizes(`.\\${current_media[0]}`, `${current_media[1]}`) - } - else if (current_media[1] == "webm" || current_media[1] == "mov" || current_media[1] == "avi" || current_media[1] == "mp4") { - console.log(`Video: ${current_media[0]}.${current_media[1]}\n`) - - generateNewVideoSizes(`${current_media[0]}`, `${current_media[1]}`, [2560, 1080, 720, 480]) - - } - } - } -} - - - diff --git a/packages/preprocessor/src/songs_list.ts b/packages/preprocessor/src/songs_list.ts deleted file mode 100644 index df3ec20..0000000 --- a/packages/preprocessor/src/songs_list.ts +++ /dev/null @@ -1 +0,0 @@ -export const songs = ["..\\public\\samples\\bass\\01 HTS Arpeggiated Bass.ogg","..\\public\\samples\\bass\\02 HTS Hardtrance Bass.ogg","..\\public\\samples\\bass\\03 HTS Break Bass.ogg","..\\public\\samples\\bass\\04 HTS Sub Bass.ogg","..\\public\\samples\\drums\\01 HTS Rides and Hats.ogg","..\\public\\samples\\drums\\02 HTS Claps and Hats.ogg","..\\public\\samples\\drums\\03 HTS Club Snares.ogg","..\\public\\samples\\drums\\04 HTS Buildup Snares.ogg","..\\public\\samples\\FX\\01 HTS Boom Kicks.ogg","..\\public\\samples\\FX\\02 HTS Verbclaps.ogg","..\\public\\samples\\FX\\03 HTS Noisesweep.ogg","..\\public\\samples\\FX\\04 HTS Combined FX.ogg","..\\public\\samples\\kicks\\01 HTS Trancekick.ogg","..\\public\\samples\\kicks\\02 HTS Sizzle Layer.ogg","..\\public\\samples\\kicks\\03 HTS Transients.ogg","..\\public\\samples\\kicks\\04 HTS Kick Combined.ogg","..\\public\\samples\\loops\\01 HTS Closed Hat Loop.ogg","..\\public\\samples\\loops\\02 HTS Open Hat Loop.ogg","..\\public\\samples\\loops\\03 HTS Perc Loop.ogg","..\\public\\samples\\loops\\04 HTS Full Loop.ogg","..\\public\\samples\\synths\\01 HTS Pluck Leads and Arp Bass.ogg","..\\public\\samples\\synths\\02 HTS Arp Leads and Saw Pads.ogg","..\\public\\samples\\synths\\03 HTS Pluck Leads and Break Bass.ogg","..\\public\\samples\\synths\\04 HTS Saw Leads and String Pads.ogg"] \ No newline at end of file diff --git a/packages/preprocessor/src/vite-env.d.ts b/packages/preprocessor/src/vite-env.d.ts deleted file mode 100644 index 11f02fe..0000000 --- a/packages/preprocessor/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/packages/preprocessor/tsconfig.json b/packages/preprocessor/tsconfig.json index 6068edb..e3c4370 100644 --- a/packages/preprocessor/tsconfig.json +++ b/packages/preprocessor/tsconfig.json @@ -1,30 +1,30 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": [ - "ESNext", - "DOM" - ], - "moduleResolution": "Node", - "strict": true, - "resolveJsonModule": true, - "isolatedModules": true, - "esModuleInterop": true, - "noEmit": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "skipLibCheck": true, - "types": [ - "vite/client" - ] - }, - "include": [ - "src", - "src/media_process.js" - ] -} \ No newline at end of file + "compilerOptions": { + "esModuleInterop": true, + "jsxImportSource": "hono/jsx", + "jsx": "react-jsx", + "lib": [ + "ESNext" + ], + "module": "esnext", + "target": "esnext", + "moduleResolution": "bundler", + "moduleDetection": "force", + "allowImportingTsExtensions": true, + "noEmit": true, + "composite": true, + "strict": true, + "downlevelIteration": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "allowJs": true, + "types": [ + "bun-types" // add Bun global + ], + "include": [ + "src", + "src/media_process.js" + ] + } +} diff --git a/packages/preprocessor/vite.config.ts b/packages/preprocessor/vite.config.ts deleted file mode 100644 index e608aa4..0000000 --- a/packages/preprocessor/vite.config.ts +++ /dev/null @@ -1,33 +0,0 @@ -/// -import { defineConfig } from "vite" - -import viteTsConfigPaths from "vite-tsconfig-paths" - -export default defineConfig({ - cacheDir: "../../node_modules/.vite/preprocessor", - - server: { - port: 4201, - host: "localhost" - }, - - preview: { - port: 4300, - host: "localhost" - }, - - plugins: [ - viteTsConfigPaths({ - root: "." - }) - ] - - // Uncomment this if you are using workers. - // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '../../', - // }), - // ], - // }, -})