mirror of
https://gitlab.com/80486DX2-66/gists
synced 2024-11-08 18:02:23 +05:30
add js-programming/bytebeat-render.js
This commit is contained in:
parent
021333aca6
commit
1606eb57d2
113
js-programming/bytebeat-render.js
Normal file
113
js-programming/bytebeat-render.js
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
Node.JS: Bytebeat generator
|
||||
|
||||
Note: Calls `ffmpeg` to convert output raw audio to a WAVE file
|
||||
|
||||
Warning: The current result is quick and dirty. Not for educational or
|
||||
production purposes.
|
||||
|
||||
To-Do: Fix signed bytebeat and floatbeat
|
||||
To-Do: (cosmetic) Wrap the code before 81th column
|
||||
*/
|
||||
|
||||
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 change 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
|
||||
const int = x => Math.floor(x)
|
||||
const abs = Math.abs
|
||||
const cbrt = Math.cbrt
|
||||
const cos = Math.cos
|
||||
const cosh = Math.cosh
|
||||
const floor = Math.floor
|
||||
const log = Math.log
|
||||
const log2 = Math.log2
|
||||
const PI = Math.PI
|
||||
const pow = Math.pow
|
||||
const random = Math.random
|
||||
const sin = Math.sin
|
||||
const sinh = Math.sinh
|
||||
const sqrt = Math.sqrt
|
||||
const tan = Math.tan
|
||||
const tanh = Math.tanh
|
||||
|
||||
const generateAudio = t => {
|
||||
t *= FINAL_SAMPLE_RATE_CONVERSION
|
||||
return t&t>>8
|
||||
}
|
||||
|
||||
const constrainValue = sample => {
|
||||
switch (SELECTED_TYPE) {
|
||||
case TYPE_BYTEBEAT:
|
||||
return sample & 255
|
||||
case TYPE_SIGNED_BYTEBEAT:
|
||||
return ((sample + 127) & 255) - 128
|
||||
case TYPE_FLOATBEAT:
|
||||
return floor(sample * 127) + 127
|
||||
}
|
||||
}
|
||||
|
||||
const random_choice = choices => choices[Math.floor(Math.random() * choices.length)]
|
||||
|
||||
const randomFileNameAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"
|
||||
|
||||
const generateRandomFileName = () => {
|
||||
let res = tmpdir() + "/" + basename(__filename) + "_"
|
||||
for (let i = 0; i < 64; i++)
|
||||
res += random_choice(randomFileNameAlphabet)
|
||||
return res
|
||||
}
|
||||
|
||||
let t = 0
|
||||
|
||||
let fileName = generateRandomFileName()
|
||||
writeFileSync(fileName, Buffer.alloc(0))
|
||||
|
||||
// the loop of sequential file writing, created to ease load on RAM
|
||||
for (let buffer = 0; t < PRODUCT; buffer++) {
|
||||
let audioData = new Uint8Array(BUFFER_SIZE)
|
||||
|
||||
let idx = 0
|
||||
for (; idx < BUFFER_SIZE && t < PRODUCT; idx++) {
|
||||
let sample = generateAudio(t)
|
||||
if (sample.constructor === Array)
|
||||
sample.forEach((sample, index) => {
|
||||
audioData[CHANNELS * idx + index] = constrainValue(sample);
|
||||
})
|
||||
else
|
||||
audioData[idx] = constrainValue(sample);
|
||||
t++;
|
||||
}
|
||||
|
||||
if (t >= PRODUCT) {
|
||||
let truncatedArray = new Uint8Array(idx)
|
||||
truncatedArray.set(audioData.subarray(0, idx))
|
||||
audioData = truncatedArray
|
||||
}
|
||||
|
||||
appendFileSync(fileName, Buffer.from(audioData.buffer))
|
||||
}
|
||||
|
||||
execSync(`ffmpeg -f u8 -ar ${FINAL_SAMPLE_RATE} -ac ${CHANNELS} -i ${fileName} output_${+new Date()}.wav -y`)
|
||||
unlinkSync(fileName)
|
Loading…
Reference in New Issue
Block a user