87 lines
2.8 KiB
C#
87 lines
2.8 KiB
C#
using NAudio.Wave;
|
|
using Core.Interfaces;
|
|
using System;
|
|
using System.Threading;
|
|
|
|
namespace Desktop
|
|
{
|
|
public class BeeperDevice : IAudioDevice
|
|
{
|
|
private WaveOutEvent _waveOut;
|
|
private BufferedWaveProvider _buffer;
|
|
|
|
// Audio Filtering
|
|
private float _lastSample = 0.0f;
|
|
private float _lastFiltered = 0.0f;
|
|
|
|
// AY-3-8912 Digital Oscillators (Phase Trackers)
|
|
private float _phaseA = 0f;
|
|
private float _phaseB = 0f;
|
|
private float _phaseC = 0f;
|
|
|
|
public BeeperDevice()
|
|
{
|
|
_waveOut = new WaveOutEvent();
|
|
_waveOut.DesiredLatency = 50;
|
|
|
|
// 44.1kHz, 1 channel (Mono), Float format
|
|
_buffer = new BufferedWaveProvider(WaveFormat.CreateIeeeFloatWaveFormat(44100, 1));
|
|
_buffer.BufferDuration = TimeSpan.FromSeconds(1);
|
|
_buffer.DiscardOnBufferOverflow = true;
|
|
|
|
_waveOut.Init(_buffer);
|
|
_waveOut.Play();
|
|
}
|
|
|
|
public void AddSample(bool isHigh, float freqA, float volA, float freqB, float volB, float freqC, float volC)
|
|
{
|
|
// Buffer overrun check
|
|
while (_buffer.BufferedDuration.TotalMilliseconds > 80)
|
|
{
|
|
Thread.Sleep(1);
|
|
}
|
|
|
|
// 1. The Beeper (Reduced base volume from 0.2 to 0.1 to make headroom for the AY)
|
|
float beeper = isHigh ? 0.1f : -0.1f;
|
|
|
|
// 2. Channel A Oscillator
|
|
float ayA = 0f;
|
|
if (freqA > 0)
|
|
{
|
|
_phaseA += freqA / 44100f;
|
|
if (_phaseA > 1f) _phaseA -= 1f; // Wrap around
|
|
ayA = (_phaseA < 0.5f ? 0.1f : -0.1f) * volA;
|
|
}
|
|
|
|
// 3. Channel B Oscillator
|
|
float ayB = 0f;
|
|
if (freqB > 0)
|
|
{
|
|
_phaseB += freqB / 44100f;
|
|
if (_phaseB > 1f) _phaseB -= 1f;
|
|
ayB = (_phaseB < 0.5f ? 0.1f : -0.1f) * volB;
|
|
}
|
|
|
|
// 4. Channel C Oscillator
|
|
float ayC = 0f;
|
|
if (freqC > 0)
|
|
{
|
|
_phaseC += freqC / 44100f;
|
|
if (_phaseC > 1f) _phaseC -= 1f;
|
|
ayC = (_phaseC < 0.5f ? 0.1f : -0.1f) * volC;
|
|
}
|
|
|
|
// Mix them all together!
|
|
float rawSample = beeper + ayA + ayB + ayC;
|
|
|
|
// Pass the mixed sound wave through your existing High-Pass filter to stop popping
|
|
float filteredSample = rawSample - _lastSample + 0.995f * _lastFiltered;
|
|
_lastSample = rawSample;
|
|
_lastFiltered = filteredSample;
|
|
|
|
// Convert to bytes and drop it in the pipe
|
|
byte[] bytes = BitConverter.GetBytes(filteredSample);
|
|
_buffer.AddSamples(bytes, 0, 4);
|
|
}
|
|
}
|
|
} |