vibeaudio 0.6.1 → 0.6.2
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/package.json +1 -1
- package/src/synth/chiptune.js +32 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeaudio",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Procedural focus music while your AI coding tools (Claude Code, Codex, Cursor, Grok, Gemini, Copilot) think \u2014 a different arrangement per project.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"vibeaudio": "bin/vibeaudio.js",
|
package/src/synth/chiptune.js
CHANGED
|
@@ -64,16 +64,26 @@ function generateChiptuneLoop(durationSec = 7.5, tier = 2, seed = 0) {
|
|
|
64
64
|
const startIdx = Math.floor(m.start * secPerBeat * SAMPLE_RATE);
|
|
65
65
|
const numSamples = Math.floor(m.dur * secPerBeat * SAMPLE_RATE);
|
|
66
66
|
|
|
67
|
+
// Accumulated, for the same reason as the arpeggio below, plus one of its
|
|
68
|
+
// own: `softPulse((f + vib) * t)` is not vibrato but a phase that jumps
|
|
69
|
+
// when the vibrato switches on at t > 0.15 - by (vib * 0.15) cycles, once
|
|
70
|
+
// per note. Accumulating makes `vib` an actual frequency deviation of
|
|
71
|
+
// +/-3.5Hz, which is what it was meant to be, and the switch-on changes
|
|
72
|
+
// only the rate.
|
|
73
|
+
let leadPhase = 0.0;
|
|
74
|
+
|
|
67
75
|
for (let i = 0; i < numSamples; i++) {
|
|
68
76
|
const idx = startIdx + i;
|
|
69
77
|
if (idx >= totalSamples) break;
|
|
70
78
|
const t = i / SAMPLE_RATE;
|
|
71
79
|
const env = Math.min(1.0, t * 75.0) * Math.max(0.0, 1.0 - (t / (m.dur * secPerBeat)));
|
|
72
80
|
const vib = t > 0.15 ? Math.sin(2 * Math.PI * 5.5 * t) * 3.5 : 0.0;
|
|
73
|
-
const sample = softPulse(
|
|
81
|
+
const sample = softPulse(leadPhase) * env * 0.22;
|
|
74
82
|
|
|
75
83
|
left[idx] += sample;
|
|
76
84
|
right[idx] += sample;
|
|
85
|
+
|
|
86
|
+
leadPhase += (f + vib) / SAMPLE_RATE;
|
|
77
87
|
}
|
|
78
88
|
}
|
|
79
89
|
|
|
@@ -81,6 +91,22 @@ function generateChiptuneLoop(durationSec = 7.5, tier = 2, seed = 0) {
|
|
|
81
91
|
const chords = variant.chords;
|
|
82
92
|
const arpSpeed = 0.075;
|
|
83
93
|
|
|
94
|
+
// The phase is accumulated, not computed as `f * t`.
|
|
95
|
+
//
|
|
96
|
+
// This arpeggio steps to a new note every 75ms and has no envelope at all -
|
|
97
|
+
// it is meant to run continuously. With `softPulse(f * t)`, changing f while
|
|
98
|
+
// t keeps running jumps the phase by (f2 - f1) * t: hundreds of cycles a few
|
|
99
|
+
// seconds in, which lands the waveform on an arbitrary value. That is a
|
|
100
|
+
// click, 13 times a second, with no envelope to hide it - reported as static
|
|
101
|
+
// on 8bit, and at tier 1 every single step over 0.05 full-scale landed
|
|
102
|
+
// exactly on one of these boundaries.
|
|
103
|
+
//
|
|
104
|
+
// Accumulating instead means a new note changes the *rate* the phase
|
|
105
|
+
// advances, never its value, so the waveform stays continuous across the
|
|
106
|
+
// step. It is also how a real oscillator behaves.
|
|
107
|
+
let arpPhase = 0.0;
|
|
108
|
+
let shimmerPhase = 0.0;
|
|
109
|
+
|
|
84
110
|
for (let i = 0; i < totalSamples; i++) {
|
|
85
111
|
const t = i / SAMPLE_RATE;
|
|
86
112
|
const beat = Math.floor(t / secPerBeat);
|
|
@@ -88,17 +114,20 @@ function generateChiptuneLoop(durationSec = 7.5, tier = 2, seed = 0) {
|
|
|
88
114
|
const chord = chords[chordIdx];
|
|
89
115
|
const noteIdx = Math.floor(t / arpSpeed) % chord.length;
|
|
90
116
|
const f = noteToFreq(chord[noteIdx]);
|
|
91
|
-
const sample = softPulse(
|
|
117
|
+
const sample = softPulse(arpPhase) * (tier === 1 ? 0.09 : 0.075);
|
|
92
118
|
|
|
93
119
|
left[i] += sample * 0.85;
|
|
94
120
|
right[i] += sample * 0.85;
|
|
95
121
|
|
|
96
122
|
// Tier 3: octave-up shimmer arpeggio doubling
|
|
97
123
|
if (tier >= 3) {
|
|
98
|
-
const shimmer = softPulse(
|
|
124
|
+
const shimmer = softPulse(shimmerPhase) * 0.03;
|
|
99
125
|
left[i] += shimmer * 1.1;
|
|
100
126
|
right[i] += shimmer * 0.9;
|
|
101
127
|
}
|
|
128
|
+
|
|
129
|
+
arpPhase += f / SAMPLE_RATE;
|
|
130
|
+
shimmerPhase += (f * 2.0) / SAMPLE_RATE;
|
|
102
131
|
}
|
|
103
132
|
|
|
104
133
|
// 3. NES Triangle Bass
|