Skip to content

Commit

Permalink
2.0.3.0 Improved sounds output timing accuracy.
Browse files Browse the repository at this point in the history
  • Loading branch information
110-kenichi committed Aug 9, 2020
1 parent d6bcb4f commit caa5de8
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 72 deletions.
2 changes: 1 addition & 1 deletion src/emu/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ void running_machine::start()
StartMAmidiMEmoMain();

emu_timer* mami_timer = m_scheduler.timer_alloc(timer_expired_delegate(FUNC(running_machine::mami_timer_callback), this));
mami_timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1));
mami_timer->adjust(attotime::from_usec(10), 0, attotime::from_usec(10));

// initialize UI input
m_ui_input = make_unique_clear<ui_input_manager>(*this);
Expand Down
18 changes: 5 additions & 13 deletions src/mamidimemo/Gui/FormMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -689,42 +689,36 @@ private void tabPage1_Paint(object sender, PaintEventArgs e)
using (Pen p = new Pen(Color.DarkGreen))
{
int max = h * 4;
//int? ldt = null;
int zero = 0;
for (int ch = 0; ch < 2; ch++)
{
if (data[ch] != null)
{
for (int i = 0; i < data[ch].Length; i++)
{
int dt = data[ch][i];
//int sn = Math.Sign(dt);
//if (zero == 0 && ldt != null && sn > 0 && sn != Math.Sign(ldt.Value))
// zero = i;
max = Math.Max(Math.Abs(dt), max);
//ldt = dt;
}
}
}
max += max / 10;

if (data[0] != null)
draw(e, p, data[0], zero, w / 2 - 1, h / 2, 0, max);
draw(e, p, data[0], w / 2 - 1, h / 2, 0, max);
if (data[1] != null)
draw(e, p, data[1], zero, w / 2 - 1, h / 2, w / 2 + 1, max);
draw(e, p, data[1], w / 2 - 1, h / 2, w / 2 + 1, max);
}
}
e.Graphics.DrawLine(SystemPens.Control, w / 2 - 1, 0, w / 2 - 1, h);
e.Graphics.DrawLine(SystemPens.Control, w / 2, 0, w / 2, h);
}

