2015-02-17 22:58:25 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using Jellyfish.Virtu.Services;
|
|
|
|
|
|
|
|
|
|
namespace Jellyfish.Virtu
|
|
|
|
|
{
|
|
|
|
|
public sealed class Speaker : MachineComponent
|
|
|
|
|
{
|
|
|
|
|
public Speaker(Machine machine) :
|
|
|
|
|
base(machine)
|
|
|
|
|
{
|
|
|
|
|
_flushOutputEvent = FlushOutputEvent; // cache delegates; avoids garbage
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Initialize()
|
|
|
|
|
{
|
|
|
|
|
_audioService = Machine.Services.GetService<AudioService>();
|
|
|
|
|
|
|
|
|
|
Volume = 0.5f;
|
|
|
|
|
Machine.Events.AddEvent(CyclesPerFlush * Machine.Cpu.Multiplier, _flushOutputEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Reset()
|
|
|
|
|
{
|
|
|
|
|
_audioService.Reset();
|
|
|
|
|
_isHigh = false;
|
|
|
|
|
_highCycles = _totalCycles = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void LoadState(BinaryReader reader, Version version)
|
|
|
|
|
{
|
|
|
|
|
if (reader == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException("reader");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Volume = reader.ReadSingle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void SaveState(BinaryWriter writer)
|
|
|
|
|
{
|
|
|
|
|
if (writer == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException("writer");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
writer.Write(Volume);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ToggleOutput()
|
|
|
|
|
{
|
|
|
|
|
UpdateCycles();
|
|
|
|
|
_isHigh ^= true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FlushOutputEvent()
|
|
|
|
|
{
|
|
|
|
|
UpdateCycles();
|
|
|
|
|
_audioService.Output(_highCycles * short.MaxValue / _totalCycles); // quick and dirty decimation
|
|
|
|
|
_highCycles = _totalCycles = 0;
|
|
|
|
|
|
|
|
|
|
Machine.Events.AddEvent(CyclesPerFlush * Machine.Cpu.Multiplier, _flushOutputEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateCycles()
|
|
|
|
|
{
|
|
|
|
|
int delta = (int)(Machine.Cpu.Cycles - _lastCycles);
|
|
|
|
|
if (_isHigh)
|
|
|
|
|
{
|
|
|
|
|
_highCycles += delta;
|
|
|
|
|
}
|
|
|
|
|
_totalCycles += delta;
|
|
|
|
|
_lastCycles = Machine.Cpu.Cycles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public float Volume { get { return _volume; } set { _volume = value; _audioService.SetVolume(_volume); } }
|
|
|
|
|
|
|
|
|
|
private const int CyclesPerFlush = 23;
|
|
|
|
|
|
|
|
|
|
private Action _flushOutputEvent;
|
|
|
|
|
|
|
|
|
|
private AudioService _audioService;
|
|
|
|
|
|
|
|
|
|
private bool _isHigh;
|
|
|
|
|
private int _highCycles;
|
|
|
|
|
private int _totalCycles;
|
|
|
|
|
private long _lastCycles;
|
|
|
|
|
private float _volume;
|
2015-03-27 23:24:58 +00:00
|
|
|
|
|
|
|
|
|
public AudioService AudioService { get { return _audioService; } }
|
2015-02-17 22:58:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|