play method
Implementation
@override
Future<void> play({
required double leftFreq,
required double rightFreq,
double volume = 0.7,
}) async {
final ctx = _ctx!;
// Resume if suspended (browser autoplay policy).
if (ctx.state == 'suspended') {
await ctx.resume().toDart;
}
// Master gain → destination.
_masterGain = ctx.createGain();
_masterGain!.gain.value = volume;
_masterGain!.connect(ctx.destination);
// Channel merger (2 inputs) → master gain.
_merger = ctx.createChannelMerger(2);
_merger!.connect(_masterGain!);
// Left: oscillator → gain → merger input 0.
_gainL = ctx.createGain();
_gainL!.gain.value = 1.0;
_gainL!.connect(_merger!, 0, 0);
_oscL = ctx.createOscillator();
_oscL!.type = 'sine';
_oscL!.frequency.value = leftFreq;
_oscL!.connect(_gainL!);
_oscL!.start();
// Right: oscillator → gain → merger input 1.
_gainR = ctx.createGain();
_gainR!.gain.value = 1.0;
_gainR!.connect(_merger!, 0, 1);
_oscR = ctx.createOscillator();
_oscR!.type = 'sine';
_oscR!.frequency.value = rightFreq;
_oscR!.connect(_gainR!);
_oscR!.start();
_running = true;
}