private static void draw(PaintEventArgs e, Pen p, int[] data, int zero, int w, int h, int ox, int max)
private static void draw(PaintEventArgs e, Pen p, int[] data, int w, int h, int ox, int max)
{
int len = data.Length - zero;
int len = data.Length;
List<Point> pts = new List<Point>();
for (int i = 0; i < w; i++)
{
int y = data[zero + (int)(((double)i / w) * len)];
int y = data[(int)(((double)i / w) * len)];
y = -(int)((y / (double)max) * h);
y += h;
int lx = i - 1;
Expand All @@ -739,8 +733,6 @@ private void timer1_Tick(object sender, EventArgs e)
{
if (tabControl1.SelectedTab == tabPage1)
tabPage1.Invalidate();
//else if (tabControl1.SelectedTab == tabPage3)
// tabPage3.Invalidate();
}

private void resetToDefaultThisPropertyToolStripMenuItem_Click(object sender, EventArgs e)
Expand Down
4 changes: 2 additions & 2 deletions src/mamidimemo/instruments/DrumTimbre.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public void ResetBaseNote()
[DataMember]
[Description("Gate Time[ms]")]
[DefaultValue(typeof(uint), "500")]
[SlideParametersAttribute((int)HighPrecisionTimer.TIMER_BASIC_INTERVAL, 10000)]
[SlideParametersAttribute(1, 10000)]
[EditorAttribute(typeof(SlideEditor), typeof(System.Drawing.Design.UITypeEditor))]
public uint GateTime
{
Expand All @@ -94,7 +94,7 @@ public uint GateTime
{
if (value > 10000)
value = 10000;
if (f_GateTime != value && value >= HighPrecisionTimer.TIMER_BASIC_INTERVAL)
if (f_GateTime != value && value >= 1)
{
f_GateTime = value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public virtual bool Enable
[DataMember]
[Description("Set interval of envelope changing [ms]")]
[DefaultValue(typeof(uint), "50")]
[SlideParametersAttribute((int)HighPrecisionTimer.TIMER_BASIC_INTERVAL, 10000)]
[SlideParametersAttribute(1, 10000)]
[EditorAttribute(typeof(SlideEditor), typeof(System.Drawing.Design.UITypeEditor))]
public uint EnvelopeInterval
{
Expand All @@ -58,7 +58,7 @@ public uint EnvelopeInterval
{
if (value > 10000)
value = 10000;
if (f_Interval != value && value >= HighPrecisionTimer.TIMER_BASIC_INTERVAL)
if (f_Interval != value && value >= 1)
{
f_Interval = value;
}
Expand Down
6 changes: 3 additions & 3 deletions src/mamidimemo/instruments/Envelopes/AdsrEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public AdsrEngine()
/// <param name="rate">[sec]</param>
public void SetAttackRate(double rate)
{
attackRate = rate * HighPrecisionTimer.TIMER_BASIC_HZ;
attackRate = rate * HighPrecisionTimer.TIMER_BASIC_1KHZ;
attackCoef = calcCoef(rate, targetRatioA);
attackBase = (1.0 + targetRatioA) * (1.0 - attackCoef);
}
Expand All @@ -75,7 +75,7 @@ public void SetAttackRate(double rate)
/// <param name="rate">[sec]</param>
public void SetDecayRate(double rate)
{
decayRate = rate * HighPrecisionTimer.TIMER_BASIC_HZ;
decayRate = rate * HighPrecisionTimer.TIMER_BASIC_1KHZ;
decayCoef = calcCoef(rate, targetRatioDR);
decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
}
Expand All @@ -86,7 +86,7 @@ public void SetDecayRate(double rate)
/// <param name="rate">[sec]</param>
public void SetReleaseRate(double rate)
{
releaseRate = rate * HighPrecisionTimer.TIMER_BASIC_HZ;
releaseRate = rate * HighPrecisionTimer.TIMER_BASIC_1KHZ;
releaseCoef = calcCoef(rate, targetRatioDR);
releaseBase = -targetRatioDR * (1.0 - releaseCoef);
}
Expand Down
6 changes: 3 additions & 3 deletions src/mamidimemo/instruments/Envelopes/ArpSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public ArpResolution ArpResolution
if (f_ArpResolution != value)
{
f_ArpResolution = value;
ArpStep = (60d * HighPrecisionTimer.TIMER_BASIC_HZ / Beat) / (double)ArpResolution;
ArpStep = (60d * HighPrecisionTimer.TIMER_BASIC_1KHZ / Beat) / (double)ArpResolution;
}
}
}
Expand Down Expand Up @@ -193,7 +193,7 @@ public int GateTime
if (f_GateTime != value)
{
f_GateTime = value;
ArpStep = (60d * HighPrecisionTimer.TIMER_BASIC_HZ / Beat) / (double)ArpResolution;
ArpStep = (60d * HighPrecisionTimer.TIMER_BASIC_1KHZ / Beat) / (double)ArpResolution;
}
}
}
Expand Down Expand Up @@ -223,7 +223,7 @@ public bool KeySync
/// </summary>
public ArpSettings()
{
ArpStep = (60d * HighPrecisionTimer.TIMER_BASIC_HZ / Beat) / (double)ArpResolution;
ArpStep = (60d * HighPrecisionTimer.TIMER_BASIC_1KHZ / Beat) / (double)ArpResolution;
}

#region Etc
Expand Down
42 changes: 18 additions & 24 deletions src/mamidimemo/instruments/HighPrecisionTimer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@

namespace zanac.MAmidiMEmo.Instruments
{
/// <summary>
/// 高精度タイマー
/// </summary>
public static class HighPrecisionTimer
{

private const int WAIT_TIMEOUT = 120 * 1000;

/// <summary>
/// Periodic Action Timer Interval[ms]
/// Periodic Action Timer Interval[1 ms]
/// </summary>
public const uint TIMER_BASIC_INTERVAL = 1;
public const uint TIMER_BASIC_1MS_COUNT = 100;

/// <summary>
/// Periodic Action Timer Hz
/// Periodic Action Timer Hz()
/// </summary>
public const double TIMER_BASIC_HZ = 1000d / TIMER_BASIC_INTERVAL;
public const double TIMER_BASIC_1KHZ = 1000d;

private static List<PeriodicAction> periodicTimerSounds = new List<PeriodicAction>();

Expand All @@ -34,40 +35,33 @@ static HighPrecisionTimer()
Program.ShuttingDown += Program_ShuttingDown;
}

private static bool shutDown;

/// <summary>
///
/// </summary>
/// <param name="action"></param>
/// <param name="periodMs"></param>
/// <param name="state"></param>
public static void SetPeriodicCallback(Func<object, double> action, double periodMs, object state)
{
action(state);
lock (periodicTimerSounds)
periodicTimerSounds.Add(new PeriodicAction(action, periodMs, state));
}

private static bool shutDown;

/// <param name="sender"></param>
/// <param name="e"></param>
private static void Program_ShuttingDown(object sender, EventArgs e)
{
shutDown = true;
}


/// <summary>
///
/// </summary>
/// <param name="instance"></param>
public static void SetFixedPeriodicCallback(Func<object, double> action, object state)
/// <param name="action"></param>
/// <param name="periodMs"></param>
/// <param name="state"></param>
public static void SetPeriodicCallback(Func<object, double> action, double periodMs, object state)
{
action(state);
lock (periodicTimerSounds)
periodicTimerSounds.Add(new PeriodicAction(action, TIMER_BASIC_INTERVAL, state));
periodicTimerSounds.Add(new PeriodicAction(action, periodMs, state));
}

/// <summary>
///
/// MAMEから呼ばれる
/// </summary>
public static void SoundTimerCallback()
{
Expand All @@ -79,7 +73,7 @@ public static void SoundTimerCallback()
plist = new List<PeriodicAction>(periodicTimerSounds);
foreach (var snd in plist)
{
snd.CurrentPeriodMs -= TIMER_BASIC_INTERVAL;
snd.CurrentPeriodMs -= (double)1 / (double)TIMER_BASIC_1MS_COUNT;
if (snd.CurrentPeriodMs > 0)
continue;

Expand Down
29 changes: 13 additions & 16 deletions src/mamidimemo/instruments/SoundBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public virtual void KeyOn()
if (ParentModule.ChannelTypes[NoteOnEvent.Channel] == ChannelType.Drum)
{
gateTime = ParentModule.DrumTimbres[NoteOnEvent.NoteNumber].GateTime;
HighPrecisionTimer.SetFixedPeriodicCallback(new Func<object, double>(processGateTime), null);
HighPrecisionTimer.SetPeriodicCallback(new Func<object, double>(processGateTime), gateTime, null);
}
}

Expand All @@ -161,9 +161,9 @@ private double processGateTime(object state)
if (!IsDisposed && !IsSoundOff)
{
if (gateTime > 0)
gateTime -= HighPrecisionTimer.TIMER_BASIC_INTERVAL;
gateTime -= 1 / HighPrecisionTimer.TIMER_BASIC_1MS_COUNT;
if (gateTime > 0)
return HighPrecisionTimer.TIMER_BASIC_INTERVAL;
return gateTime;

KeyOff();
}
Expand Down Expand Up @@ -365,7 +365,7 @@ private double processAdsr(object state)
OnVolumeUpdated();

if (AdsrEngine.AdsrState != AdsrState.SoundOff)
return HighPrecisionTimer.TIMER_BASIC_INTERVAL;
return 1;

EnableADSR = false;
SoundOff();
Expand All @@ -392,7 +392,7 @@ private double processPortamento(object state)
if (!IsDisposed && !IsSoundOff && PortamentoEnabled && PortamentoDeltaNoteNumber != 0)
{
//double delta = -portStartNoteDeltSign * 12d / Math.Pow(((double)ParentModule.PortamentoTimes[NoteOnEvent.Channel] / 2d) + 1d, 1.25);
double delta = -portStartNoteDeltSign * PortamentSpeedTable[ParentModule.PortamentoTimes[NoteOnEvent.Channel]] * HighPrecisionTimer.TIMER_BASIC_INTERVAL / 100d;
double delta = -portStartNoteDeltSign * PortamentSpeedTable[ParentModule.PortamentoTimes[NoteOnEvent.Channel]] * HighPrecisionTimer.TIMER_BASIC_1MS_COUNT / 100d;
PortamentoDeltaNoteNumber += delta;

if (portStartNoteDeltSign < 0 && PortamentoDeltaNoteNumber >= 0)
Expand All @@ -403,7 +403,7 @@ private double processPortamento(object state)
OnPitchUpdated();

if (PortamentoDeltaNoteNumber != 0)
return HighPrecisionTimer.TIMER_BASIC_INTERVAL;
return 1;

PortamentoEnabled = false;
}
Expand All @@ -414,15 +414,15 @@ private double processModulation(object state)
{
if (!IsDisposed && !IsSoundOff && ModulationEnabled)
{
double radian = 2 * Math.PI * (modulationStep / HighPrecisionTimer.TIMER_BASIC_HZ);
double radian = 2 * Math.PI * (modulationStep / HighPrecisionTimer.TIMER_BASIC_1KHZ);

double mdepth = 0;
if (ParentModule.ModulationDepthes[NoteOnEvent.Channel] > 64)
{
if (modulationStartCounter < 10d * HighPrecisionTimer.TIMER_BASIC_HZ)
if (modulationStartCounter < 10d * HighPrecisionTimer.TIMER_BASIC_1KHZ)
modulationStartCounter += 1.0;

if (modulationStartCounter > ParentModule.GetModulationDelaySec(NoteOnEvent.Channel) * HighPrecisionTimer.TIMER_BASIC_HZ)
if (modulationStartCounter > ParentModule.GetModulationDelaySec(NoteOnEvent.Channel) * HighPrecisionTimer.TIMER_BASIC_1KHZ)
mdepth = (double)ParentModule.ModulationDepthes[NoteOnEvent.Channel] / 127d;
}
//急激な変化を抑制
Expand All @@ -441,7 +441,7 @@ private double processModulation(object state)

OnPitchUpdated();

return HighPrecisionTimer.TIMER_BASIC_INTERVAL;
return 1;
}
return -1;
}
Expand Down Expand Up @@ -520,8 +520,7 @@ public bool ModulationEnabled
f_modulationEnabled = value;
}
if (f_modulationEnabled)
HighPrecisionTimer.SetFixedPeriodicCallback(new Func<object, double>(processModulation), null);
//HighPrecisionTimer.SetPeriodicCallback(new Func<object, double>(processModulation), HighPrecisionTimer.TIMER_BASIC_INTERVAL, null);
HighPrecisionTimer.SetPeriodicCallback(new Func<object, double>(processModulation), 1, null);
}
}
}
Expand Down Expand Up @@ -556,8 +555,7 @@ public bool PortamentoEnabled
f_portamentoEnabled = value;

if (f_portamentoEnabled)
HighPrecisionTimer.SetFixedPeriodicCallback(new Func<object, double>(processPortamento), null);
//HighPrecisionTimer.SetPeriodicCallback(new Func<object, double>(processPortamento), HighPrecisionTimer.TIMER_BASIC_INTERVAL, null);
HighPrecisionTimer.SetPeriodicCallback(new Func<object, double>(processPortamento), 1, null);
}
}
}
Expand All @@ -582,8 +580,7 @@ public bool EnableADSR
f_AdsrEnabled = value;

