diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Abstraction/IBeeperDevice.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Abstraction/IBeeperDevice.cs
index 7367e3948f..2e4d2dea50 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Abstraction/IBeeperDevice.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Abstraction/IBeeperDevice.cs
@@ -11,14 +11,12 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
void Init(int sampleRate, int tStatesPerFrame);
- void ProcessPulseValue(bool fromTape, bool earPulse);
+ void ProcessPulseValue(bool pulse);
void StartFrame();
void EndFrame();
- void SetTapeMode(bool tapeMode);
-
void SyncState(Serializer ser);
}
}
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Datacorder/DatacorderDevice.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Datacorder/DatacorderDevice.cs
index c67ce41ee4..3ca036d3bc 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Datacorder/DatacorderDevice.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Datacorder/DatacorderDevice.cs
@@ -151,10 +151,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public void StartFrame()
{
- //if (TapeIsPlaying && AutoPlay)
- //FlashLoad();
-
- _buzzer.ProcessPulseValue(true, currentState);
+ //_buzzer.ProcessPulseValue(currentState);
}
#endregion
@@ -169,8 +166,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (_tapeIsPlaying)
return;
- _buzzer.SetTapeMode(true);
-
_machine.Spectrum.OSD_TapePlaying();
// update the lastCycle
@@ -224,8 +219,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (!_tapeIsPlaying)
return;
- _buzzer.SetTapeMode(false);
-
_machine.Spectrum.OSD_TapeStopped();
// sign that the tape is no longer playing
@@ -384,16 +377,15 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
#endregion
- #region Tape Device Methods
-
-
-
+ #region Tape Device Methods
///
- /// Runs every frame
+ /// Is called every cpu cycle but runs every 50 t-states
+ /// This enables the tape devices to play out even if the spectrum itself is not
+ /// requesting tape data
///
public void TapeCycle()
- {
+ {
if (TapeIsPlaying)
{
counter++;
@@ -402,7 +394,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
counter = 0;
bool state = GetEarBit(_machine.CPU.TotalExecutedCycles);
- _buzzer.ProcessPulseValue(false, state);
+ _buzzer.ProcessPulseValue(state);
}
}
}
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/SoundOuput/Buzzer.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/SoundOuput/Buzzer.cs
index 3a9516a63b..1f6b9ad20c 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/SoundOuput/Buzzer.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/SoundOuput/Buzzer.cs
@@ -1,10 +1,8 @@
using BizHawk.Common;
using BizHawk.Emulation.Common;
-using BizHawk.Emulation.Cores.Components;
using System;
using System.Collections.Generic;
-using System.Linq;
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
@@ -14,30 +12,28 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
///
/// For the purposes of emulation this devices is locked to a frame
/// a list of Pulses is built up over the course of the frame and outputted at the end of the frame
+ ///
+ /// ZXHawk instantiates multiples of these buzzers to achieve separation between tape and spectrum audio output
///
public class Buzzer : ISoundProvider, IBeeperDevice
{
- ///
- /// Supplied values are right for 48K spectrum
- /// These will deviate for 128k and up (as there are more T-States per frame)
- ///
- //public int SampleRate = 44100; //35000;
- //public int SamplesPerFrame = 882; //699;
- //public int TStatesPerSample = 79; //100;
-
+ #region Fields and Properties
+
///
/// Sample Rate
/// This usually has to be 44100 for ISoundProvider
///
+ private int _sampleRate;
public int SampleRate
{
get { return _sampleRate; }
set { _sampleRate = value; }
}
-
+
///
/// Number of samples in one frame
///
+ private int _samplesPerFrame;
public int SamplesPerFrame
{
get { return _samplesPerFrame; }
@@ -47,6 +43,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
///
/// Number of TStates in each sample
///
+ private int _tStatesPerSample;
public int TStatesPerSample
{
get { return _tStatesPerSample; }
@@ -54,37 +51,55 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
}
///
- /// The tape loading volume
+ /// Buzzer volume
/// Accepts an int 0-100 value
///
- private int _tapeVolume;
- public int TapeVolume
+ private int _volume;
+ public int Volume
{
get
{
- return VolumeConverterOut(_tapeVolume);
+ return VolumeConverterOut(_volume);
}
set
{
- _tapeVolume = VolumeConverterIn(value);
+ _volume = VolumeConverterIn(value);
}
}
///
- /// The EAR beeper volume
+ /// The number of cpu cycles per frame
///
- private int _earVolume;
- public int EarVolume
- {
- get
- {
- return VolumeConverterOut(_earVolume);
- }
- set
- {
- _earVolume = VolumeConverterIn(value);
- }
- }
+ private long _tStatesPerFrame;
+
+ ///
+ /// The cycle at which the frame starts
+ ///
+ private long _frameStart;
+
+ ///
+ /// The parent emulated machine
+ ///
+ private SpectrumBase _machine;
+
+ ///
+ /// Pulses collected during the last frame
+ ///
+ public List Pulses { get; private set; }
+
+ ///
+ /// The last pulse
+ ///
+ public bool LastPulse { get; set; }
+
+ ///
+ /// The last T-State (cpu cycle) that the last pulse was received
+ ///
+ public long LastPulseTState { get; set; }
+
+ #endregion
+
+ #region Private Methods
///
/// Takes an int 0-100 and returns the relevant short volume to output
@@ -115,33 +130,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
return shortvol / increment;
}
-
- private SpectrumBase _machine;
-
- ///
- /// State fields
- ///
- private long _frameStart;
- private bool _tapeMode;
- private long _tStatesPerFrame;
- private int _sampleRate;
- private int _samplesPerFrame;
- private int _tStatesPerSample;
-
- ///
- /// Pulses collected during the last frame
- ///
- public List Pulses { get; private set; }
-
- ///
- /// The last pulse
- ///
- public bool LastPulse { get; set; }
-
- ///
- /// The last T-State (cpu cycle) that the last pulse was received
- ///
- public long LastPulseTState { get; set; }
+ #endregion
#region Construction & Initialisation
@@ -159,75 +148,31 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
_tStatesPerFrame = tStatesPerFrame;
_tStatesPerSample = 79;
_samplesPerFrame = (int)_tStatesPerFrame / _tStatesPerSample;
-
- /*
-
- // set the tstatesperframe
- _tStatesPerFrame = tStatesPerFrame;
-
- // calculate actual refresh rate
- double refresh = (double)_machine.ULADevice.ClockSpeed / (double)_tStatesPerFrame;
-
- // how many samples per frame are expected by ISoundProvider (at 44.1KHz)
- _samplesPerFrame = 880;// (int)((double)sampleRate / (double)refresh);
-
- // set the sample rate
- _sampleRate = sampleRate;
-
- // calculate samples per frame (what ISoundProvider will be expecting at 44100)
- //_samplesPerFrame = (int)((double)_tStatesPerFrame / (double)refresh);
-
- // calculate tstates per sameple
- _tStatesPerSample = 79;// _tStatesPerFrame / _samplesPerFrame;
-
- /*
-
-
-
-
- // get divisors
- var divs = from a in Enumerable.Range(2, _tStatesPerFrame / 2)
- where _tStatesPerFrame % a == 0
- select a;
-
- // get the highest int value under 120 (this will be TStatesPerSample)
- _tStatesPerSample = divs.Where(a => a < 100).Last();
-
- // get _samplesPerFrame
- _samplesPerFrame = _tStatesPerFrame / _tStatesPerSample;
-
- */
Pulses = new List(1000);
}
#endregion
+ #region IBeeperDevice
+
///
- /// When the pulse value from the EAR output changes it is processed here
+ /// When the pulse value changes it is processed here
///
- ///
- ///
- public void ProcessPulseValue(bool fromTape, bool earPulse)
+ ///
+ public void ProcessPulseValue(bool pulse)
{
if (!_machine._renderSound)
return;
- if (!fromTape && _tapeMode)
- {
- // tape mode is active but the pulse value came from an OUT instruction
- // do not process the value
- //return;
- }
-
- if (earPulse == LastPulse)
+ if (pulse == LastPulse)
{
// no change detected
return;
}
// set the lastpulse
- LastPulse = earPulse;
+ LastPulse = pulse;
// get where we are in the frame
var currentULACycle = _machine.CurrentFrameCycle;
@@ -244,7 +189,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// add the pulse
Pulse p = new Pulse
{
- State = !earPulse,
+ State = !pulse,
Length = length
};
Pulses.Add(p);
@@ -259,7 +204,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
///
public void StartFrame()
{
- //DiscardSamples();
Pulses.Clear();
LastPulseTState = 0;
}
@@ -296,11 +240,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
for (var i = firstSample; i < currentEnd + pulse.Length; i += TStatesPerSample)
{
- if (_tapeMode)
- samples[sampleIndex++] = pulse.State ? (short)(_tapeVolume) : (short)0;
- else
- samples[sampleIndex++] = pulse.State ? (short)(_earVolume) : (short)0;
- }
+ samples[sampleIndex++] = pulse.State ? (short)(_volume) : (short)0;
+ }
currentEnd += pulse.Length;
}
@@ -316,16 +257,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
_frameStart += _tStatesPerFrame;
}
- ///
- /// When the spectrum is set to receive tape input, the EAR output on the ULA is disabled
- /// (so no buzzer sound is emitted)
- ///
- ///
- public void SetTapeMode(bool tapeMode)
- {
- _tapeMode = tapeMode;
- }
-
+ #endregion
#region ISoundProvider
@@ -370,24 +302,21 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
#endregion
-
+ #region State Serialization
+
public void SyncState(Serializer ser)
{
ser.BeginSection("Buzzer");
ser.Sync("_frameStart", ref _frameStart);
- ser.Sync("_tapeMode", ref _tapeMode);
ser.Sync("_tStatesPerFrame", ref _tStatesPerFrame);
ser.Sync("_sampleRate", ref _sampleRate);
ser.Sync("_samplesPerFrame", ref _samplesPerFrame);
ser.Sync("_tStatesPerSample", ref _tStatesPerSample);
-
ser.Sync("soundBuffer", ref soundBuffer, false);
ser.Sync("soundBufferContains", ref soundBufferContains);
ser.EndSection();
}
-
+ #endregion
}
-
-
}
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs
index bcebb55542..f88922132c 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs
@@ -158,7 +158,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
ULADevice.borderColour = value & BORDER_BIT;
// Buzzer
- BuzzerDevice.ProcessPulseValue(false, (value & EAR_BIT) != 0);
+ BuzzerDevice.ProcessPulseValue((value & EAR_BIT) != 0);
TapeDevice.WritePort(port, value);
// Tape
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs
index 24e7a13760..425d33f275 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs
@@ -250,7 +250,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
ULADevice.borderColour = value & BORDER_BIT;
// Buzzer
- BuzzerDevice.ProcessPulseValue(false, (value & EAR_BIT) != 0);
+ BuzzerDevice.ProcessPulseValue((value & EAR_BIT) != 0);
// Tape
TapeDevice.WritePort(port, value);
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs
index e56c23440b..8226326b11 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs
@@ -177,7 +177,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
ULADevice.borderColour = value & BORDER_BIT;
// Buzzer
- BuzzerDevice.ProcessPulseValue(false, (value & EAR_BIT) != 0);
+ BuzzerDevice.ProcessPulseValue((value & EAR_BIT) != 0);
// Tape
TapeDevice.WritePort(port, value);
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs
index 0cb5b9c7c1..12f8850957 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs
@@ -115,7 +115,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
ULADevice.borderColour = value & BORDER_BIT;
// Buzzer
- BuzzerDevice.ProcessPulseValue(false, (value & EAR_BIT) != 0);
+ BuzzerDevice.ProcessPulseValue((value & EAR_BIT) != 0);
// Tape
TapeDevice.WritePort(port, value);
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ISettable.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ISettable.cs
index 5f721f233d..deb5d63eaa 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ISettable.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ISettable.cs
@@ -33,8 +33,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
}
if (_machine != null && _machine.BuzzerDevice != null)
{
- ((Buzzer)_machine.BuzzerDevice as Buzzer).TapeVolume = o.TapeVolume;
- ((Buzzer)_machine.BuzzerDevice as Buzzer).EarVolume = o.EarVolume;
+ ((Buzzer)_machine.BuzzerDevice as Buzzer).Volume = o.EarVolume;
+ }
+ if (_machine != null && _machine.TapeBuzzer != null)
+ {
+ ((Buzzer)_machine.TapeBuzzer as Buzzer).Volume = o.TapeVolume;
}
Settings = o;
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.cs
index cd4eabe7ba..f6c97c692e 100644
--- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.cs
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.cs
@@ -79,8 +79,6 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
default:
throw new InvalidOperationException("Machine not yet emulated");
}
-
-
_cpu.MemoryCallbacks = MemoryCallbacks;
@@ -98,37 +96,33 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
ser.Register(_cpu);
ser.Register(_machine.ULADevice);
+ // initialize sound mixer and attach the various ISoundProvider devices
SoundMixer = new SoundProviderMixer((int)(32767 / 10), (ISoundProvider)_machine.BuzzerDevice);
+ SoundMixer.AddSource((ISoundProvider)_machine.TapeBuzzer);
if (_machine.AYDevice != null)
SoundMixer.AddSource(_machine.AYDevice);
- if (_machine.TapeBuzzer != null)
- SoundMixer.AddSource((ISoundProvider)_machine.TapeBuzzer);
- //SoundMixer.Stereo = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).StereoSound;
-
+
+ // set audio device settings
if (_machine.AYDevice != null && _machine.AYDevice.GetType() == typeof(AYChip))
{
((AYChip)_machine.AYDevice as AYChip).PanningConfiguration = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).AYPanConfig;
_machine.AYDevice.Volume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).AYVolume;
}
-
+
if (_machine.BuzzerDevice != null)
{
- ((Buzzer)_machine.BuzzerDevice as Buzzer).TapeVolume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).TapeVolume;
- ((Buzzer)_machine.BuzzerDevice as Buzzer).EarVolume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).EarVolume;
+ ((Buzzer)_machine.BuzzerDevice as Buzzer).Volume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).EarVolume;
}
if (_machine.TapeBuzzer != null)
{
- ((Buzzer)_machine.TapeBuzzer as Buzzer).TapeVolume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).TapeVolume;
- //((Buzzer)_machine.TapeBuzzer as Buzzer).EarVolume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).EarVolume;
+ ((Buzzer)_machine.TapeBuzzer as Buzzer).Volume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).TapeVolume;
}
-
ser.Register(SoundMixer);
HardReset();
-
SetupMemoryDomains();
}