From 83a50dc22aaadfc26df9a3d403db380789ff5f9c Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sat, 13 Jul 2024 17:16:18 +0300 Subject: [PATCH] bytebeat-render.js: fix visibility scope --- js-programming/bytebeat-render.js | 241 +++++++++++++++--------------- 1 file changed, 124 insertions(+), 117 deletions(-) diff --git a/js-programming/bytebeat-render.js b/js-programming/bytebeat-render.js index d0db6d3..8c30451 100644 --- a/js-programming/bytebeat-render.js +++ b/js-programming/bytebeat-render.js @@ -18,138 +18,145 @@ * License: Creative Commons Zero 1.0 Universal */ -const { appendFileSync, unlinkSync, writeFileSync } = require("fs") -const { tmpdir } = require("os") -const { execSync } = require("child_process") -const { basename } = require("path") - -let BUFFER_SIZE = 65536 // feel free to change this -const LIGHTNING_MODE = false // disables sequential file write optimization, -// feel free to enable this - -const SAMPLE_RATE = 8000 // feel free to change this -const SECONDS = 30 // feel free to change this -const CHANNELS = 1 // feel free to change this - -const FINAL_SAMPLE_RATE = 44100 // feel free to change this -const FINAL_SAMPLE_RATE_CONVERSION = SAMPLE_RATE / FINAL_SAMPLE_RATE / CHANNELS -const SAMPLES = SECONDS * FINAL_SAMPLE_RATE // feel free to change this -const PRODUCT = SAMPLES * CHANNELS -BUFFER_SIZE = LIGHTNING_MODE ? PRODUCT : BUFFER_SIZE - -const TYPE_BYTEBEAT = 0 -const TYPE_SIGNED_BYTEBEAT = 1 -const TYPE_FLOATBEAT = 2 - -const SELECTED_TYPE = TYPE_BYTEBEAT // feel free to change this - -// for bytebeat -var int = x => Math.floor(x) -var abs = Math.abs -var acos = Math.acos -var acosh = Math.acosh -var asin = Math.asin -var asinh = Math.asinh -var atan = Math.atan -var atanh = Math.atanh -var cbrt = Math.cbrt -var cos = Math.cos -var cosh = Math.cosh -var exp = Math.exp -var floor = Math.floor -var log = Math.log -var log2 = Math.log2 -var max = Math.max -var min = Math.min -var PI = Math.PI -var pow = Math.pow -var random = Math.random -var sin = Math.sin -var sinh = Math.sinh -var sqrt = Math.sqrt -var tan = Math.tan -var tanh = Math.tanh - const generateAudio = t => { + // for bytebeat + var int = x => Math.floor(x) + var abs = Math.abs + var acos = Math.acos + var acosh = Math.acosh + var asin = Math.asin + var asinh = Math.asinh + var atan = Math.atan + var atanh = Math.atanh + var cbrt = Math.cbrt + var cos = Math.cos + var cosh = Math.cosh + var exp = Math.exp + var floor = Math.floor + var log = Math.log + var log2 = Math.log2 + var max = Math.max + var min = Math.min + var PI = Math.PI + var pow = Math.pow + var random = Math.random + var sin = Math.sin + var sinh = Math.sinh + var sqrt = Math.sqrt + var tan = Math.tan + var tanh = Math.tanh + return t&t>>8 } -const clamp = (a, b, c) => max(min(a, c), b) +function main() { + const { appendFileSync, unlinkSync, writeFileSync } = require("fs") + const { tmpdir } = require("os") + const { execSync } = require("child_process") + const { basename } = require("path") -let lastCorrectSample -switch (SELECTED_TYPE) { -case TYPE_BYTEBEAT: - lastCorrectSample = 127 - break; -case TYPE_SIGNED_BYTEBEAT: - lastCorrectSample = 0 - break; -case TYPE_FLOATBEAT: - lastCorrectSample = 0.0 - break; -} + let BUFFER_SIZE = 65536 // feel free to change this + const LIGHTNING_MODE = false // disables sequential file write optimization, + // feel free to enable this -const constrainValue = sample => { - if (isNaN(sample) || sample < 0) - sample = lastCorrectSample - else - lastCorrectSample = sample + const SAMPLE_RATE = 8000 // feel free to change this + const SECONDS = 30 // feel free to change this + const CHANNELS = 1 // feel free to change this + const FINAL_SAMPLE_RATE = 44100 // feel free to change this + const FINAL_SAMPLE_RATE_CONVERSION = SAMPLE_RATE / FINAL_SAMPLE_RATE / + CHANNELS + const SAMPLES = SECONDS * FINAL_SAMPLE_RATE // feel free to change this + const PRODUCT = SAMPLES * CHANNELS + BUFFER_SIZE = LIGHTNING_MODE ? PRODUCT : BUFFER_SIZE + + const TYPE_BYTEBEAT = 0 + const TYPE_SIGNED_BYTEBEAT = 1 + const TYPE_FLOATBEAT = 2 + + const SELECTED_TYPE = TYPE_BYTEBEAT // feel free to change this + + const clamp = (a, b, c) => max(min(a, c), b) + + let lastCorrectSample switch (SELECTED_TYPE) { case TYPE_BYTEBEAT: - return sample & 255 + lastCorrectSample = 127 + break case TYPE_SIGNED_BYTEBEAT: - return ((sample + 127) & 255) - 128 + lastCorrectSample = 0 + break case TYPE_FLOATBEAT: - // NOTE: temporary fix copied from a code by lehandsomeguy, see https:// - // www.reddit.com/r/bytebeat/comments/48r00a/floatbeat_test/ - return floor((clamp(sample, -0.9999, 0.9999) * 128) + 128) - } -} - -const random_choice = choices => choices[Math.floor(Math.random() * choices.length)] - -const randomFileNameAlphabet = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-" - -const generateRandomFilePath = () => { - let res = tmpdir() + "/" + basename(__filename) + "_" - for (let i = 0; i < 64; i++) - res += random_choice(randomFileNameAlphabet) - return res -} - -let t = 0 - -let filePath = generateRandomFilePath() -writeFileSync(filePath, Buffer.alloc(0)) - -// the loop of sequential file writing, created to ease load on RAM -const buffer_max = Math.floor((PRODUCT + (BUFFER_SIZE - 1)) / BUFFER_SIZE), - needTwoBuffers = buffer_max > 1, needSingleBuffer = !needTwoBuffers - -let audioData = new Uint8Array(needSingleBuffer ? PRODUCT : BUFFER_SIZE) - -for (let seq = 0; seq < buffer_max; seq++) { - if (needTwoBuffers && (t + BUFFER_SIZE) >= PRODUCT) { - let calculatedSize = PRODUCT - t - audioData = new Uint8Array(calculatedSize) + lastCorrectSample = 0.0 + break } - for (let idx = 0; t < PRODUCT && idx < BUFFER_SIZE; idx++, t++) { - let sample = generateAudio(t * FINAL_SAMPLE_RATE_CONVERSION) - if (sample.constructor === Array) - sample.forEach((sample, index) => { - audioData[CHANNELS * idx + index] = constrainValue(sample) - }) + const constrainValue = sample => { + if (isNaN(sample) || sample < 0) + sample = lastCorrectSample else - audioData[idx] = constrainValue(sample) + lastCorrectSample = sample + + switch (SELECTED_TYPE) { + case TYPE_BYTEBEAT: + return sample & 255 + case TYPE_SIGNED_BYTEBEAT: + return ((sample + 127) & 255) - 128 + case TYPE_FLOATBEAT: + // NOTE: temporary fix copied from a code by lehandsomeguy, see + // https://www.reddit.com/r/bytebeat/comments/48r00a/floatbeat_test/ + return floor((clamp(sample, -0.9999, 0.9999) * 128) + 128) + } } - appendFileSync(filePath, Buffer.from(audioData.buffer)) + const random_choice = choices => choices[Math.floor(Math.random() * + choices.length)] + + const randomFileNameAlphabet = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-" + + const generateRandomFilePath = () => { + let res = tmpdir() + "/" + basename(__filename) + "_" + for (let i = 0; i < 64; i++) + res += random_choice(randomFileNameAlphabet) + return res + } + + let filePath = generateRandomFilePath() + writeFileSync(filePath, Buffer.alloc(0)) + + // the loop of sequential file writing, created to ease load on RAM + const buffer_max = Math.floor((PRODUCT + (BUFFER_SIZE - 1)) / BUFFER_SIZE), + needTwoBuffers = buffer_max > 1, needSingleBuffer = !needTwoBuffers + + let audioData = new Uint8Array(needSingleBuffer ? PRODUCT : BUFFER_SIZE) + + let t = 0 + + for (let seq = 0; seq < buffer_max; seq++) { + if (needTwoBuffers && (t + BUFFER_SIZE) >= PRODUCT) { + let calculatedSize = PRODUCT - t + audioData = new Uint8Array(calculatedSize) + } + + for (let idx = 0; t < PRODUCT && idx < BUFFER_SIZE; idx++, t++) { + let sample = generateAudio(t * FINAL_SAMPLE_RATE_CONVERSION) + if (sample.constructor === Array) + sample.forEach((sample, index) => { + audioData[CHANNELS * idx + index] = constrainValue(sample) + }) + else + audioData[idx] = constrainValue(sample) + } + + appendFileSync(filePath, Buffer.from(audioData.buffer)) + } + + execSync( + `ffmpeg -f u8 -ar ${FINAL_SAMPLE_RATE} -ac ${CHANNELS} ` + + `-i ${filePath} output_${+new Date()}.wav`) + unlinkSync(filePath) } -execSync( - `ffmpeg -f u8 -ar ${FINAL_SAMPLE_RATE} -ac ${CHANNELS} ` + - `-i ${filePath} output_${+new Date()}.wav`) -unlinkSync(filePath) +if (require.main === module) + main()