if (f_AdsrEnabled)
HighPrecisionTimer.SetFixedPeriodicCallback(new Func<object, double>(processAdsr), null);
//HighPrecisionTimer.SetPeriodicCallback(new Func<object, double>(processAdsr), HighPrecisionTimer.TIMER_BASIC_INTERVAL, null);
HighPrecisionTimer.SetPeriodicCallback(new Func<object, double>(processAdsr), 1, null);
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/mamidimemo/instruments/SoundManagerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ private double processArpeggiatorsForKeyOn(object state)
}

arp.StepCounter += 1;
if (arp.StepCounter == arp.StepNum)
if (arp.StepCounter >= arp.StepNum)
{
// on sound
arp.StepCounter = 0;
Expand Down Expand Up @@ -572,7 +572,7 @@ private double processArpeggiatorsForPitch(object state)
}
}
arp.StepCounter += 1;
if (arp.StepCounter == arp.StepNum)
if (arp.StepCounter >= arp.StepNum)
{
// on sound
arp.StepCounter = 0;
Expand Down Expand Up @@ -856,18 +856,18 @@ private static void setupArp(ArpSettings sds, ArpEngine arp)
var steps = (60d * 1000d / sds.Beat) / (double)sds.ArpResolution;
if (steps < 20)
{
arp.Step = steps / 2;
arp.StepNum = 2;
arp.Step = steps / 10;
arp.StepNum = 10;
}
else if (arp.StepNum < 50)
{
arp.Step = steps / 5;
arp.StepNum = 5;
arp.Step = steps / 25;
arp.StepNum = 25;
}
else
{
arp.Step = steps / 10;
arp.StepNum = 10;
arp.Step = steps / 100;
arp.StepNum = 100;
}
}

Expand Down

0 comments on commit caa5de8

Please sign in to comment.