Add resonance and result sound effects

This commit is contained in:
2026-06-24 17:11:02 +09:00
parent 3eda3e8d14
commit 8c446f8948
7 changed files with 73 additions and 14 deletions

View File

@@ -1,8 +1,8 @@
import { mkdir, writeFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { join } from 'node:path';
const sampleRate = 44100;
const outputPath = join('src', 'assets', 'audio', 'sfx', 'level-up.wav');
const outputDir = join('src', 'assets', 'audio', 'sfx');
function envelope(time, start, duration) {
const local = time - start;
@@ -10,7 +10,7 @@ function envelope(time, start, duration) {
return 0;
}
const attack = 0.018;
const release = 0.22;
const release = Math.min(0.24, duration * 0.42);
if (local < attack) {
return local / attack;
}
@@ -29,10 +29,17 @@ function tone(time, frequency, start, duration, gain, wave = 'sine') {
if (wave === 'triangle') {
return amp * (2 / Math.PI) * Math.asin(Math.sin(phase));
}
if (wave === 'square') {
return amp * Math.sign(Math.sin(phase));
}
return amp * Math.sin(phase);
}
function sampleAt(time) {
function clamp(sample) {
return Math.max(-0.92, Math.min(0.92, sample));
}
function levelUpSample(time) {
const notes = [
{ start: 0, frequency: 523.25, gain: 0.22, duration: 0.52 },
{ start: 0.09, frequency: 659.25, gain: 0.2, duration: 0.56 },
@@ -44,7 +51,44 @@ function sampleAt(time) {
const shimmer =
tone(time, 1318.51, 0.42, 0.36, 0.055, 'triangle') +
tone(time, 1567.98, 0.52, 0.28, 0.042, 'triangle');
return Math.max(-0.92, Math.min(0.92, chord + shimmer));
return clamp(chord + shimmer);
}
function bondResonanceSample(time) {
const pulse =
tone(time, 392, 0, 0.34, 0.1, 'triangle') +
tone(time, 587.33, 0.04, 0.42, 0.13, 'triangle') +
tone(time, 783.99, 0.1, 0.42, 0.11, 'sine') +
tone(time, 1174.66, 0.2, 0.38, 0.065, 'sine');
const sparkle =
tone(time, 1567.98, 0.34, 0.24, 0.045, 'triangle') +
tone(time, 1760, 0.42, 0.2, 0.035, 'triangle');
const tremolo = 1 + Math.sin(time * Math.PI * 18) * 0.08;
return clamp((pulse + sparkle) * tremolo);
}
function victoryFanfareSample(time) {
const brass =
tone(time, 392, 0, 0.26, 0.14, 'triangle') +
tone(time, 493.88, 0.16, 0.26, 0.14, 'triangle') +
tone(time, 587.33, 0.32, 0.28, 0.14, 'triangle') +
tone(time, 783.99, 0.5, 0.58, 0.16, 'triangle');
const harmony =
tone(time, 196, 0, 0.92, 0.07, 'sine') +
tone(time, 293.66, 0.5, 0.64, 0.06, 'sine') +
tone(time, 987.77, 0.72, 0.34, 0.055, 'sine');
return clamp(brass + harmony);
}
function defeatStingSample(time) {
const low =
tone(time, 174.61, 0, 0.46, 0.16, 'triangle') +
tone(time, 146.83, 0.24, 0.52, 0.15, 'triangle') +
tone(time, 110, 0.48, 0.56, 0.15, 'sine');
const strike =
tone(time, 87.31, 0, 0.18, 0.13, 'square') +
tone(time, 261.63, 0.02, 0.16, 0.06, 'triangle');
return clamp(low + strike);
}
function wavBuffer(samples) {
@@ -71,8 +115,17 @@ function wavBuffer(samples) {
return buffer;
}
await mkdir(dirname(outputPath), { recursive: true });
const duration = 1.12;
const samples = Array.from({ length: Math.floor(sampleRate * duration) }, (_, index) => sampleAt(index / sampleRate));
await writeFile(outputPath, wavBuffer(samples));
console.log(`Generated ${outputPath}`);
const clips = [
{ name: 'level-up', duration: 1.12, sampleAt: levelUpSample },
{ name: 'bond-resonance', duration: 0.82, sampleAt: bondResonanceSample },
{ name: 'victory-fanfare', duration: 1.2, sampleAt: victoryFanfareSample },
{ name: 'defeat-sting', duration: 1.08, sampleAt: defeatStingSample }
];
await mkdir(outputDir, { recursive: true });
for (const clip of clips) {
const samples = Array.from({ length: Math.floor(sampleRate * clip.duration) }, (_, index) => clip.sampleAt(index / sampleRate));
const outputPath = join(outputDir, `${clip.name}.wav`);
await writeFile(outputPath, wavBuffer(samples));
console.log(`Generated ${outputPath}`);
}