From caa5de8dc37a583b7a7c976efcac538a0df88418 Mon Sep 17 00:00:00 2001 From: 110-kenichi <110.kenichi@gmail.com> Date: Sun, 9 Aug 2020 22:27:14 +0900 Subject: [PATCH] 2.0.3.0 Improved sounds output timing accuracy. --- src/emu/machine.cpp | 2 +- src/mamidimemo/Gui/FormMain.cs | 18 +++----- src/mamidimemo/instruments/DrumTimbre.cs | 4 +- .../Envelopes/AbstractFxSettingsBase.cs | 4 +- .../instruments/Envelopes/AdsrEngine.cs | 6 +-- .../instruments/Envelopes/ArpSettings.cs | 6 +-- .../instruments/HighPrecisionTimer.cs | 42 ++++++++----------- src/mamidimemo/instruments/SoundBase.cs | 29 ++++++------- .../instruments/SoundManagerBase.cs | 16 +++---- 9 files changed, 55 insertions(+), 72 deletions(-) diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp index e7284bad33d9d..aae25369bca5d 100644 --- a/src/emu/machine.cpp +++ b/src/emu/machine.cpp @@ -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(*this); diff --git a/src/mamidimemo/Gui/FormMain.cs b/src/mamidimemo/Gui/FormMain.cs index 513b80fa24f85..7060e3a145518 100644 --- a/src/mamidimemo/Gui/FormMain.cs +++ b/src/mamidimemo/Gui/FormMain.cs @@ -689,8 +689,6 @@ 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) @@ -698,33 +696,29 @@ private void tabPage1_Paint(object sender, PaintEventArgs e) 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 pts = new List(); 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; @@ -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) diff --git a/src/mamidimemo/instruments/DrumTimbre.cs b/src/mamidimemo/instruments/DrumTimbre.cs index e7904e8e2772f..4debd63623f42 100644 --- a/src/mamidimemo/instruments/DrumTimbre.cs +++ b/src/mamidimemo/instruments/DrumTimbre.cs @@ -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 { @@ -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; } diff --git a/src/mamidimemo/instruments/Envelopes/AbstractFxSettingsBase.cs b/src/mamidimemo/instruments/Envelopes/AbstractFxSettingsBase.cs index 1499446bbcd36..3f375d222e78b 100644 --- a/src/mamidimemo/instruments/Envelopes/AbstractFxSettingsBase.cs +++ b/src/mamidimemo/instruments/Envelopes/AbstractFxSettingsBase.cs @@ -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 { @@ -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; } diff --git a/src/mamidimemo/instruments/Envelopes/AdsrEngine.cs b/src/mamidimemo/instruments/Envelopes/AdsrEngine.cs index fdc4062169975..a84a1884c1dc0 100644 --- a/src/mamidimemo/instruments/Envelopes/AdsrEngine.cs +++ b/src/mamidimemo/instruments/Envelopes/AdsrEngine.cs @@ -64,7 +64,7 @@ public AdsrEngine() /// [sec] 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); } @@ -75,7 +75,7 @@ public void SetAttackRate(double rate) /// [sec] 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); } @@ -86,7 +86,7 @@ public void SetDecayRate(double rate) /// [sec] 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); } diff --git a/src/mamidimemo/instruments/Envelopes/ArpSettings.cs b/src/mamidimemo/instruments/Envelopes/ArpSettings.cs index 7c6e0c5f17b75..c811b0f02bca2 100644 --- a/src/mamidimemo/instruments/Envelopes/ArpSettings.cs +++ b/src/mamidimemo/instruments/Envelopes/ArpSettings.cs @@ -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; } } } @@ -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; } } } @@ -223,7 +223,7 @@ public bool KeySync /// public ArpSettings() { - ArpStep = (60d * HighPrecisionTimer.TIMER_BASIC_HZ / Beat) / (double)ArpResolution; + ArpStep = (60d * HighPrecisionTimer.TIMER_BASIC_1KHZ / Beat) / (double)ArpResolution; } #region Etc diff --git a/src/mamidimemo/instruments/HighPrecisionTimer.cs b/src/mamidimemo/instruments/HighPrecisionTimer.cs index 8bc215da1dbe2..effe806bae881 100644 --- a/src/mamidimemo/instruments/HighPrecisionTimer.cs +++ b/src/mamidimemo/instruments/HighPrecisionTimer.cs @@ -12,20 +12,21 @@ namespace zanac.MAmidiMEmo.Instruments { + /// + /// 高精度タイマー + /// public static class HighPrecisionTimer { - private const int WAIT_TIMEOUT = 120 * 1000; - /// - /// Periodic Action Timer Interval[ms] + /// Periodic Action Timer Interval[1 ms] /// - public const uint TIMER_BASIC_INTERVAL = 1; + public const uint TIMER_BASIC_1MS_COUNT = 100; /// - /// Periodic Action Timer Hz + /// Periodic Action Timer Hz() /// - public const double TIMER_BASIC_HZ = 1000d / TIMER_BASIC_INTERVAL; + public const double TIMER_BASIC_1KHZ = 1000d; private static List periodicTimerSounds = new List(); @@ -34,40 +35,33 @@ static HighPrecisionTimer() Program.ShuttingDown += Program_ShuttingDown; } + private static bool shutDown; + /// /// /// - /// - /// - /// - public static void SetPeriodicCallback(Func action, double periodMs, object state) - { - action(state); - lock (periodicTimerSounds) - periodicTimerSounds.Add(new PeriodicAction(action, periodMs, state)); - } - - private static bool shutDown; - + /// + /// private static void Program_ShuttingDown(object sender, EventArgs e) { shutDown = true; } - /// /// /// - /// - public static void SetFixedPeriodicCallback(Func action, object state) + /// + /// + /// + public static void SetPeriodicCallback(Func 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)); } /// - /// + /// MAMEから呼ばれる /// public static void SoundTimerCallback() { @@ -79,7 +73,7 @@ public static void SoundTimerCallback() plist = new List(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; diff --git a/src/mamidimemo/instruments/SoundBase.cs b/src/mamidimemo/instruments/SoundBase.cs index 2e15cf331e8b9..6a17d94d24b03 100644 --- a/src/mamidimemo/instruments/SoundBase.cs +++ b/src/mamidimemo/instruments/SoundBase.cs @@ -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(processGateTime), null); + HighPrecisionTimer.SetPeriodicCallback(new Func(processGateTime), gateTime, null); } } @@ -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(); } @@ -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(); @@ -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) @@ -403,7 +403,7 @@ private double processPortamento(object state) OnPitchUpdated(); if (PortamentoDeltaNoteNumber != 0) - return HighPrecisionTimer.TIMER_BASIC_INTERVAL; + return 1; PortamentoEnabled = false; } @@ -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; } //急激な変化を抑制 @@ -441,7 +441,7 @@ private double processModulation(object state) OnPitchUpdated(); - return HighPrecisionTimer.TIMER_BASIC_INTERVAL; + return 1; } return -1; } @@ -520,8 +520,7 @@ public bool ModulationEnabled f_modulationEnabled = value; } if (f_modulationEnabled) - HighPrecisionTimer.SetFixedPeriodicCallback(new Func(processModulation), null); - //HighPrecisionTimer.SetPeriodicCallback(new Func(processModulation), HighPrecisionTimer.TIMER_BASIC_INTERVAL, null); + HighPrecisionTimer.SetPeriodicCallback(new Func(processModulation), 1, null); } } } @@ -556,8 +555,7 @@ public bool PortamentoEnabled f_portamentoEnabled = value; if (f_portamentoEnabled) - HighPrecisionTimer.SetFixedPeriodicCallback(new Func(processPortamento), null); - //HighPrecisionTimer.SetPeriodicCallback(new Func(processPortamento), HighPrecisionTimer.TIMER_BASIC_INTERVAL, null); + HighPrecisionTimer.SetPeriodicCallback(new Func(processPortamento), 1, null); } } } @@ -582,8 +580,7 @@ public bool EnableADSR f_AdsrEnabled = value; if (f_AdsrEnabled) - HighPrecisionTimer.SetFixedPeriodicCallback(new Func(processAdsr), null); - //HighPrecisionTimer.SetPeriodicCallback(new Func(processAdsr), HighPrecisionTimer.TIMER_BASIC_INTERVAL, null); + HighPrecisionTimer.SetPeriodicCallback(new Func(processAdsr), 1, null); } } } diff --git a/src/mamidimemo/instruments/SoundManagerBase.cs b/src/mamidimemo/instruments/SoundManagerBase.cs index 1e3f33faeaced..341cc389b351e 100644 --- a/src/mamidimemo/instruments/SoundManagerBase.cs +++ b/src/mamidimemo/instruments/SoundManagerBase.cs @@ -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; @@ -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; @@ -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; } }