54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
// @vitest-environment jsdom
|
||
|
||
import { describe, expect, it } from 'vitest';
|
||
|
||
import { ArpeggioTone } from '../../../../src/card-controller/call/tones/arpeggio';
|
||
import { useAudioMocks } from './test-utils';
|
||
|
||
// Each strike emits a 3-layer bell stack in order: sparkle (octave above
|
||
// fundamental), fundamental, hum (octave below). Indices into
|
||
// `audio.oscillators` step through the three descending plucks.
|
||
describe('ArpeggioTone', () => {
|
||
const audio = useAudioMocks();
|
||
|
||
it('should play G5-E5-C5 descending plucks 0.25s apart', () => {
|
||
new ArpeggioTone(0).start();
|
||
|
||
// 3 strikes × 3 layers = 9 oscillators.
|
||
expect(audio.oscillators).toHaveLength(9);
|
||
|
||
// G5 (783.99) at t=0.
|
||
expect(audio.oscillators[1].frequency.value).toBe(783.99);
|
||
expect(audio.oscillators[1].start).toHaveBeenCalledWith(0);
|
||
|
||
// E5 (659.25) at t=0.25.
|
||
expect(audio.oscillators[4].frequency.value).toBe(659.25);
|
||
expect(audio.oscillators[4].start).toHaveBeenCalledWith(0.25);
|
||
|
||
// C5 (523.25) at t=0.5.
|
||
expect(audio.oscillators[7].frequency.value).toBe(523.25);
|
||
expect(audio.oscillators[7].start).toHaveBeenCalledWith(0.5);
|
||
});
|
||
|
||
it('should use the lighter PLUCK envelope for every strike', () => {
|
||
new ArpeggioTone(0).start();
|
||
|
||
// Sparkle / fundamental / hum peaks for every strike.
|
||
for (let strike = 0; strike < 3; strike++) {
|
||
const i = strike * 3;
|
||
expect(audio.gainParams[i].linearRampToValueAtTime).toHaveBeenCalledWith(
|
||
0.05,
|
||
expect.any(Number),
|
||
);
|
||
expect(audio.gainParams[i + 1].linearRampToValueAtTime).toHaveBeenCalledWith(
|
||
0.13,
|
||
expect.any(Number),
|
||
);
|
||
expect(audio.gainParams[i + 2].linearRampToValueAtTime).toHaveBeenCalledWith(
|
||
0.04,
|
||
expect.any(Number),
|
||
);
|
||
}
|
||
});
|
||
});
|