Virtu/Virtu/Speaker.cs
Sean Fausett 0182641281 Merged machine settings into machine components.
Added save state support to all machine components.
Switched from xml serialization to binary serialization.
Refactored audio service for performance.
Bumped machine version to 0.9.0 for next release.
Miscellaneous cosmetic or minor changes.
2010-11-29 09:08:11 +13:00

95 lines
2.5 KiB
C#

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>();
#if WINDOWS_PHONE
Volume = 0.85;
#else
Volume = 0.5;
#endif
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.ReadDouble();
}
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 double 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 double _volume;
}
}