@igggy/waveform 0.1.0
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/README.md +5 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/renderer.d.ts +82 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +314 -0
- package/dist/renderer.js.map +1 -0
- package/package.json +27 -0
package/README.md
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WaveformRenderer = void 0;
|
|
4
|
+
var renderer_1 = require("./renderer");
|
|
5
|
+
Object.defineProperty(exports, "WaveformRenderer", { enumerable: true, get: function () { return renderer_1.WaveformRenderer; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uCAA6C;AAApC,4GAAA,gBAAgB,OAAA"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @igggy/waveform — shared waveform renderer
|
|
3
|
+
*
|
|
4
|
+
* Pure canvas drawing logic for recording and processing states.
|
|
5
|
+
* No framework dependencies — works with React refs, vanilla DOM, or any
|
|
6
|
+
* platform that provides a CanvasRenderingContext2D.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const renderer = new WaveformRenderer({ accentColor: '#6366f1' })
|
|
10
|
+
* // In your rAF loop:
|
|
11
|
+
* renderer.drawRecording(ctx, width, height, freqData)
|
|
12
|
+
* // or:
|
|
13
|
+
* renderer.drawProcessing(ctx, width, height)
|
|
14
|
+
* // On cleanup:
|
|
15
|
+
* renderer.reset()
|
|
16
|
+
*/
|
|
17
|
+
export interface WaveformConfig {
|
|
18
|
+
/** Accent color for bars. Default: '#6366f1' (indigo-500) */
|
|
19
|
+
accentColor?: string;
|
|
20
|
+
/** Canvas height in px. Default: 36 */
|
|
21
|
+
canvasHeight?: number;
|
|
22
|
+
/** Silence threshold (0–255). Default: 5 */
|
|
23
|
+
silenceThreshold?: number;
|
|
24
|
+
}
|
|
25
|
+
export declare class WaveformRenderer {
|
|
26
|
+
private accentColor;
|
|
27
|
+
private canvasHeight;
|
|
28
|
+
private silenceThreshold;
|
|
29
|
+
private smoothedHeights;
|
|
30
|
+
private barSeeds;
|
|
31
|
+
private lastBarCount;
|
|
32
|
+
constructor(config?: WaveformConfig);
|
|
33
|
+
/** Update accent color (e.g. when theme changes) */
|
|
34
|
+
setAccentColor(color: string): void;
|
|
35
|
+
/** Clear all internal state */
|
|
36
|
+
reset(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Draw the recording waveform. Uses a multi-peak envelope driven by
|
|
39
|
+
* audio energy for a natural, distributed look.
|
|
40
|
+
*
|
|
41
|
+
* @param ctx Canvas 2D context
|
|
42
|
+
* @param width Canvas width in px
|
|
43
|
+
* @param height Canvas height in px
|
|
44
|
+
* @param freqData Frequency data from AnalyserNode.getByteFrequencyData()
|
|
45
|
+
* @returns Whether silence was detected (for silence warnings)
|
|
46
|
+
*/
|
|
47
|
+
drawRecording(ctx: CanvasRenderingContext2D, width: number, height: number, freqData: Uint8Array): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Draw the processing waveform. A rolling wave sweeps left-to-right
|
|
50
|
+
* with a distinct crest, bars rising and falling as it passes.
|
|
51
|
+
* Brightness tracks the crest. A calm period follows before the
|
|
52
|
+
* next wave rolls through.
|
|
53
|
+
*
|
|
54
|
+
* Cycle: ~4.5s total. ~3s for the wave to sweep, ~1.5s calm.
|
|
55
|
+
*
|
|
56
|
+
* @param ctx Canvas 2D context
|
|
57
|
+
* @param width Canvas width in px
|
|
58
|
+
* @param height Canvas height in px
|
|
59
|
+
*/
|
|
60
|
+
drawProcessing(ctx: CanvasRenderingContext2D, width: number, height: number): void;
|
|
61
|
+
/**
|
|
62
|
+
* Draw a continuous scrolling wave pattern. Multiple peaks and valleys
|
|
63
|
+
* are always visible, scrolling left-to-right like ocean waves.
|
|
64
|
+
* All bars stay active at varying heights — no dead periods.
|
|
65
|
+
*
|
|
66
|
+
* @param ctx Canvas 2D context
|
|
67
|
+
* @param width Canvas width in px
|
|
68
|
+
* @param height Canvas height in px
|
|
69
|
+
*/
|
|
70
|
+
drawProcessingB(ctx: CanvasRenderingContext2D, width: number, height: number): void;
|
|
71
|
+
/**
|
|
72
|
+
* Draw the paused waveform. Static bars with a slow brightness sweep.
|
|
73
|
+
*
|
|
74
|
+
* @param ctx Canvas 2D context
|
|
75
|
+
* @param width Canvas width in px
|
|
76
|
+
* @param height Canvas height in px
|
|
77
|
+
*/
|
|
78
|
+
drawPaused(ctx: CanvasRenderingContext2D, width: number, height: number): void;
|
|
79
|
+
/** Initialize/resize persistent state when bar count changes */
|
|
80
|
+
private ensureState;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAaH,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAqCD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,gBAAgB,CAAQ;IAGhC,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,YAAY,CAAI;gBAEZ,MAAM,CAAC,EAAE,cAAc;IAMnC,oDAAoD;IACpD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAInC,+BAA+B;IAC/B,KAAK,IAAI,IAAI;IAQb;;;;;;;;;OASG;IACH,aAAa,CACX,GAAG,EAAE,wBAAwB,EAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,UAAU,GACnB,OAAO;IAuEV;;;;;;;;;;;OAWG;IACH,cAAc,CACZ,GAAG,EAAE,wBAAwB,EAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,IAAI;IAsFP;;;;;;;;OAQG;IACH,eAAe,CACb,GAAG,EAAE,wBAAwB,EAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,IAAI;IA8DP;;;;;;OAMG;IACH,UAAU,CACR,GAAG,EAAE,wBAAwB,EAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,IAAI;IAiCP,gEAAgE;IAChE,OAAO,CAAC,WAAW;CAcpB"}
|
package/dist/renderer.js
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @igggy/waveform — shared waveform renderer
|
|
4
|
+
*
|
|
5
|
+
* Pure canvas drawing logic for recording and processing states.
|
|
6
|
+
* No framework dependencies — works with React refs, vanilla DOM, or any
|
|
7
|
+
* platform that provides a CanvasRenderingContext2D.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const renderer = new WaveformRenderer({ accentColor: '#6366f1' })
|
|
11
|
+
* // In your rAF loop:
|
|
12
|
+
* renderer.drawRecording(ctx, width, height, freqData)
|
|
13
|
+
* // or:
|
|
14
|
+
* renderer.drawProcessing(ctx, width, height)
|
|
15
|
+
* // On cleanup:
|
|
16
|
+
* renderer.reset()
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.WaveformRenderer = void 0;
|
|
20
|
+
// ── Constants ───────────────────────────────────────────────────────────────
|
|
21
|
+
const BAR_WIDTH = 3;
|
|
22
|
+
const BAR_GAP = 2;
|
|
23
|
+
const BAR_UNIT = BAR_WIDTH + BAR_GAP; // 5px per bar
|
|
24
|
+
const MIN_BAR_COUNT = 28;
|
|
25
|
+
const MIN_BAR_HEIGHT = 3;
|
|
26
|
+
const SILENCE_THRESHOLD = 5; // max bin value (0–255) below which = silence
|
|
27
|
+
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
28
|
+
/** Deterministic pseudo-random from a seed (0–1 output) */
|
|
29
|
+
function seededRandom(seed) {
|
|
30
|
+
const x = Math.sin(seed * 127.1 + 311.7) * 43758.5453;
|
|
31
|
+
return x - Math.floor(x);
|
|
32
|
+
}
|
|
33
|
+
/** Check if context supports roundRect */
|
|
34
|
+
function hasRoundRect(ctx) {
|
|
35
|
+
return typeof ctx.roundRect === 'function';
|
|
36
|
+
}
|
|
37
|
+
/** Draw a single rounded bar centered vertically */
|
|
38
|
+
function drawBar(ctx, x, height, canvasHeight, useRoundRect) {
|
|
39
|
+
const y = (canvasHeight - height) / 2;
|
|
40
|
+
ctx.beginPath();
|
|
41
|
+
if (useRoundRect) {
|
|
42
|
+
;
|
|
43
|
+
ctx.roundRect(x, y, BAR_WIDTH, height, 2);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
ctx.rect(x, y, BAR_WIDTH, height);
|
|
47
|
+
}
|
|
48
|
+
ctx.fill();
|
|
49
|
+
}
|
|
50
|
+
// ── Renderer ────────────────────────────────────────────────────────────────
|
|
51
|
+
class WaveformRenderer {
|
|
52
|
+
constructor(config) {
|
|
53
|
+
// Persistent state for smooth animations
|
|
54
|
+
this.smoothedHeights = [];
|
|
55
|
+
this.barSeeds = [];
|
|
56
|
+
this.lastBarCount = 0;
|
|
57
|
+
this.accentColor = config?.accentColor ?? '#6366f1';
|
|
58
|
+
this.canvasHeight = config?.canvasHeight ?? 36;
|
|
59
|
+
this.silenceThreshold = config?.silenceThreshold ?? SILENCE_THRESHOLD;
|
|
60
|
+
}
|
|
61
|
+
/** Update accent color (e.g. when theme changes) */
|
|
62
|
+
setAccentColor(color) {
|
|
63
|
+
this.accentColor = color;
|
|
64
|
+
}
|
|
65
|
+
/** Clear all internal state */
|
|
66
|
+
reset() {
|
|
67
|
+
this.smoothedHeights = [];
|
|
68
|
+
this.barSeeds = [];
|
|
69
|
+
this.lastBarCount = 0;
|
|
70
|
+
}
|
|
71
|
+
// ── Recording ───────────────────────────────────────────────────────────
|
|
72
|
+
/**
|
|
73
|
+
* Draw the recording waveform. Uses a multi-peak envelope driven by
|
|
74
|
+
* audio energy for a natural, distributed look.
|
|
75
|
+
*
|
|
76
|
+
* @param ctx Canvas 2D context
|
|
77
|
+
* @param width Canvas width in px
|
|
78
|
+
* @param height Canvas height in px
|
|
79
|
+
* @param freqData Frequency data from AnalyserNode.getByteFrequencyData()
|
|
80
|
+
* @returns Whether silence was detected (for silence warnings)
|
|
81
|
+
*/
|
|
82
|
+
drawRecording(ctx, width, height, freqData) {
|
|
83
|
+
const barCount = Math.max(MIN_BAR_COUNT, Math.floor(width / BAR_UNIT));
|
|
84
|
+
this.ensureState(barCount);
|
|
85
|
+
ctx.clearRect(0, 0, width, height);
|
|
86
|
+
const totalBarsWidth = barCount * BAR_UNIT;
|
|
87
|
+
const offsetX = Math.max(0, (width - totalBarsWidth) / 2);
|
|
88
|
+
const binCount = freqData.length;
|
|
89
|
+
const roundRect = hasRoundRect(ctx);
|
|
90
|
+
// Energy: RMS + peak blend for responsiveness
|
|
91
|
+
let sumSq = 0;
|
|
92
|
+
let peakVal = 0;
|
|
93
|
+
for (let b = 0; b < binCount; b++) {
|
|
94
|
+
const v = freqData[b] / 255;
|
|
95
|
+
sumSq += v * v;
|
|
96
|
+
if (v > peakVal)
|
|
97
|
+
peakVal = v;
|
|
98
|
+
}
|
|
99
|
+
const rmsEnergy = Math.sqrt(sumSq / binCount);
|
|
100
|
+
const energy = rmsEnergy * 0.6 + peakVal * 0.4;
|
|
101
|
+
ctx.fillStyle = this.accentColor;
|
|
102
|
+
// Each bar maps to a scattered frequency bin via its seed (not sequential).
|
|
103
|
+
// Sequential mapping makes a synthetic source look uniform because adjacent
|
|
104
|
+
// bins have similar values. Scattered mapping pulls from across the spectrum,
|
|
105
|
+
// giving more natural variation even with synthetic audio.
|
|
106
|
+
// Neighborhood coherence comes from the smoothing, not the bin mapping.
|
|
107
|
+
for (let i = 0; i < barCount; i++) {
|
|
108
|
+
const t = i / (barCount - 1); // 0–1 position
|
|
109
|
+
// Scattered bin mapping — each bar samples a different part of the spectrum
|
|
110
|
+
const binIndex = Math.floor(this.barSeeds[i] * binCount);
|
|
111
|
+
const bandLevel = freqData[binIndex] / 255;
|
|
112
|
+
// Wide sensitivity range so adjacent bars differ noticeably in height
|
|
113
|
+
// even when their source values are similar
|
|
114
|
+
const sensitivity = 0.2 + this.barSeeds[i] * 1.8; // 0.2–2.0x
|
|
115
|
+
// Combine band level with overall energy — boosted to compensate
|
|
116
|
+
// for center bias scaling down most bars
|
|
117
|
+
const level = bandLevel * sensitivity * energy * 5.0;
|
|
118
|
+
// Center bias: bell curve peaks at center, tapers toward edges.
|
|
119
|
+
// sin(t * PI) = 0 at edges, 1 at center. The 0.5 exponent widens
|
|
120
|
+
// the active region so the center ~60% stays energetic.
|
|
121
|
+
const centerBias = Math.pow(Math.sin(t * Math.PI), 0.5);
|
|
122
|
+
// Cap at 95% of canvas height
|
|
123
|
+
const maxBarHeight = height * 0.95;
|
|
124
|
+
const targetHeight = Math.min(maxBarHeight, Math.max(MIN_BAR_HEIGHT, level * height * centerBias));
|
|
125
|
+
// Smooth lerp — responsive enough to show movement, smooth enough
|
|
126
|
+
// to feel continuous rather than jumpy. 0.28 balances both.
|
|
127
|
+
this.smoothedHeights[i] += (targetHeight - this.smoothedHeights[i]) * 0.28;
|
|
128
|
+
drawBar(ctx, offsetX + i * BAR_UNIT, this.smoothedHeights[i], height, roundRect);
|
|
129
|
+
}
|
|
130
|
+
// Silence detection
|
|
131
|
+
let maxVal = 0;
|
|
132
|
+
for (let b = 0; b < binCount; b++) {
|
|
133
|
+
if (freqData[b] > maxVal)
|
|
134
|
+
maxVal = freqData[b];
|
|
135
|
+
}
|
|
136
|
+
return maxVal < this.silenceThreshold;
|
|
137
|
+
}
|
|
138
|
+
// ── Processing ──────────────────────────────────────────────────────────
|
|
139
|
+
/**
|
|
140
|
+
* Draw the processing waveform. A rolling wave sweeps left-to-right
|
|
141
|
+
* with a distinct crest, bars rising and falling as it passes.
|
|
142
|
+
* Brightness tracks the crest. A calm period follows before the
|
|
143
|
+
* next wave rolls through.
|
|
144
|
+
*
|
|
145
|
+
* Cycle: ~4.5s total. ~3s for the wave to sweep, ~1.5s calm.
|
|
146
|
+
*
|
|
147
|
+
* @param ctx Canvas 2D context
|
|
148
|
+
* @param width Canvas width in px
|
|
149
|
+
* @param height Canvas height in px
|
|
150
|
+
*/
|
|
151
|
+
drawProcessing(ctx, width, height) {
|
|
152
|
+
const barCount = Math.max(MIN_BAR_COUNT, Math.floor(width / BAR_UNIT));
|
|
153
|
+
this.ensureState(barCount);
|
|
154
|
+
ctx.clearRect(0, 0, width, height);
|
|
155
|
+
const totalBarsWidth = barCount * BAR_UNIT;
|
|
156
|
+
const offsetX = Math.max(0, (width - totalBarsWidth) / 2);
|
|
157
|
+
const roundRect = hasRoundRect(ctx);
|
|
158
|
+
const now = Date.now() * 0.001;
|
|
159
|
+
// ── Timing ────────────────────────────────────────────────────
|
|
160
|
+
const cycleDuration = 5.0; // full cycle in seconds
|
|
161
|
+
const cyclePhase = (now % cycleDuration) / cycleDuration;
|
|
162
|
+
// ── Wave position ───────────────────────────────────────────────
|
|
163
|
+
// Tighter offscreen range — less time invisible
|
|
164
|
+
// Smooth ease-in-out sweep across full cycle (no calm period)
|
|
165
|
+
const eased = cyclePhase < 0.5
|
|
166
|
+
? 2 * cyclePhase * cyclePhase
|
|
167
|
+
: 1 - 2 * (1 - cyclePhase) * (1 - cyclePhase);
|
|
168
|
+
const waveCenter = -0.4 + eased * 2.2;
|
|
169
|
+
// ── Wave shape: smooth rounded hill ─────────────────────────────
|
|
170
|
+
// Leading edge has a moderate slope, trailing shoulder is steeper
|
|
171
|
+
// than before for a tighter wave that doesn't linger as long
|
|
172
|
+
const leadWidth = 0.18; // leading edge width
|
|
173
|
+
const trailWidth = 0.24; // trailing shoulder
|
|
174
|
+
// Peak height: 55% of canvas — calm swell, not dramatic
|
|
175
|
+
const peakHeight = height * 0.55;
|
|
176
|
+
ctx.fillStyle = this.accentColor;
|
|
177
|
+
// Pass 1: base dots — always visible, matches paused-state brightness
|
|
178
|
+
for (let i = 0; i < barCount; i++) {
|
|
179
|
+
const t = i / (barCount - 1);
|
|
180
|
+
const edgeDist = Math.min(t, 1 - t);
|
|
181
|
+
const edgeFade = Math.min(1, edgeDist * 6);
|
|
182
|
+
ctx.globalAlpha = 0.50 * edgeFade;
|
|
183
|
+
drawBar(ctx, offsetX + i * BAR_UNIT, MIN_BAR_HEIGHT, height, roundRect);
|
|
184
|
+
}
|
|
185
|
+
// Pass 2: wave crest — adds height and brightness on top
|
|
186
|
+
for (let i = 0; i < barCount; i++) {
|
|
187
|
+
const t = i / (barCount - 1);
|
|
188
|
+
const dist = t - waveCenter;
|
|
189
|
+
// Asymmetric shape: steep leading slope, wider trailing shoulder
|
|
190
|
+
const w = dist >= 0 ? leadWidth : trailWidth;
|
|
191
|
+
// Raised cosine for smooth rounded top (not gaussian spiky)
|
|
192
|
+
const normalized = Math.abs(dist) / w;
|
|
193
|
+
let waveIntensity;
|
|
194
|
+
if (normalized > Math.PI) {
|
|
195
|
+
waveIntensity = 0;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
waveIntensity = Math.max(0, (1 + Math.cos(normalized)) / 2);
|
|
199
|
+
}
|
|
200
|
+
if (waveIntensity < 0.01)
|
|
201
|
+
continue; // skip — base dots already drawn
|
|
202
|
+
// Subtle per-bar texture: ±5% variation, no ripple
|
|
203
|
+
const texture = 0.95 + this.barSeeds[i] * 0.10;
|
|
204
|
+
waveIntensity *= texture;
|
|
205
|
+
// Bar height
|
|
206
|
+
const barHeight = MIN_BAR_HEIGHT + waveIntensity * (peakHeight - MIN_BAR_HEIGHT);
|
|
207
|
+
// Soft edge fade at canvas edges
|
|
208
|
+
const edgeDist = Math.min(t, 1 - t);
|
|
209
|
+
const edgeFade = Math.min(1, edgeDist * 6);
|
|
210
|
+
// Brightness tracks wave shape
|
|
211
|
+
const opacity = 0.50 + waveIntensity * 0.50;
|
|
212
|
+
ctx.globalAlpha = opacity * edgeFade;
|
|
213
|
+
drawBar(ctx, offsetX + i * BAR_UNIT, barHeight * edgeFade, height, roundRect);
|
|
214
|
+
}
|
|
215
|
+
ctx.globalAlpha = 1;
|
|
216
|
+
}
|
|
217
|
+
// ── Processing B (continuous scrolling wave) ───────────────────────────
|
|
218
|
+
/**
|
|
219
|
+
* Draw a continuous scrolling wave pattern. Multiple peaks and valleys
|
|
220
|
+
* are always visible, scrolling left-to-right like ocean waves.
|
|
221
|
+
* All bars stay active at varying heights — no dead periods.
|
|
222
|
+
*
|
|
223
|
+
* @param ctx Canvas 2D context
|
|
224
|
+
* @param width Canvas width in px
|
|
225
|
+
* @param height Canvas height in px
|
|
226
|
+
*/
|
|
227
|
+
drawProcessingB(ctx, width, height) {
|
|
228
|
+
const barCount = Math.max(MIN_BAR_COUNT, Math.floor(width / BAR_UNIT));
|
|
229
|
+
this.ensureState(barCount);
|
|
230
|
+
ctx.clearRect(0, 0, width, height);
|
|
231
|
+
const totalBarsWidth = barCount * BAR_UNIT;
|
|
232
|
+
const offsetX = Math.max(0, (width - totalBarsWidth) / 2);
|
|
233
|
+
const roundRect = hasRoundRect(ctx);
|
|
234
|
+
const now = Date.now() * 0.001;
|
|
235
|
+
// Scroll speed: waves move left-to-right
|
|
236
|
+
const scrollSpeed = 0.5; // lower = slower, more calming
|
|
237
|
+
// Two overlapping wave frequencies for organic feel
|
|
238
|
+
const freq1 = 2.5; // primary wave: ~2.5 peaks across the bar field
|
|
239
|
+
const freq2 = 1.2; // secondary wave: slower undulation
|
|
240
|
+
// Peak height: 75% of canvas
|
|
241
|
+
const peakHeight = height * 0.75;
|
|
242
|
+
ctx.fillStyle = this.accentColor;
|
|
243
|
+
for (let i = 0; i < barCount; i++) {
|
|
244
|
+
const t = i / (barCount - 1); // 0–1 position
|
|
245
|
+
// Two sine waves scrolling at different rates for natural variation
|
|
246
|
+
const wave1 = Math.sin((t * freq1 - now * scrollSpeed) * Math.PI * 2);
|
|
247
|
+
const wave2 = Math.sin((t * freq2 - now * scrollSpeed * 0.7) * Math.PI * 2);
|
|
248
|
+
// Combine: primary drives shape, secondary adds undulation
|
|
249
|
+
const combined = wave1 * 0.7 + wave2 * 0.3;
|
|
250
|
+
// Map from [-1, 1] to [0, 1]
|
|
251
|
+
const intensity = (combined + 1) / 2;
|
|
252
|
+
// Per-bar texture: ±5% variation
|
|
253
|
+
const texture = 0.95 + this.barSeeds[i] * 0.10;
|
|
254
|
+
// Center bias: slightly taller in the middle
|
|
255
|
+
const centerBias = 0.6 + 0.4 * Math.pow(Math.sin(t * Math.PI), 0.5);
|
|
256
|
+
// Bar height: always at least MIN_BAR_HEIGHT
|
|
257
|
+
const barHeight = MIN_BAR_HEIGHT + intensity * texture * centerBias * (peakHeight - MIN_BAR_HEIGHT);
|
|
258
|
+
// Soft edge fade
|
|
259
|
+
const edgeDist = Math.min(t, 1 - t);
|
|
260
|
+
const edgeFade = Math.min(1, edgeDist * 6);
|
|
261
|
+
// Opacity tracks height — valleys are dimmer but still visible
|
|
262
|
+
const opacity = 0.30 + intensity * 0.70;
|
|
263
|
+
ctx.globalAlpha = opacity * edgeFade;
|
|
264
|
+
drawBar(ctx, offsetX + i * BAR_UNIT, barHeight * edgeFade, height, roundRect);
|
|
265
|
+
}
|
|
266
|
+
ctx.globalAlpha = 1;
|
|
267
|
+
}
|
|
268
|
+
// ── Paused ──────────────────────────────────────────────────────────────
|
|
269
|
+
/**
|
|
270
|
+
* Draw the paused waveform. Static bars with a slow brightness sweep.
|
|
271
|
+
*
|
|
272
|
+
* @param ctx Canvas 2D context
|
|
273
|
+
* @param width Canvas width in px
|
|
274
|
+
* @param height Canvas height in px
|
|
275
|
+
*/
|
|
276
|
+
drawPaused(ctx, width, height) {
|
|
277
|
+
const barCount = Math.max(MIN_BAR_COUNT, Math.floor(width / BAR_UNIT));
|
|
278
|
+
this.ensureState(barCount);
|
|
279
|
+
ctx.clearRect(0, 0, width, height);
|
|
280
|
+
const totalBarsWidth = barCount * BAR_UNIT;
|
|
281
|
+
const offsetX = Math.max(0, (width - totalBarsWidth) / 2);
|
|
282
|
+
const roundRect = hasRoundRect(ctx);
|
|
283
|
+
const now = Date.now() * 0.001;
|
|
284
|
+
for (let i = 0; i < barCount; i++) {
|
|
285
|
+
const t = i / (barCount - 1);
|
|
286
|
+
// Concentrated brightness sweep — tighter gradient, higher base
|
|
287
|
+
const phase = t * Math.PI * 2 - now * 0.8;
|
|
288
|
+
const rawSweep = Math.sin(phase);
|
|
289
|
+
// Raise to power to concentrate the bright region into a narrower band
|
|
290
|
+
const sweep = rawSweep > 0 ? Math.pow(rawSweep, 2) : 0;
|
|
291
|
+
const opacity = 0.3 + sweep * 0.45;
|
|
292
|
+
ctx.fillStyle = this.accentColor;
|
|
293
|
+
ctx.globalAlpha = opacity;
|
|
294
|
+
drawBar(ctx, offsetX + i * BAR_UNIT, MIN_BAR_HEIGHT, height, roundRect);
|
|
295
|
+
}
|
|
296
|
+
ctx.globalAlpha = 1;
|
|
297
|
+
}
|
|
298
|
+
// ── Internal ────────────────────────────────────────────────────────────
|
|
299
|
+
/** Initialize/resize persistent state when bar count changes */
|
|
300
|
+
ensureState(barCount) {
|
|
301
|
+
if (barCount === this.lastBarCount)
|
|
302
|
+
return;
|
|
303
|
+
this.barSeeds = Array.from({ length: barCount }, (_, i) => seededRandom(i + 0.5));
|
|
304
|
+
// Resize smoothed heights, preserving existing values where possible
|
|
305
|
+
const newHeights = new Array(barCount).fill(MIN_BAR_HEIGHT);
|
|
306
|
+
for (let i = 0; i < Math.min(this.smoothedHeights.length, barCount); i++) {
|
|
307
|
+
newHeights[i] = this.smoothedHeights[i];
|
|
308
|
+
}
|
|
309
|
+
this.smoothedHeights = newHeights;
|
|
310
|
+
this.lastBarCount = barCount;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
exports.WaveformRenderer = WaveformRenderer;
|
|
314
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@igggy/waveform",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared waveform renderer for Igggy clients (web + plugin)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Andrew Lassetter",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/andrewlassetter/igggy-web",
|
|
10
|
+
"directory": "packages/waveform"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["igggy", "waveform", "canvas", "audio"],
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"files": ["dist"],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "tsc --watch",
|
|
22
|
+
"prepare": "tsc"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"typescript": "^5.9.3"
|
|
26
|
+
}
|
|
27
|
+
}
|