From 69b1485a22dc2b8a2cfe0bd10edcbaad0da0cf6e Mon Sep 17 00:00:00 2001 From: strangerke Date: Thu, 12 May 2011 01:13:57 +0200 Subject: GIT: Clean up: Suppress SVN tags, now useless --- audio/softsynth/adlib.cpp | 3 --- audio/softsynth/appleiigs.cpp | 3 --- audio/softsynth/cms.cpp | 3 --- audio/softsynth/cms.h | 3 --- audio/softsynth/eas.cpp | 3 --- audio/softsynth/emumidi.h | 3 --- audio/softsynth/fluidsynth.cpp | 3 --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 3 --- audio/softsynth/fmtowns_pc98/towns_audio.h | 3 --- audio/softsynth/fmtowns_pc98/towns_euphony.cpp | 3 --- audio/softsynth/fmtowns_pc98/towns_euphony.h | 3 --- audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp | 3 --- audio/softsynth/fmtowns_pc98/towns_pc98_driver.h | 3 --- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 3 --- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 3 --- audio/softsynth/mt32.cpp | 3 --- audio/softsynth/mt32/freeverb.cpp | 3 --- audio/softsynth/mt32/freeverb.h | 3 --- audio/softsynth/opl/dosbox.cpp | 3 --- audio/softsynth/opl/dosbox.h | 3 --- audio/softsynth/opl/mame.cpp | 3 --- audio/softsynth/opl/mame.h | 3 --- audio/softsynth/pcspk.cpp | 3 --- audio/softsynth/pcspk.h | 3 --- audio/softsynth/sid.cpp | 3 --- audio/softsynth/sid.h | 3 --- audio/softsynth/wave6581.cpp | 3 --- audio/softsynth/ym2612.cpp | 3 --- audio/softsynth/ym2612.h | 3 --- 29 files changed, 87 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/adlib.cpp b/audio/softsynth/adlib.cpp index 9fec74c9d6..60de8fad60 100644 --- a/audio/softsynth/adlib.cpp +++ b/audio/softsynth/adlib.cpp @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #include "audio/softsynth/emumidi.h" diff --git a/audio/softsynth/appleiigs.cpp b/audio/softsynth/appleiigs.cpp index 80159c79ce..6ee70d1202 100644 --- a/audio/softsynth/appleiigs.cpp +++ b/audio/softsynth/appleiigs.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * -* $URL$ -* $Id$ -* */ #include "audio/null.h" diff --git a/audio/softsynth/cms.cpp b/audio/softsynth/cms.cpp index fcc15f127e..67eacd1a41 100644 --- a/audio/softsynth/cms.cpp +++ b/audio/softsynth/cms.cpp @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #include "audio/softsynth/cms.h" diff --git a/audio/softsynth/cms.h b/audio/softsynth/cms.h index d5bb7f0a42..48064746a8 100644 --- a/audio/softsynth/cms.h +++ b/audio/softsynth/cms.h @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #ifndef SOUND_SOFTSYNTH_CMS_H diff --git a/audio/softsynth/eas.cpp b/audio/softsynth/eas.cpp index 7d17655d20..d829e3b39a 100644 --- a/audio/softsynth/eas.cpp +++ b/audio/softsynth/eas.cpp @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #include "common/scummsys.h" diff --git a/audio/softsynth/emumidi.h b/audio/softsynth/emumidi.h index 190b70c392..f3d7645f87 100644 --- a/audio/softsynth/emumidi.h +++ b/audio/softsynth/emumidi.h @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #ifndef SOUND_SOFTSYNTH_EMUMIDI_H diff --git a/audio/softsynth/fluidsynth.cpp b/audio/softsynth/fluidsynth.cpp index a4877a4ec1..2451336784 100644 --- a/audio/softsynth/fluidsynth.cpp +++ b/audio/softsynth/fluidsynth.cpp @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #include "common/scummsys.h" diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 7b6658ab3a..ee8327fba7 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #include "audio/softsynth/fmtowns_pc98/towns_audio.h" diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.h b/audio/softsynth/fmtowns_pc98/towns_audio.h index 2819ab2d57..f3d863b949 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.h +++ b/audio/softsynth/fmtowns_pc98/towns_audio.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #ifndef TOWNS_AUDIO_H diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp index cd3a348b85..49c156f142 100644 --- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #include "audio/softsynth/fmtowns_pc98/towns_euphony.h" diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.h b/audio/softsynth/fmtowns_pc98/towns_euphony.h index dc40373913..a8f22f593a 100644 --- a/audio/softsynth/fmtowns_pc98/towns_euphony.h +++ b/audio/softsynth/fmtowns_pc98/towns_euphony.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #ifndef TOWNS_EUP_H diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp index a551276ab1..289cc95863 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #include "audio/softsynth/fmtowns_pc98/towns_pc98_driver.h" diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h index 1227e2626a..46ee23895b 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #ifndef TOWNS_PC98_AUDIODRIVER_H diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index 9d3751a0cc..57ab8d9e1f 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h" diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index 2b916b2cdc..5edd1a3ab8 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #ifndef TOWNS_PC98_FMSYNTH_H diff --git a/audio/softsynth/mt32.cpp b/audio/softsynth/mt32.cpp index 5371be60b3..a9a612f410 100644 --- a/audio/softsynth/mt32.cpp +++ b/audio/softsynth/mt32.cpp @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #include "common/scummsys.h" diff --git a/audio/softsynth/mt32/freeverb.cpp b/audio/softsynth/mt32/freeverb.cpp index c62d4f2cf3..67f065c20e 100644 --- a/audio/softsynth/mt32/freeverb.cpp +++ b/audio/softsynth/mt32/freeverb.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ // Comb filter implementation diff --git a/audio/softsynth/mt32/freeverb.h b/audio/softsynth/mt32/freeverb.h index 8310aca3e3..39ae463970 100644 --- a/audio/softsynth/mt32/freeverb.h +++ b/audio/softsynth/mt32/freeverb.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ // Macro for killing denormalled numbers diff --git a/audio/softsynth/opl/dosbox.cpp b/audio/softsynth/opl/dosbox.cpp index 7a494d70ec..e039845b8f 100644 --- a/audio/softsynth/opl/dosbox.cpp +++ b/audio/softsynth/opl/dosbox.cpp @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ /* diff --git a/audio/softsynth/opl/dosbox.h b/audio/softsynth/opl/dosbox.h index 1e92c7f7c9..125dde8aec 100644 --- a/audio/softsynth/opl/dosbox.h +++ b/audio/softsynth/opl/dosbox.h @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ /* diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp index 5d790f924f..b380a15345 100644 --- a/audio/softsynth/opl/mame.cpp +++ b/audio/softsynth/opl/mame.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * * LGPL licensed version of MAMEs fmopl (V0.37a modified) by * Tatsuyuki Satoh. Included from LGPL'ed AdPlug. */ diff --git a/audio/softsynth/opl/mame.h b/audio/softsynth/opl/mame.h index 4314aa6dba..4c40949483 100644 --- a/audio/softsynth/opl/mame.h +++ b/audio/softsynth/opl/mame.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * * LGPL licensed version of MAMEs fmopl (V0.37a modified) by * Tatsuyuki Satoh. Included from LGPL'ed AdPlug. */ diff --git a/audio/softsynth/pcspk.cpp b/audio/softsynth/pcspk.cpp index 947c142b73..66af968463 100644 --- a/audio/softsynth/pcspk.cpp +++ b/audio/softsynth/pcspk.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * -* $URL$ -* $Id$ -* */ #include "audio/softsynth/pcspk.h" diff --git a/audio/softsynth/pcspk.h b/audio/softsynth/pcspk.h index 8f01fa852b..3641400b1f 100644 --- a/audio/softsynth/pcspk.h +++ b/audio/softsynth/pcspk.h @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #ifndef SOUND_SOFTSYNTH_PCSPK_H diff --git a/audio/softsynth/sid.cpp b/audio/softsynth/sid.cpp index 40dc50e972..4b8f783ef4 100644 --- a/audio/softsynth/sid.cpp +++ b/audio/softsynth/sid.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ /* diff --git a/audio/softsynth/sid.h b/audio/softsynth/sid.h index d6e402dc3b..a015242844 100644 --- a/audio/softsynth/sid.h +++ b/audio/softsynth/sid.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ /* diff --git a/audio/softsynth/wave6581.cpp b/audio/softsynth/wave6581.cpp index d1ddad1623..63e08fb113 100644 --- a/audio/softsynth/wave6581.cpp +++ b/audio/softsynth/wave6581.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ /* diff --git a/audio/softsynth/ym2612.cpp b/audio/softsynth/ym2612.cpp index 162c92f05a..d966595ae4 100644 --- a/audio/softsynth/ym2612.cpp +++ b/audio/softsynth/ym2612.cpp @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #include diff --git a/audio/softsynth/ym2612.h b/audio/softsynth/ym2612.h index f652b2d9e4..de91fc98e9 100644 --- a/audio/softsynth/ym2612.h +++ b/audio/softsynth/ym2612.h @@ -17,9 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ */ #ifndef SOUND_SOFTSYNTH_Y2612_H -- cgit v1.2.3 From a03ed0a3f7643417bbc169301a4fdd23043f3134 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 17 May 2011 12:57:46 +0200 Subject: AUDIO: Fix typo --- audio/softsynth/mt32/partial.cpp | 2 +- audio/softsynth/mt32/synth.cpp | 2 +- audio/softsynth/mt32/tables.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/mt32/partial.cpp b/audio/softsynth/mt32/partial.cpp index 5ba9ef6145..d06634dc91 100644 --- a/audio/softsynth/mt32/partial.cpp +++ b/audio/softsynth/mt32/partial.cpp @@ -28,7 +28,7 @@ #if defined(MACOSX) || defined(SOLARIS) || defined(__MINGW32__) // Older versions of Mac OS X didn't supply a powf function, so using it // will cause a binary incompatibility when trying to run a binary built -// on a newer OS X release on an olderr one. And Solaris 8 doesn't provide +// on a newer OS X release on an older one. And Solaris 8 doesn't provide // powf, floorf, fabsf etc. at all. // Cross-compiled MinGW32 toolchains suffer from a cross-compile bug in // libstdc++. math/stubs.o should be empty, but it comes with a symbol for diff --git a/audio/softsynth/mt32/synth.cpp b/audio/softsynth/mt32/synth.cpp index 112527cc71..5e74b262ae 100644 --- a/audio/softsynth/mt32/synth.cpp +++ b/audio/softsynth/mt32/synth.cpp @@ -34,7 +34,7 @@ #if defined(MACOSX) || defined(SOLARIS) || defined(__MINGW32__) // Older versions of Mac OS X didn't supply a powf function, so using it // will cause a binary incompatibility when trying to run a binary built -// on a newer OS X release on an olderr one. And Solaris 8 doesn't provide +// on a newer OS X release on an older one. And Solaris 8 doesn't provide // powf, floorf, fabsf etc. at all. // Cross-compiled MinGW32 toolchains suffer from a cross-compile bug in // libstdc++. math/stubs.o should be empty, but it comes with a symbol for diff --git a/audio/softsynth/mt32/tables.cpp b/audio/softsynth/mt32/tables.cpp index eba4d2a520..4bb6a06053 100644 --- a/audio/softsynth/mt32/tables.cpp +++ b/audio/softsynth/mt32/tables.cpp @@ -28,7 +28,7 @@ #if defined(MACOSX) || defined(SOLARIS) || defined(__MINGW32__) // Older versions of Mac OS X didn't supply a powf function, so using it // will cause a binary incompatibility when trying to run a binary built -// on a newer OS X release on an olderr one. And Solaris 8 doesn't provide +// on a newer OS X release on an older one. And Solaris 8 doesn't provide // powf, floorf, fabsf etc. at all. // Cross-compiled MinGW32 toolchains suffer from a cross-compile bug in // libstdc++. math/stubs.o should be empty, but it comes with a symbol for -- cgit v1.2.3 From 9b2ef340dceebc3db36519051e45af0fd9477850 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 17 May 2011 12:58:34 +0200 Subject: COMMON: Forbid use of some more symbols --- audio/softsynth/mt32/tables.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'audio/softsynth') diff --git a/audio/softsynth/mt32/tables.cpp b/audio/softsynth/mt32/tables.cpp index 4bb6a06053..25ee0436db 100644 --- a/audio/softsynth/mt32/tables.cpp +++ b/audio/softsynth/mt32/tables.cpp @@ -19,6 +19,10 @@ * IN THE SOFTWARE. */ + +// FIXME: Avoid using rand +#define FORBIDDEN_SYMBOL_EXCEPTION_rand + #include #include #include -- cgit v1.2.3 From 5c34e33c2c27b2b5083199b40306370d732f4e53 Mon Sep 17 00:00:00 2001 From: athrxx Date: Fri, 29 Apr 2011 22:16:02 +0200 Subject: FM-TOWNS AUDIO: Some more midi driver code for FM-TOWNS monkey2 and indy4 --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 239 +++++++ audio/softsynth/fmtowns_pc98/towns_midi.h | 70 ++ .../softsynth/fmtowns_pc98/towns_pc98_plugins.cpp | 87 +++ audio/softsynth/ym2612.cpp | 790 --------------------- audio/softsynth/ym2612.h | 176 ----- 5 files changed, 396 insertions(+), 966 deletions(-) create mode 100644 audio/softsynth/fmtowns_pc98/towns_midi.cpp create mode 100644 audio/softsynth/fmtowns_pc98/towns_midi.h create mode 100644 audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp delete mode 100644 audio/softsynth/ym2612.cpp delete mode 100644 audio/softsynth/ym2612.h (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp new file mode 100644 index 0000000000..c223d44c11 --- /dev/null +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -0,0 +1,239 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: $ + * $Id: $ + */ + +#include "audio/softsynth/fmtowns_pc98/towns_midi.h" +#include "common/textconsole.h" + +class MidiChannel_TOWNS : public MidiChannel { +public: + MidiChannel_TOWNS(MidiDriver_TOWNS *driver); + ~MidiChannel_TOWNS(); + + MidiDriver *device() { return _driver; } + byte getNumber() { return 0; } + void release(); + + void send(uint32 b); + + void noteOff(byte note); + void noteOn(byte note, byte velocity); + void programChange(byte program); + void pitchBend(int16 bend); + void controlChange(byte control, byte value); + void pitchBendFactor(byte value); + void priority(byte value); + + void sysEx_customInstrument(uint32 type, const byte *instr); + +private: + MidiDriver_TOWNS *_driver; +}; + +MidiChannel_TOWNS::MidiChannel_TOWNS(MidiDriver_TOWNS *driver) : MidiChannel(), _driver(driver) { + +} + +MidiChannel_TOWNS::~MidiChannel_TOWNS() { + +} + +void MidiChannel_TOWNS::release() { + +} + +void MidiChannel_TOWNS::send(uint32 b) { + +} + +void MidiChannel_TOWNS::noteOff(byte note) { + +} + +void MidiChannel_TOWNS::noteOn(byte note, byte velocity) { + +} + +void MidiChannel_TOWNS::programChange(byte program) { + +} + +void MidiChannel_TOWNS::pitchBend(int16 bend) { + +} + +void MidiChannel_TOWNS::controlChange(byte control, byte value) { + +} + +void MidiChannel_TOWNS::pitchBendFactor(byte value) { + +} + +void MidiChannel_TOWNS::priority(byte value) { + +} + +void MidiChannel_TOWNS::sysEx_customInstrument(uint32 type, const byte *instr) { + +} + +MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timerBpara(0), _open(false) { + _intf = new TownsAudioInterface(mixer, this); + _channels = new MidiChannel_TOWNS*[16]; + for (int i = 0; i < 16; i++) + _channels[i] = new MidiChannel_TOWNS(this); + + _tickCounter = 0; + _curChan = 0; + //unbuffered write: _intf->callback(17, part, reg, val); + //buffered write: _intf->callback(19, part, reg, val); +} + +MidiDriver_TOWNS::~MidiDriver_TOWNS() { + close(); + delete _intf; + setTimerCallback(0, 0); + + for (int i = 0; i < 16; i++) + delete _channels[i]; + delete[] _channels; +} + +int MidiDriver_TOWNS::open() { + if (_open) + return MERR_ALREADY_OPEN; + + if (!_intf->init()) + return MERR_CANNOT_CONNECT; + + _intf->callback(0); + + _intf->callback(21, 255, 1); + _intf->callback(21, 0, 1); + _intf->callback(22, 255, 221); + + _intf->callback(33, 8); + _intf->setSoundEffectChanMask(~0x3f); + + _open = true; + + return 0; +} + +void MidiDriver_TOWNS::close() { + _open = false; +} + +void MidiDriver_TOWNS::send(uint32 b) { + byte param2 = (b >> 16) & 0xFF; + byte param1 = (b >> 8) & 0xFF; + byte cmd = b & 0xF0; + + /*AdLibPart *part; + if (chan == 9) + part = &_percussion; + else**/ + MidiChannel_TOWNS *c = _channels[b & 0x0F]; + + switch (cmd) { + case 0x80: + //part->noteOff(param1); + break; + case 0x90: + //part->noteOn(param1, param2); + if (param2) + c->noteOn(param1, param2); + else + c->noteOff(param1); + break; + case 0xB0: + // supported: 1, 7, 0x40 + c->controlChange(param1, param2); + break; + case 0xC0: + c->programChange(param1); + break; + case 0xE0: + //part->pitchBend((param1 | (param2 << 7)) - 0x2000); + c->pitchBend((param1 | (param2 << 7)) - 0x2000); + break; + case 0xF0: + warning("MidiDriver_ADLIB: Receiving SysEx command on a send() call"); + break; + + default: + break; + } +} + +void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { + _timerBproc = timer_proc; + _timerBpara = timer_param; +} + +uint32 MidiDriver_TOWNS::getBaseTempo() { + return 0; +} + +MidiChannel *MidiDriver_TOWNS::allocateChannel() { + MidiChannel *res = 0; + + for (int i = 0; i < 6; i++) { + if (++_curChan == 6) + _curChan = 0; + + //if (_channels[i]-> //// ) + // return _channels[i]; + + } + + //if (res) + // res->noteOff(); + + return res; +} + +MidiChannel *MidiDriver_TOWNS::getPercussionChannel() { + return 0; +} + +void MidiDriver_TOWNS::timerCallback(int timerId) { + if (!_open) + return; + + switch (timerId) { + case 1: + if (_timerBproc) { + _timerBproc(_timerBpara); + _tickCounter += 10000; + while (_tickCounter >= 4167) { + _tickCounter -= 4167; + //_timerBproc(_timerBpara); + } + } + break; + default: + break; + } +} diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h new file mode 100644 index 0000000000..658c5a456b --- /dev/null +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -0,0 +1,70 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: $ + * $Id: $ + */ + +#ifndef TOWNS_MIDI_H +#define TOWNS_MIDI_H + +#include "audio/mididrv.h" +#include "audio/softsynth/fmtowns_pc98/towns_audio.h" + +class MidiChannel_TOWNS; +class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver { +friend class MidiChannel_TOWNS; +public: + MidiDriver_TOWNS(Audio::Mixer *mixer); + ~MidiDriver_TOWNS(); + + int open(); + bool isOpen() const { return _open; } + void close(); + void send(uint32 b); + //virtual uint32 property(int prop, uint32 param) { return 0; } + //virtual void sysEx(const byte *msg, uint16 length) { } + //virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { } + //virtual void metaEvent(byte type, byte *data, uint16 length) { } + void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc); + uint32 getBaseTempo(); + MidiChannel *allocateChannel(); + MidiChannel *getPercussionChannel(); + + void timerCallback(int timerId); + + TownsAudioInterface *intf() { return _intf; } + +private: + MidiChannel_TOWNS **_channels; + + Common::TimerManager::TimerProc _timerBproc; + void *_timerBpara; + + TownsAudioInterface *_intf; + + uint32 _tickCounter; + uint8 _curChan; + + bool _open; +}; + +#endif + diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp new file mode 100644 index 0000000000..bbde75eb66 --- /dev/null +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp @@ -0,0 +1,87 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: $ + * $Id: $ + */ + +#include "audio/softsynth/fmtowns_pc98/towns_midi.h" +#include "audio/musicplugin.h" +#include "common/translation.h" +#include "common/error.h" + + +class TownsEmuMusicPlugin : public MusicPluginObject { +public: + const char *getName() const { + return _s("FM-Towns Audio"); + } + + const char *getId() const { + return "towns"; + } + + MusicDevices getDevices() const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; +}; + +MusicDevices TownsEmuMusicPlugin::getDevices() const { + MusicDevices devices; + devices.push_back(MusicDevice(this, "", MT_TOWNS)); + return devices; +} + +Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { + *mididriver = new MidiDriver_TOWNS(g_system->getMixer()); + return Common::kNoError; +} + +class PC98EmuMusicPlugin : public MusicPluginObject { +public: + const char *getName() const { + return _s("PC-98 Audio"); + } + + const char *getId() const { + return "pc98"; + } + + MusicDevices getDevices() const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; +}; + +MusicDevices PC98EmuMusicPlugin::getDevices() const { + MusicDevices devices; + devices.push_back(MusicDevice(this, "", MT_PC98)); + return devices; +} + +Common::Error PC98EmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { + //*mididriver = /**/ + return Common::kNoError; +} + +//#if PLUGIN_ENABLED_DYNAMIC(TOWNS) + //REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin); + //REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin); +//#else + REGISTER_PLUGIN_STATIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin); + REGISTER_PLUGIN_STATIC(PC98, PLUGIN_TYPE_MUSIC, PC98EmuMusicPlugin); +//#endif diff --git a/audio/softsynth/ym2612.cpp b/audio/softsynth/ym2612.cpp deleted file mode 100644 index d966595ae4..0000000000 --- a/audio/softsynth/ym2612.cpp +++ /dev/null @@ -1,790 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include - -#include "audio/softsynth/ym2612.h" -#include "common/util.h" -#include "audio/musicplugin.h" -#include "common/error.h" -#include "common/system.h" -#include "common/textconsole.h" -#include "common/translation.h" -#include "common/types.h" - -//////////////////////////////////////// -// -// Miscellaneous -// -//////////////////////////////////////// - -static int *sintbl = 0; -static int *powtbl = 0; -static int *frequencyTable = 0; -static int *keycodeTable = 0; -static int *keyscaleTable = 0; -static int *attackOut = 0; - - -//////////////////////////////////////// -// -// Operator2612 implementation -// -//////////////////////////////////////// - -Operator2612::Operator2612 (Voice2612 *owner) : - _owner (owner), - _state (_s_ready), - _currentLevel ((int32)0x7f << 15), - _phase (0), - _lastOutput (0), - _feedbackLevel (0), - _detune (0), - _multiple (1), - _keyScale (0), - _specifiedTotalLevel (127), - _specifiedAttackRate (0), - _specifiedDecayRate (0), - _specifiedSustainRate (0), - _specifiedReleaseRate (15) { - velocity(0); -} - -Operator2612::~Operator2612() -{ } - -void Operator2612::velocity(int velo) { - _velocity = velo; - _totalLevel = ((int32)_specifiedTotalLevel << 15) + - ((int32)(127-_velocity) << 13); - _sustainLevel = ((int32)_specifiedSustainLevel << 17); -} - -void Operator2612::feedbackLevel(int level) { - _feedbackLevel = level; -} - -void Operator2612::setInstrument(byte const *instrument) { - _detune = (instrument[8] >> 4) & 7; - _multiple = instrument[8] & 15; - _specifiedTotalLevel = instrument[12] & 127; - _keyScale = (instrument[16] >> 6) & 3; - _specifiedAttackRate = instrument[16] & 31; - _specifiedDecayRate = instrument[20] & 31; - _specifiedSustainRate = instrument[24] & 31; - _specifiedSustainLevel = (instrument[28] >> 4) & 15; - _specifiedReleaseRate = instrument[28] & 15; - _state = _s_ready; - velocity(_velocity); -} - -void Operator2612::keyOn() { - _state = _s_attacking; - _tickCount = 0; - _phase = 0; - _currentLevel = ((int32)0x7f << 15); -} - -void Operator2612::keyOff() { - if (_state != _s_ready) - _state = _s_releasing; -} - -void Operator2612::frequency(int freq) { - double value; // Use for intermediate computations to avoid int64 arithmetic - int r; - - _frequency = freq / _owner->_rate; - - r = _specifiedAttackRate; - if (r != 0) { - r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale)); - if (r >= 64) - r = 63; - } - - r = 63 - r; - if (_specifiedTotalLevel >= 128) - value = 0; - else { - value = powtbl[(r&3) << 7]; - value *= 1 << (r >> 2); - value *= 41; - value /= 1 << (15 + 5); - value *= 127 - _specifiedTotalLevel; - value /= 127; - } - _attackTime = (int32) value; // 1 ?? == (1 << 12) - if (_attackTime > 0) - _attackTime = (1 << (12+10)) / (_owner->_rate * _attackTime); - - r = _specifiedDecayRate; - if (r != 0) { - r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale)); - if (r >= 64) - r = 63; - } - value = (double) powtbl[(r&3) << 7] * (0x10 << (r>>2)) / 31; - _decayRate = (int32) value / _owner->_rate; - - r = _specifiedSustainRate; - if (r != 0) { - r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale)); - if (r >= 64) - r = 63; - } - value = (double) powtbl[(r&3) << 7] * (0x10 << (r>>2)) / 31; - _sustainRate = (int32) value / _owner->_rate; - - r = _specifiedReleaseRate; - if (r != 0) { - r = r * 2 + 1; // (Translated) I cannot know whether the timing is a good choice or not - r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale)); - // KS - if (r >= 64) - r = 63; - } - value = (double) powtbl[(r&3) << 7] * (0x10 << (r>>2)) / 31; - _releaseRate = (int32) value / _owner->_rate; -} - -void Operator2612::nextTick(const int *phasebuf, int *outbuf, int buflen) { - if (_state == _s_ready) - return; - if (_state == _s_attacking && _attackTime <= 0) { - _currentLevel = 0; - _state = _s_decaying; - } - - int32 levelIncrement = 0; - int32 target = 0; - State next_state = _s_ready; - const int32 zero_level = ((int32)0x7f << 15); - const int phaseIncrement = (_multiple > 0) ? (_frequency * _multiple) : (_frequency / 2); - - int32 output = _lastOutput; - int32 level = _currentLevel + _totalLevel; - - while (buflen) { - switch (_state) { - case _s_ready: - return; - case _s_attacking: - next_state = _s_attacking; - break; - case _s_decaying: - levelIncrement = _decayRate; - target = _sustainLevel + _totalLevel; - next_state = _s_sustaining; - break; - case _s_sustaining: - levelIncrement = _sustainRate; - target = zero_level + _totalLevel; - next_state = _s_ready; - break; - case _s_releasing: - levelIncrement = _releaseRate; - target = zero_level + _totalLevel; - next_state = _s_ready; - break; - } - - bool switching = false; - do { - if (next_state == _s_attacking) { - // Attack phase - ++_tickCount; - int i = (int) (_tickCount * _attackTime); - if (i >= 1024) { - level = _totalLevel; - _state = _s_decaying; - switching = true; - } else { - level = (attackOut[i] << (31 - 8 - 16)) + _totalLevel; - } - } else { - // Decay, Sustain and Release phases - level += levelIncrement; - if (level >= target) { - level = target; - _state = next_state; - switching = true; - } - } - - if (level < zero_level) { - int phaseShift = *phasebuf >> 2; - if (_feedbackLevel) - phaseShift += (output << (_feedbackLevel - 1)) / 1024; - output = sintbl[((_phase >> 7) + phaseShift) & 0x7ff]; - output >>= (level >> 18); - // Here is the original code, which requires 64-bit ints -// output *= powtbl[511 - ((level>>25)&511)]; -// output >>= 16; -// output >>= 1; - // And here's our 32-bit trick for doing it. (Props to Fingolfin!) - // Result varies from original code by max of 1. -// int powVal = powtbl[511 - ((level>>9)&511)]; -// int outputHI = output / 256; -// int powHI = powVal / 256; -// output = (outputHI * powHI) / 2 + (outputHI * (powVal % 256) + powHI * (output % 256)) / 512; - // And here's the even faster code. - // Result varies from original code by max of 8. - output = ((output >> 4) * (powtbl[511-((level>>9)&511)] >> 3)) / 1024; - - _phase += phaseIncrement; - _phase &= 0x3ffff; - } else - output = 0; - - *outbuf += output; - --buflen; - ++phasebuf; - ++outbuf; - } while (buflen && !switching); - } - _lastOutput = output; - _currentLevel = level - _totalLevel; -} - -//////////////////////////////////////// -// -// Voice2612 implementation -// -//////////////////////////////////////// - -Voice2612::Voice2612() { - next = 0; - _control7 = 127; - _note = 40; - _frequency = 440; - _frequencyOffs = 0x2000; - _algorithm = 7; - - _buffer = 0; - _buflen = 0; - - int i; - for (i = 0; i < ARRAYSIZE(_opr); ++i) - _opr[i] = new Operator2612 (this); - velocity(0); -} - -Voice2612::~Voice2612() { - int i; - for (i = 0; i < ARRAYSIZE(_opr); ++i) - delete _opr[i]; - free(_buffer); -} - -void Voice2612::velocity(int velo) { - _velocity = velo; -#if 0 - int v = (velo * _control7) >> 7; -#else - int v = velo + (_control7 - 127) * 4; -#endif - bool iscarrier[8][4] = { - { false, false, false, true, }, //0 - { false, false, false, true, }, //1 - { false, false, false, true, }, //2 - { false, false, false, true, }, //3 - { false, true, false, true, }, //4 - { false, true, true, true, }, //5 - { false, true, true, true, }, //6 - { true, true, true, true, }, //7 - }; - int opr; - for (opr = 0; opr < 4; opr++) - if (iscarrier[_algorithm][opr]) - _opr[opr]->velocity(v); - else - _opr[opr]->velocity(127); -} - -void Voice2612::setControlParameter(int control, int value) { - switch (control) { - case 7: - _control7 = value; - velocity(_velocity); - break; - case 123: - // All notes off - noteOff(_note); - }; -} - -void Voice2612::setInstrument(byte const *instrument) { - if (instrument == NULL) - return; - - _algorithm = instrument[32] & 7; - _opr[0]->feedbackLevel((instrument[32] >> 3) & 7); - _opr[1]->feedbackLevel(0); - _opr[2]->feedbackLevel(0); - _opr[3]->feedbackLevel(0); - _opr[0]->setInstrument(instrument + 0); - _opr[1]->setInstrument(instrument + 2); - _opr[2]->setInstrument(instrument + 1); - _opr[3]->setInstrument(instrument + 3); -} - -void Voice2612::nextTick(int *outbuf, int buflen) { - if (_velocity == 0) - return; - - if (_buflen < buflen) { - free(_buffer); - _buflen = buflen; - _buffer = (int *) malloc(sizeof(int) * buflen * 2); - } - - int *buf1 = _buffer; - int *buf2 = _buffer + buflen; - memset(_buffer, 0, sizeof(int) * buflen * 2); - - switch (_algorithm) { - case 0: - _opr[0]->nextTick(buf1, buf2, buflen); - _opr[1]->nextTick(buf2, buf1, buflen); - memset (buf2, 0, sizeof (int) * buflen); - _opr[2]->nextTick(buf1, buf2, buflen); - _opr[3]->nextTick(buf2, outbuf, buflen); - break; - case 1: - _opr[0]->nextTick(buf1, buf2, buflen); - _opr[1]->nextTick(buf1, buf2, buflen); - _opr[2]->nextTick(buf2, buf1, buflen); - _opr[3]->nextTick(buf1, outbuf, buflen); - break; - case 2: - _opr[1]->nextTick(buf1, buf2, buflen); - _opr[2]->nextTick(buf2, buf1, buflen); - memset(buf2, 0, sizeof(int) * buflen); - _opr[0]->nextTick(buf2, buf1, buflen); - _opr[3]->nextTick(buf1, outbuf, buflen); - break; - case 3: - _opr[0]->nextTick(buf1, buf2, buflen); - _opr[1]->nextTick(buf2, buf1, buflen); - memset(buf2, 0, sizeof(int) * buflen); - _opr[2]->nextTick(buf2, buf1, buflen); - _opr[3]->nextTick(buf1, outbuf, buflen); - break; - case 4: - _opr[0]->nextTick(buf1, buf2, buflen); - _opr[1]->nextTick(buf2, outbuf, buflen); - _opr[2]->nextTick(buf1, buf1, buflen); - _opr[3]->nextTick(buf1, outbuf, buflen); - break; - case 5: - _opr[0]->nextTick(buf1, buf2, buflen); - _opr[1]->nextTick(buf2, outbuf, buflen); - _opr[2]->nextTick(buf2, outbuf, buflen); - _opr[3]->nextTick(buf2, outbuf, buflen); - break; - case 6: - _opr[0]->nextTick(buf1, buf2, buflen); - _opr[1]->nextTick(buf2, outbuf, buflen); - _opr[2]->nextTick(buf1, outbuf, buflen); - _opr[3]->nextTick(buf1, outbuf, buflen); - break; - case 7: - _opr[0]->nextTick(buf1, outbuf, buflen); - _opr[1]->nextTick(buf1, outbuf, buflen); - _opr[2]->nextTick(buf1, outbuf, buflen); - _opr[3]->nextTick(buf1, outbuf, buflen); - break; - }; -} - -void Voice2612::noteOn(int n, int onVelo) { - _note = n; - velocity(onVelo); - recalculateFrequency(); - int i; - for (i = 0; i < ARRAYSIZE(_opr); i++) - _opr[i]->keyOn(); -} - -bool Voice2612::noteOff(int note) { - if (_note != note) - return false; - int i; - for (i = 0; i < ARRAYSIZE(_opr); i++) - _opr[i]->keyOff(); - return true; -} - -void Voice2612::pitchBend(int value) { - _frequencyOffs = value; - recalculateFrequency(); -} - -void Voice2612::recalculateFrequency() { - // - // - // - int32 basefreq = frequencyTable[_note]; - int cfreq = frequencyTable[_note - (_note % 12)]; - int oct = _note / 12; - int fnum = (int) (((double)basefreq * (1 << 13)) / cfreq); - fnum += _frequencyOffs - 0x2000; - if (fnum < 0x2000) { - fnum += 0x2000; - oct--; - } - if (fnum >= 0x4000) { - fnum -= 0x2000; - oct++; - } - - // - _frequency = (int) ((frequencyTable[oct*12] * (double)fnum) / 8); - - int i; - for (i = 0; i < ARRAYSIZE(_opr); i++) - _opr[i]->frequency(_frequency); -} - -//////////////////////////////////////// -// -// MidiChannel_YM2612 -// -//////////////////////////////////////// - -MidiChannel_YM2612::MidiChannel_YM2612() { - _voices = 0; - _next_voice = 0; -} - -MidiChannel_YM2612::~MidiChannel_YM2612() { - removeAllVoices(); -} - -void MidiChannel_YM2612::removeAllVoices() { - if (!_voices) - return; - Voice2612 *last, *voice = _voices; - for (; voice; voice = last) { - last = voice->next; - delete voice; - } - _voices = _next_voice = 0; -} - -void MidiChannel_YM2612::noteOn(byte note, byte onVelo) { - if (!_voices) - return; - _next_voice = _next_voice ? _next_voice : _voices; - _next_voice->noteOn(note, onVelo); - _next_voice = _next_voice->next; -} - -void MidiChannel_YM2612::noteOff(byte note) { - if (!_voices) - return; - if (_next_voice == _voices) - _next_voice = 0; - Voice2612 *voice = _next_voice; - do { - if (!voice) - voice = _voices; - if (voice->noteOff(note)) { - _next_voice = voice; - break; - } - voice = voice->next; - } while (voice != _next_voice); -} - -void MidiChannel_YM2612::controlChange(byte control, byte value) { - // - if (control == 121) { - // Reset controller - removeAllVoices(); - } else { - Voice2612 *voice = _voices; - for (; voice; voice = voice->next) - voice->setControlParameter(control, value); - } -} - -void MidiChannel_YM2612::sysEx_customInstrument(uint32 type, const byte *fmInst) { - if (type != 'EUP ') - return; - Voice2612 *voice = new Voice2612; - voice->next = _voices; - _voices = voice; - voice->_rate = _rate; - voice->setInstrument(fmInst); -} - -void MidiChannel_YM2612::pitchBend(int16 value) { - // - Voice2612 *voice = _voices; - for (; voice; voice = voice->next) - voice->pitchBend(value); -} - -void MidiChannel_YM2612::nextTick(int *outbuf, int buflen) { - Voice2612 *voice = _voices; - for (; voice; voice = voice->next) - voice->nextTick(outbuf, buflen); -} - -void MidiChannel_YM2612::rate(uint16 r) { - _rate = r; - Voice2612 *voice = _voices; - for (; voice; voice = voice->next) - voice->_rate = r; -} - -//////////////////////////////////////// -// -// MidiDriver_YM2612 -// -//////////////////////////////////////// - -MidiDriver_YM2612::MidiDriver_YM2612(Audio::Mixer *mixer) - : MidiDriver_Emulated(mixer) { - _next_voice = 0; - - createLookupTables(); - _volume = 256; - int i; - for (i = 0; i < ARRAYSIZE(_channel); i++) - _channel[i] = new MidiChannel_YM2612; - rate(getRate()); -} - -MidiDriver_YM2612::~MidiDriver_YM2612() { - int i; - for (i = 0; i < ARRAYSIZE(_channel); i++) - delete _channel[i]; - removeLookupTables(); -} - -int MidiDriver_YM2612::open() { - if (_isOpen) - return MERR_ALREADY_OPEN; - - MidiDriver_Emulated::open(); - - _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); - return 0; -} - -void MidiDriver_YM2612::close() { - if (!_isOpen) - return; - _isOpen = false; - - _mixer->stopHandle(_mixerSoundHandle); -} - -void MidiDriver_YM2612::send(uint32 b) { - send(b & 0xF, b & 0xFFFFFFF0); -} - -void MidiDriver_YM2612::send(byte chan, uint32 b) { - //byte param3 = (byte) ((b >> 24) & 0xFF); - byte param2 = (byte) ((b >> 16) & 0xFF); - byte param1 = (byte) ((b >> 8) & 0xFF); - byte cmd = (byte) (b & 0xF0); - if (chan > ARRAYSIZE(_channel)) - return; - - switch (cmd) { - case 0x80:// Note Off - _channel[chan]->noteOff(param1); - break; - case 0x90: // Note On - _channel[chan]->noteOn(param1, param2); - break; - case 0xA0: // Aftertouch - break; // Not supported. - case 0xB0: // Control Change - _channel[chan]->controlChange(param1, param2); - break; - case 0xC0: // Program Change - _channel[chan]->programChange(param1); - break; - case 0xD0: // Channel Pressure - break; // Not supported. - case 0xE0: // Pitch Bend - _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000); - break; - case 0xF0: // SysEx - // We should never get here! SysEx information has to be - // sent via high-level semantic methods. - warning("MidiDriver_YM2612: Receiving SysEx command on a send() call"); - break; - - default: - warning("MidiDriver_YM2612: Unknown send() command 0x%02X", cmd); - } -} - -void MidiDriver_YM2612::sysEx(const byte *msg, uint16 length) { - if (msg[0] != 0x7C || msg[1] >= ARRAYSIZE(_channel)) - return; - _channel[msg[1]]->sysEx_customInstrument('EUP ', &msg[2]); -} - -void MidiDriver_YM2612::generateSamples(int16 *data, int len) { - memset(data, 0, 2 * sizeof(int16) * len); - nextTick(data, len); -} - -void MidiDriver_YM2612::nextTick(int16 *buf1, int buflen) { - int *buf0 = (int *)buf1; - - int i; - for (i = 0; i < ARRAYSIZE(_channel); i++) - _channel[i]->nextTick(buf0, buflen); - - for (i = 0; i < buflen; ++i) - buf1[i*2+1] = buf1[i*2] = ((buf0[i] * volume()) >> 10) & 0xffff; -} - -void MidiDriver_YM2612::rate(uint16 r) -{ - int i; - for (i = 0; i < ARRAYSIZE(_channel); i++) - _channel[i]->rate(r); -} - -void MidiDriver_YM2612::createLookupTables() { - { - int i; - sintbl = new int [2048]; - for (i = 0; i < 2048; i++) - sintbl[i] = (int)(0xffff * sin(i/2048.0 * 2.0 * M_PI)); - } - - { - int i; - powtbl = new int [1025]; - for (i = 0; i <= 1024; i++) - powtbl[i] = (int)(0x10000 * pow(2.0, (i - 512) / 512.0)); - } - - { - int i; - int block; - - static int fnum[] = { - 0x026a, 0x028f, 0x02b6, 0x02df, - 0x030b, 0x0339, 0x036a, 0x039e, - 0x03d5, 0x0410, 0x044e, 0x048f, - }; - - // (int)(880.0 * 256.0 * pow(2.0, (note-0x51)/12.0)) - // - frequencyTable = new int [120]; - for (block = -1; block < 9; block++) { - for (i = 0; i < 12; i++) { - double freq = fnum[i] * (166400.0 / 3) * pow(2.0, block-21); - frequencyTable[(block+1)*12+i] = (int)(256.0 * freq); - } - } - - keycodeTable = new int [120]; - // detune - for (block = -1; block < 9; block++) { - for (i = 0; i < 12; i++) { - // see p.204 - int f8 = (fnum[i] >> 7) & 1; - int f9 = (fnum[i] >> 8) & 1; - int f10 = (fnum[i] >> 9) & 1; - int f11 = (fnum[i] >> 10) & 1; - int n4 = f11; - int n3 = (f11&(f10|f9|f8)) | (~f11&f10&f9&f8); - int note = n4*2 + n3; - // see p.207 - keycodeTable[(block+1)*12+i] = block*4 + note; - } - } - } - - { - int freq; - keyscaleTable = new int [8192]; - keyscaleTable[0] = 0; - for (freq = 1; freq < 8192; freq++) { - keyscaleTable[freq] = (int)(log((double)freq) / 9.03 * 32.0) - 1; - // 8368[Hz] (o9c) - } - } - - { - int i; - attackOut = new int [1024]; - for (i = 0; i < 1024; i++) - attackOut[i] = (int)(((0x7fff+0x03a5)*30.0) / (30.0+i)) - 0x03a5; - } -} - -void MidiDriver_YM2612::removeLookupTables() { - delete[] sintbl; - delete[] powtbl; - delete[] frequencyTable; - delete[] keycodeTable; - delete[] keyscaleTable; - delete[] attackOut; - sintbl = powtbl = frequencyTable = keycodeTable = keyscaleTable = attackOut = 0; -} - - -// Plugin interface - -class TownsEmuMusicPlugin : public MusicPluginObject { -public: - const char *getName() const { - return _s("FM Towns Emulator"); - } - - const char *getId() const { - return "towns"; - } - - MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; -}; - -MusicDevices TownsEmuMusicPlugin::getDevices() const { - MusicDevices devices; - devices.push_back(MusicDevice(this, "", MT_TOWNS)); - return devices; -} - -Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { - *mididriver = new MidiDriver_YM2612(g_system->getMixer()); - - return Common::kNoError; -} - -//#if PLUGIN_ENABLED_DYNAMIC(TOWNS) - //REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin); -//#else - REGISTER_PLUGIN_STATIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin); -//#endif diff --git a/audio/softsynth/ym2612.h b/audio/softsynth/ym2612.h deleted file mode 100644 index de91fc98e9..0000000000 --- a/audio/softsynth/ym2612.h +++ /dev/null @@ -1,176 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef SOUND_SOFTSYNTH_Y2612_H -#define SOUND_SOFTSYNTH_Y2612_H - -#include "common/scummsys.h" - -#include "audio/softsynth/emumidi.h" - -//////////////////////////////////////// -// -// Class declarations -// -//////////////////////////////////////// - -class Voice2612; -class Operator2612 { -protected: - Voice2612 *_owner; - enum State { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing }; - State _state; - int32 _currentLevel; - int _frequency; - uint32 _phase; - int _lastOutput; - int _feedbackLevel; - int _detune; - int _multiple; - int32 _totalLevel; - int _keyScale; - int _velocity; - int _specifiedTotalLevel; - int _specifiedAttackRate; - int _specifiedDecayRate; - int _specifiedSustainLevel; - int _specifiedSustainRate; - int _specifiedReleaseRate; - int _tickCount; - int _attackTime; - int32 _decayRate; - int32 _sustainLevel; - int32 _sustainRate; - int32 _releaseRate; - -public: - Operator2612 (Voice2612 *owner); - ~Operator2612(); - void feedbackLevel(int level); - void setInstrument(byte const *instrument); - void velocity(int velo); - void keyOn(); - void keyOff(); - void frequency(int freq); - void nextTick(const int *phaseShift, int *outbuf, int buflen); - bool inUse() { return (_state != _s_ready); } -}; - -class Voice2612 { -public: - Voice2612 *next; - uint16 _rate; - -protected: - Operator2612 *_opr[4]; - int _velocity; - int _control7; - int _note; - int _frequencyOffs; - int _frequency; - int _algorithm; - - int *_buffer; - int _buflen; - -public: - Voice2612(); - ~Voice2612(); - void setControlParameter(int control, int value); - void setInstrument(byte const *instrument); - void velocity(int velo); - void nextTick(int *outbuf, int buflen); - void noteOn(int n, int onVelo); - bool noteOff(int note); - void pitchBend(int value); - void recalculateFrequency(); -}; - -class MidiChannel_YM2612 : public MidiChannel { -protected: - uint16 _rate; - Voice2612 *_voices; - Voice2612 *_next_voice; - -public: - void removeAllVoices(); - void nextTick(int *outbuf, int buflen); - void rate(uint16 r); - -public: - MidiChannel_YM2612(); - virtual ~MidiChannel_YM2612(); - - // MidiChannel interface - MidiDriver *device() { return 0; } - byte getNumber() { return 0; } - void release() { } - void send(uint32 b) { } - void noteOff(byte note); - void noteOn(byte note, byte onVelo); - void programChange(byte program) { } - void pitchBend(int16 value); - void controlChange(byte control, byte value); - void pitchBendFactor(byte value) { } - void sysEx_customInstrument(uint32 type, const byte *instr); -}; - -class MidiDriver_YM2612 : public MidiDriver_Emulated { -protected: - MidiChannel_YM2612 *_channel[16]; - - int _next_voice; - int _volume; - -protected: - void nextTick(int16 *buf1, int buflen); - int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; } - void rate(uint16 r); - - void generateSamples(int16 *buf, int len); - -public: - MidiDriver_YM2612(Audio::Mixer *mixer); - virtual ~MidiDriver_YM2612(); - - static void createLookupTables(); - static void removeLookupTables(); - - int open(); - void close(); - void send(uint32 b); - void send(byte channel, uint32 b); // Supports higher than channel 15 - uint32 property(int prop, uint32 param) { return 0; } - - void setPitchBendRange(byte channel, uint range) { } - void sysEx(const byte *msg, uint16 length); - - MidiChannel *allocateChannel() { return 0; } - MidiChannel *getPercussionChannel() { return 0; } - - - // AudioStream API - bool isStereo() const { return true; } - int getRate() const { return _mixer->getOutputRate(); } -}; - -#endif - -- cgit v1.2.3 From 63a78593516dc428f77ac01d90bc228fcf01de5d Mon Sep 17 00:00:00 2001 From: athrxx Date: Sat, 30 Apr 2011 15:11:13 +0200 Subject: FM-TOWNS AUDIO: Change internal interface layout --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 400 ++++++++++++++++----- audio/softsynth/fmtowns_pc98/towns_audio.h | 130 +------ .../softsynth/fmtowns_pc98/towns_pc98_plugins.cpp | 1 + 3 files changed, 322 insertions(+), 209 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index ee8327fba7..065532f526 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -21,13 +21,16 @@ */ #include "audio/softsynth/fmtowns_pc98/towns_audio.h" +#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h" + #include "common/endian.h" #include "common/util.h" +#include "common/textconsole.h" #include "backends/audiocd/audiocd.h" class TownsAudio_PcmChannel { -friend class TownsAudioInterface; +friend class TownsAudioInterfaceIntern; public: TownsAudio_PcmChannel(); ~TownsAudio_PcmChannel(); @@ -77,7 +80,7 @@ private: }; class TownsAudio_WaveTable { -friend class TownsAudioInterface; +friend class TownsAudioInterfaceIntern; public: TownsAudio_WaveTable(); ~TownsAudio_WaveTable(); @@ -98,14 +101,160 @@ private: int8 *data; }; -TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns), +class TownsAudioInterfaceIntern : public TownsPC98_FmSynth { +public: + TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); + ~TownsAudioInterfaceIntern(); + + static TownsAudioInterfaceIntern *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); + static void releaseRef(); + bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver); + + bool init(); + + int callback(int command, ...); + int processCommand(int command, va_list &args); + + void setMusicVolume(int volume); + void setSoundEffectVolume(int volume); + // Defines the channels used as sound effect channels for the purpose of ScummVM GUI volume control. + // The first 6 bits are the 6 fm channels. The next 8 bits are pcm channels. + void setSoundEffectChanMask(int mask); + +private: + void nextTickEx(int32 *buffer, uint32 bufferSize); + + void timerCallbackA(); + void timerCallbackB(); + + typedef int (TownsAudioInterfaceIntern::*TownsAudioIntfCallback)(va_list &); + const TownsAudioIntfCallback *_intfOpcodes; + + int intf_reset(va_list &args); + int intf_keyOn(va_list &args); + int intf_keyOff(va_list &args); + int intf_setPanPos(va_list &args); + int intf_setInstrument(va_list &args); + int intf_loadInstrument(va_list &args); + int intf_setPitch(va_list &args); + int intf_setLevel(va_list &args); + int intf_chanOff(va_list &args); + int intf_writeReg(va_list &args); + int intf_writeRegBuffer(va_list &args); + int intf_readRegBuffer(va_list &args); + int intf_setTimerA(va_list &args); + int intf_setTimerB(va_list &args); + int intf_enableTimerA(va_list &args); + int intf_enableTimerB(va_list &args); + int intf_loadSamples(va_list &args); + int intf_reserveEffectChannels(va_list &args); + int intf_loadWaveTable(va_list &args); + int intf_unloadWaveTable(va_list &args); + int intf_pcmPlayEffect(va_list &args); + int intf_pcmChanOff(va_list &args); + int intf_pcmEffectPlaying(va_list &args); + int intf_fmKeyOn(va_list &args); + int intf_fmKeyOff(va_list &args); + int intf_fmSetPanPos(va_list &args); + int intf_fmSetInstrument(va_list &args); + int intf_fmLoadInstrument(va_list &args); + int intf_fmSetPitch(va_list &args); + int intf_fmSetLevel(va_list &args); + int intf_fmReset(va_list &args); + int intf_setOutputVolume(va_list &args); + int intf_resetOutputVolume(va_list &args); + int intf_updateOutputVolume(va_list &args); + int intf_cdaToggle(va_list &args); + int intf_pcmUpdateEnvelopeGenerator(va_list &args); + + int intf_notImpl(va_list &args); + + void fmReset(); + int fmKeyOn(int chan, int note, int velo); + int fmKeyOff(int chan); + int fmChanOff(int chan); + int fmSetPanPos(int chan, int mode); + int fmSetInstrument(int chan, int instrId); + int fmLoadInstrument(int instrId, const uint8 *data); + int fmSetPitch(int chan, int pitch); + int fmSetLevel(int chan, int lvl); + + void bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value); + + uint8 _fmChanPlaying; + uint8 _fmChanNote[6]; + int16 _fmChanPitch[6]; + + uint8 *_fmSaveReg[2]; + uint8 *_fmInstruments; + + void pcmReset(); + int pcmKeyOn(int chan, int note, int velo); + int pcmKeyOff(int chan); + int pcmChanOff(int chan); + int pcmSetPanPos(int chan, int mode); + int pcmSetInstrument(int chan, int instrId); + int pcmLoadInstrument(int instrId, const uint8 *data); + int pcmSetPitch(int chan, int pitch); + int pcmSetLevel(int chan, int lvl); + void pcmUpdateEnvelopeGenerator(int chan); + + TownsAudio_PcmChannel *_pcmChan; + uint8 _pcmChanOut; + uint8 _pcmChanReserved; + uint8 _pcmChanKeyPressed; + uint8 _pcmChanEffectPlaying; + uint8 _pcmChanKeyPlaying; + + uint8 _pcmChanNote[8]; + uint8 _pcmChanVelo[8]; + uint8 _pcmChanLevel[8]; + + uint8 _numReservedChannels; + uint8 *_pcmInstruments; + + TownsAudio_WaveTable *_waveTables; + uint8 _numWaveTables; + uint32 _waveTablesTotalDataSize; + + void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w); + + void updateOutputVolume(); + uint8 _outputVolumeFlags; + uint8 _outputLevel[16]; + uint8 _outputMuteFlags; + + const float _baserate; + uint32 _timerBase; + uint32 _tickLength; + uint32 _timer; + + uint16 _musicVolume; + uint16 _sfxVolume; + int _pcmSfxChanMask; + + TownsAudioInterfacePluginDriver *_drv; + bool _ready; + + static TownsAudioInterfaceIntern *_refInstance; + static int _refCount; + + static const uint8 _chanFlags[]; + static const uint16 _frequency[]; + static const uint8 _carrier[]; + static const uint8 _fmDefaultInstrument[]; + static const uint16 _pcmPhase1[]; + static const uint16 _pcmPhase2[]; +}; + +TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns), _fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0), _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver), _pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume), _outputVolumeFlags(0), _outputMuteFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0), _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _ready(false) { -#define INTCB(x) &TownsAudioInterface::intf_##x +#define INTCB(x) &TownsAudioInterfaceIntern::intf_##x static const TownsAudioIntfCallback intfCb[] = { // 0 INTCB(reset), @@ -222,7 +371,7 @@ TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfac _tickLength = 2 * _timerBase; } -TownsAudioInterface::~TownsAudioInterface() { +TownsAudioInterfaceIntern::~TownsAudioInterfaceIntern() { _ready = false; deinit(); @@ -234,7 +383,47 @@ TownsAudioInterface::~TownsAudioInterface() { delete[] _pcmChan; } -bool TownsAudioInterface::init() { +TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) { + _refCount++; + if (_refCount == 1 && _refInstance == 0) + _refInstance = new TownsAudioInterfaceIntern(mixer, driver); + else if (_refCount < 2 || _refInstance == 0) + error("TownsAudioInterfaceIntern::addNewRef(): Internal reference management failure"); + else if (!_refInstance->checkPluginDriver(driver)) + error("TownsAudioInterfaceIntern::addNewRef(): Plugin driver conflict"); + + return _refInstance; +} + +void TownsAudioInterfaceIntern::releaseRef() { + if (!_refCount) + return; + + _refCount--; + + if (!_refCount) { + delete _refInstance; + _refInstance = 0; + } +} + +bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDriver *driver) { + if (_refCount <= 1) + return true; + + Common::StackLock lock(_mutex); + + if (_drv) { + if (driver && driver != _drv) + return false; + } else { + _drv = driver; + } + + return true; +} + +bool TownsAudioInterfaceIntern::init() { if (_ready) return true; @@ -258,41 +447,46 @@ bool TownsAudioInterface::init() { return true; } -int TownsAudioInterface::callback(int command, ...) { +int TownsAudioInterfaceIntern::callback(int command, ...) { if (!_ready) return 1; va_list args; va_start(args, command); - if (command > 81) { - va_end(args); - return 4; - } - - int res = (this->*_intfOpcodes[command])(args); + int res = processCommand(command, args); va_end(args); return res; } -void TownsAudioInterface::setMusicVolume(int volume) { +int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) { + if (!_ready) + return 1; + + if (command < 0 || command > 81) + return 4; + + return (this->*_intfOpcodes[command])(args); +} + +void TownsAudioInterfaceIntern::setMusicVolume(int volume) { _musicVolume = CLIP(volume, 0, Audio::Mixer::kMaxMixerVolume); setVolumeIntern(_musicVolume, _sfxVolume); } -void TownsAudioInterface::setSoundEffectVolume(int volume) { +void TownsAudioInterfaceIntern::setSoundEffectVolume(int volume) { _sfxVolume = CLIP(volume, 0, Audio::Mixer::kMaxMixerVolume); setVolumeIntern(_musicVolume, _sfxVolume); } -void TownsAudioInterface::setSoundEffectChanMask(int mask) { +void TownsAudioInterfaceIntern::setSoundEffectChanMask(int mask) { _pcmSfxChanMask = mask >> 6; mask &= 0x3f; setVolumeChannelMasks(~mask, mask); } -void TownsAudioInterface::nextTickEx(int32 *buffer, uint32 bufferSize) { +void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) { if (!_ready) return; @@ -343,13 +537,13 @@ void TownsAudioInterface::nextTickEx(int32 *buffer, uint32 bufferSize) { } } -void TownsAudioInterface::timerCallbackA() { +void TownsAudioInterfaceIntern::timerCallbackA() { Common::StackLock lock(_mutex); if (_drv && _ready) _drv->timerCallback(0); } -void TownsAudioInterface::timerCallbackB() { +void TownsAudioInterfaceIntern::timerCallbackB() { Common::StackLock lock(_mutex); if (_ready) { if (_drv) @@ -358,62 +552,62 @@ void TownsAudioInterface::timerCallbackB() { } } -int TownsAudioInterface::intf_reset(va_list &args) { +int TownsAudioInterfaceIntern::intf_reset(va_list &args) { fmReset(); pcmReset(); callback(68); return 0; } -int TownsAudioInterface::intf_keyOn(va_list &args) { +int TownsAudioInterfaceIntern::intf_keyOn(va_list &args) { int chan = va_arg(args, int); int note = va_arg(args, int); int velo = va_arg(args, int); return (chan & 0x40) ? pcmKeyOn(chan, note, velo) : fmKeyOn(chan, note, velo); } -int TownsAudioInterface::intf_keyOff(va_list &args) { +int TownsAudioInterfaceIntern::intf_keyOff(va_list &args) { int chan = va_arg(args, int); return (chan & 0x40) ? pcmKeyOff(chan) : fmKeyOff(chan); } -int TownsAudioInterface::intf_setPanPos(va_list &args) { +int TownsAudioInterfaceIntern::intf_setPanPos(va_list &args) { int chan = va_arg(args, int); int mode = va_arg(args, int); return (chan & 0x40) ? pcmSetPanPos(chan, mode) : fmSetPanPos(chan, mode); } -int TownsAudioInterface::intf_setInstrument(va_list &args) { +int TownsAudioInterfaceIntern::intf_setInstrument(va_list &args) { int chan = va_arg(args, int); int instrId = va_arg(args, int); return (chan & 0x40) ? pcmSetInstrument(chan, instrId) : fmSetInstrument(chan, instrId); } -int TownsAudioInterface::intf_loadInstrument(va_list &args) { +int TownsAudioInterfaceIntern::intf_loadInstrument(va_list &args) { int chanType = va_arg(args, int); int instrId = va_arg(args, int); uint8 *instrData = va_arg(args, uint8 *); return (chanType & 0x40) ? pcmLoadInstrument(instrId, instrData) : fmLoadInstrument(instrId, instrData); } -int TownsAudioInterface::intf_setPitch(va_list &args) { +int TownsAudioInterfaceIntern::intf_setPitch(va_list &args) { int chan = va_arg(args, int); int16 pitch = (int16)(va_arg(args, int) & 0xffff); return (chan & 0x40) ? pcmSetPitch(chan, pitch) : fmSetPitch(chan, pitch); } -int TownsAudioInterface::intf_setLevel(va_list &args) { +int TownsAudioInterfaceIntern::intf_setLevel(va_list &args) { int chan = va_arg(args, int); int lvl = va_arg(args, int); return (chan & 0x40) ? pcmSetLevel(chan, lvl) : fmSetLevel(chan, lvl); } -int TownsAudioInterface::intf_chanOff(va_list &args) { +int TownsAudioInterfaceIntern::intf_chanOff(va_list &args) { int chan = va_arg(args, int); return (chan & 0x40) ? pcmChanOff(chan) : fmChanOff(chan); } -int TownsAudioInterface::intf_writeReg(va_list &args) { +int TownsAudioInterfaceIntern::intf_writeReg(va_list &args) { int part = va_arg(args, int) ? 1 : 0; int reg = va_arg(args, int); int val = va_arg(args, int); @@ -424,7 +618,7 @@ int TownsAudioInterface::intf_writeReg(va_list &args) { return 0; } -int TownsAudioInterface::intf_writeRegBuffer(va_list &args) { +int TownsAudioInterfaceIntern::intf_writeRegBuffer(va_list &args) { int part = va_arg(args, int) ? 1 : 0; int reg = va_arg(args, int); int val = va_arg(args, int); @@ -436,7 +630,7 @@ int TownsAudioInterface::intf_writeRegBuffer(va_list &args) { return 0; } -int TownsAudioInterface::intf_readRegBuffer(va_list &args) { +int TownsAudioInterfaceIntern::intf_readRegBuffer(va_list &args) { int part = va_arg(args, int) ? 1 : 0; int reg = va_arg(args, int); uint8 *dst = va_arg(args, uint8 *); @@ -449,7 +643,7 @@ int TownsAudioInterface::intf_readRegBuffer(va_list &args) { return 0; } -int TownsAudioInterface::intf_setTimerA(va_list &args) { +int TownsAudioInterfaceIntern::intf_setTimerA(va_list &args) { int enable = va_arg(args, int); int tempo = va_arg(args, int); @@ -464,7 +658,7 @@ int TownsAudioInterface::intf_setTimerA(va_list &args) { return 0; } -int TownsAudioInterface::intf_setTimerB(va_list &args) { +int TownsAudioInterfaceIntern::intf_setTimerB(va_list &args) { int enable = va_arg(args, int); int tempo = va_arg(args, int); @@ -478,17 +672,17 @@ int TownsAudioInterface::intf_setTimerB(va_list &args) { return 0; } -int TownsAudioInterface::intf_enableTimerA(va_list &args) { +int TownsAudioInterfaceIntern::intf_enableTimerA(va_list &args) { bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x15); return 0; } -int TownsAudioInterface::intf_enableTimerB(va_list &args) { +int TownsAudioInterfaceIntern::intf_enableTimerB(va_list &args) { bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x2a); return 0; } -int TownsAudioInterface::intf_loadSamples(va_list &args) { +int TownsAudioInterfaceIntern::intf_loadSamples(va_list &args) { uint32 dest = va_arg(args, uint32); int size = va_arg(args, int); uint8 *src = va_arg(args, uint8*); @@ -511,7 +705,7 @@ int TownsAudioInterface::intf_loadSamples(va_list &args) { return 0; } -int TownsAudioInterface::intf_reserveEffectChannels(va_list &args) { +int TownsAudioInterfaceIntern::intf_reserveEffectChannels(va_list &args) { int numChan = va_arg(args, int); if (numChan > 8) return 3; @@ -543,7 +737,7 @@ int TownsAudioInterface::intf_reserveEffectChannels(va_list &args) { return 0; } -int TownsAudioInterface::intf_loadWaveTable(va_list &args) { +int TownsAudioInterfaceIntern::intf_loadWaveTable(va_list &args) { uint8 *data = va_arg(args, uint8 *); if (_numWaveTables > 127) return 3; @@ -570,7 +764,7 @@ int TownsAudioInterface::intf_loadWaveTable(va_list &args) { return 0; } -int TownsAudioInterface::intf_unloadWaveTable(va_list &args) { +int TownsAudioInterfaceIntern::intf_unloadWaveTable(va_list &args) { int id = va_arg(args, int); if (id == -1) { @@ -597,7 +791,7 @@ int TownsAudioInterface::intf_unloadWaveTable(va_list &args) { return 0; } -int TownsAudioInterface::intf_pcmPlayEffect(va_list &args) { +int TownsAudioInterfaceIntern::intf_pcmPlayEffect(va_list &args) { int chan = va_arg(args, int); int note = va_arg(args, int); int velo = va_arg(args, int); @@ -647,13 +841,13 @@ int TownsAudioInterface::intf_pcmPlayEffect(va_list &args) { return 0; } -int TownsAudioInterface::intf_pcmChanOff(va_list &args) { +int TownsAudioInterfaceIntern::intf_pcmChanOff(va_list &args) { int chan = va_arg(args, int); pcmChanOff(chan); return 0; } -int TownsAudioInterface::intf_pcmEffectPlaying(va_list &args) { +int TownsAudioInterfaceIntern::intf_pcmEffectPlaying(va_list &args) { int chan = va_arg(args, int); if (chan < 0x40 || chan > 0x47) return 1; @@ -661,54 +855,54 @@ int TownsAudioInterface::intf_pcmEffectPlaying(va_list &args) { return (_pcmChanEffectPlaying & _chanFlags[chan]) ? 1 : 0; } -int TownsAudioInterface::intf_fmKeyOn(va_list &args) { +int TownsAudioInterfaceIntern::intf_fmKeyOn(va_list &args) { int chan = va_arg(args, int); int note = va_arg(args, int); int velo = va_arg(args, int); return fmKeyOn(chan, note, velo); } -int TownsAudioInterface::intf_fmKeyOff(va_list &args) { +int TownsAudioInterfaceIntern::intf_fmKeyOff(va_list &args) { int chan = va_arg(args, int); return fmKeyOff(chan); } -int TownsAudioInterface::intf_fmSetPanPos(va_list &args) { +int TownsAudioInterfaceIntern::intf_fmSetPanPos(va_list &args) { int chan = va_arg(args, int); int mode = va_arg(args, int); return fmSetPanPos(chan, mode); } -int TownsAudioInterface::intf_fmSetInstrument(va_list &args) { +int TownsAudioInterfaceIntern::intf_fmSetInstrument(va_list &args) { int chan = va_arg(args, int); int instrId = va_arg(args, int); return fmSetInstrument(chan, instrId); } -int TownsAudioInterface::intf_fmLoadInstrument(va_list &args) { +int TownsAudioInterfaceIntern::intf_fmLoadInstrument(va_list &args) { int instrId = va_arg(args, int); uint8 *instrData = va_arg(args, uint8 *); return fmLoadInstrument(instrId, instrData); } -int TownsAudioInterface::intf_fmSetPitch(va_list &args) { +int TownsAudioInterfaceIntern::intf_fmSetPitch(va_list &args) { int chan = va_arg(args, int); uint16 freq = va_arg(args, int) & 0xffff; return fmSetPitch(chan, freq); } -int TownsAudioInterface::intf_fmSetLevel(va_list &args) { +int TownsAudioInterfaceIntern::intf_fmSetLevel(va_list &args) { int chan = va_arg(args, int); int lvl = va_arg(args, int); return fmSetLevel(chan, lvl); } -int TownsAudioInterface::intf_fmReset(va_list &args) { +int TownsAudioInterfaceIntern::intf_fmReset(va_list &args) { fmReset(); return 0; } -int TownsAudioInterface::intf_setOutputVolume(va_list &args) { +int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) { int chanType = va_arg(args, int); int left = va_arg(args, int); int right = va_arg(args, int); @@ -743,7 +937,7 @@ int TownsAudioInterface::intf_setOutputVolume(va_list &args) { return 0; } -int TownsAudioInterface::intf_resetOutputVolume(va_list &args) { +int TownsAudioInterfaceIntern::intf_resetOutputVolume(va_list &args) { memset(_outputLevel, 0, sizeof(_outputLevel)); _outputMuteFlags = 0; _outputVolumeFlags = 0; @@ -751,30 +945,30 @@ int TownsAudioInterface::intf_resetOutputVolume(va_list &args) { return 0; } -int TownsAudioInterface::intf_updateOutputVolume(va_list &args) { +int TownsAudioInterfaceIntern::intf_updateOutputVolume(va_list &args) { int flags = va_arg(args, int); _outputMuteFlags = flags & 3; updateOutputVolume(); return 0; } -int TownsAudioInterface::intf_cdaToggle(va_list &args) { +int TownsAudioInterfaceIntern::intf_cdaToggle(va_list &args) { //int mode = va_arg(args, int); //_unkMask = mode ? 0x7f : 0x3f; return 0; } -int TownsAudioInterface::intf_pcmUpdateEnvelopeGenerator(va_list &args) { +int TownsAudioInterfaceIntern::intf_pcmUpdateEnvelopeGenerator(va_list &args) { for (int i = 0; i < 8; i++) pcmUpdateEnvelopeGenerator(i); return 0; } -int TownsAudioInterface::intf_notImpl(va_list &args) { +int TownsAudioInterfaceIntern::intf_notImpl(va_list &args) { return 4; } -void TownsAudioInterface::fmReset() { +void TownsAudioInterfaceIntern::fmReset() { TownsPC98_FmSynth::reset(); _fmChanPlaying = 0; @@ -802,7 +996,7 @@ void TownsAudioInterface::fmReset() { } } -int TownsAudioInterface::fmKeyOn(int chan, int note, int velo) { +int TownsAudioInterfaceIntern::fmKeyOn(int chan, int note, int velo) { if (chan > 5) return 1; if (note < 12 || note > 107 || (velo & 0x80)) @@ -882,7 +1076,7 @@ int TownsAudioInterface::fmKeyOn(int chan, int note, int velo) { return 0; } -int TownsAudioInterface::fmKeyOff(int chan) { +int TownsAudioInterfaceIntern::fmKeyOff(int chan) { if (chan > 5) return 1; _fmChanPlaying &= ~_chanFlags[chan]; @@ -892,7 +1086,7 @@ int TownsAudioInterface::fmKeyOff(int chan) { return 0; } -int TownsAudioInterface::fmChanOff(int chan) { +int TownsAudioInterfaceIntern::fmChanOff(int chan) { if (chan > 5) return 1; _fmChanPlaying &= ~_chanFlags[chan]; @@ -910,7 +1104,7 @@ int TownsAudioInterface::fmChanOff(int chan) { return 0; } -int TownsAudioInterface::fmSetPanPos(int chan, int value) { +int TownsAudioInterfaceIntern::fmSetPanPos(int chan, int value) { if (chan > 5) return 1; @@ -929,7 +1123,7 @@ int TownsAudioInterface::fmSetPanPos(int chan, int value) { return 0; } -int TownsAudioInterface::fmSetInstrument(int chan, int instrId) { +int TownsAudioInterfaceIntern::fmSetInstrument(int chan, int instrId) { if (chan > 5) return 1; if (instrId > 127) @@ -973,7 +1167,7 @@ int TownsAudioInterface::fmSetInstrument(int chan, int instrId) { return 0; } -int TownsAudioInterface::fmLoadInstrument(int instrId, const uint8 *data) { +int TownsAudioInterfaceIntern::fmLoadInstrument(int instrId, const uint8 *data) { if (instrId > 127) return 3; assert(data); @@ -981,7 +1175,7 @@ int TownsAudioInterface::fmLoadInstrument(int instrId, const uint8 *data) { return 0; } -int TownsAudioInterface::fmSetPitch(int chan, int pitch) { +int TownsAudioInterfaceIntern::fmSetPitch(int chan, int pitch) { if (chan > 5) return 1; @@ -1068,7 +1262,7 @@ int TownsAudioInterface::fmSetPitch(int chan, int pitch) { return 0; } -int TownsAudioInterface::fmSetLevel(int chan, int lvl) { +int TownsAudioInterfaceIntern::fmSetLevel(int chan, int lvl) { if (chan > 5) return 1; if (lvl > 127) @@ -1091,12 +1285,12 @@ int TownsAudioInterface::fmSetLevel(int chan, int lvl) { return 0; } -void TownsAudioInterface::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) { +void TownsAudioInterfaceIntern::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) { _fmSaveReg[part][regAddress] = value; writeReg(part, regAddress, value); } -void TownsAudioInterface::pcmReset() { +void TownsAudioInterfaceIntern::pcmReset() { _pcmChanOut = 0; _pcmChanReserved = _pcmChanKeyPressed = _pcmChanEffectPlaying = _pcmChanKeyPlaying = 0; _numReservedChannels = 0; @@ -1124,7 +1318,7 @@ void TownsAudioInterface::pcmReset() { } } -int TownsAudioInterface::pcmKeyOn(int chan, int note, int velo) { +int TownsAudioInterfaceIntern::pcmKeyOn(int chan, int note, int velo) { if (chan < 0x40 || chan > 0x47) return 1; @@ -1195,7 +1389,7 @@ int TownsAudioInterface::pcmKeyOn(int chan, int note, int velo) { return 0; } -int TownsAudioInterface::pcmKeyOff(int chan) { +int TownsAudioInterfaceIntern::pcmKeyOff(int chan) { if (chan < 0x40 || chan > 0x47) return 1; @@ -1205,7 +1399,7 @@ int TownsAudioInterface::pcmKeyOff(int chan) { return 0; } -int TownsAudioInterface::pcmChanOff(int chan) { +int TownsAudioInterfaceIntern::pcmChanOff(int chan) { if (chan < 0x40 || chan > 0x47) return 1; @@ -1219,7 +1413,7 @@ int TownsAudioInterface::pcmChanOff(int chan) { return 0; } -int TownsAudioInterface::pcmSetPanPos(int chan, int mode) { +int TownsAudioInterfaceIntern::pcmSetPanPos(int chan, int mode) { if (chan > 0x47) return 1; if (mode & 0x80) @@ -1242,7 +1436,7 @@ int TownsAudioInterface::pcmSetPanPos(int chan, int mode) { return 0; } -int TownsAudioInterface::pcmSetInstrument(int chan, int instrId) { +int TownsAudioInterfaceIntern::pcmSetInstrument(int chan, int instrId) { if (chan > 0x47) return 1; if (instrId > 31) @@ -1252,7 +1446,7 @@ int TownsAudioInterface::pcmSetInstrument(int chan, int instrId) { return 0; } -int TownsAudioInterface::pcmLoadInstrument(int instrId, const uint8 *data) { +int TownsAudioInterfaceIntern::pcmLoadInstrument(int instrId, const uint8 *data) { if (instrId > 31) return 3; assert(data); @@ -1260,7 +1454,7 @@ int TownsAudioInterface::pcmLoadInstrument(int instrId, const uint8 *data) { return 0; } -int TownsAudioInterface::pcmSetPitch(int chan, int pitch) { +int TownsAudioInterfaceIntern::pcmSetPitch(int chan, int pitch) { if (chan > 0x47) return 1; @@ -1290,7 +1484,7 @@ int TownsAudioInterface::pcmSetPitch(int chan, int pitch) { return 0; } -int TownsAudioInterface::pcmSetLevel(int chan, int lvl) { +int TownsAudioInterfaceIntern::pcmSetLevel(int chan, int lvl) { if (chan > 0x47) return 1; @@ -1319,7 +1513,7 @@ int TownsAudioInterface::pcmSetLevel(int chan, int lvl) { return 0; } -void TownsAudioInterface::pcmUpdateEnvelopeGenerator(int chan) { +void TownsAudioInterfaceIntern::pcmUpdateEnvelopeGenerator(int chan) { TownsAudio_PcmChannel *p = &_pcmChan[chan]; if (!p->envCurrentLevel) { _pcmChanKeyPlaying &= ~_chanFlags[chan]; @@ -1361,7 +1555,7 @@ void TownsAudioInterface::pcmUpdateEnvelopeGenerator(int chan) { p->velo = (p->envCurrentLevel >> 8) << 1; } -void TownsAudioInterface::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) { +void TownsAudioInterfaceIntern::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) { int8 diff = p->note - w->baseNote; uint16 r = w->rate + w->rateOffs; uint16 bl = 0; @@ -1390,7 +1584,7 @@ void TownsAudioInterface::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_ p->step = (s * p->stepPitch) >> 14; } -void TownsAudioInterface::updateOutputVolume() { +void TownsAudioInterfaceIntern::updateOutputVolume() { // FM Towns seems to support volumes of 0 - 63 for each channel. // We recalculate sane values for our 0 to 255 volume range and // balance values for our -128 to 127 volume range @@ -1405,30 +1599,34 @@ void TownsAudioInterface::updateOutputVolume() { g_system->getAudioCDManager()->setBalance(balance); } -const uint8 TownsAudioInterface::_chanFlags[] = { +TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::_refInstance = 0; + +int TownsAudioInterfaceIntern::_refCount = 0; + +const uint8 TownsAudioInterfaceIntern::_chanFlags[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; -const uint16 TownsAudioInterface::_frequency[] = { +const uint16 TownsAudioInterfaceIntern::_frequency[] = { 0x028C, 0x02B4, 0x02DC, 0x030A, 0x0338, 0x0368, 0x039C, 0x03D4, 0x040E, 0x044A, 0x048C, 0x04D0 }; -const uint8 TownsAudioInterface::_carrier[] = { +const uint8 TownsAudioInterfaceIntern::_carrier[] = { 0x10, 0x10, 0x10, 0x10, 0x30, 0x70, 0x70, 0xF0 }; -const uint8 TownsAudioInterface::_fmDefaultInstrument[] = { +const uint8 TownsAudioInterfaceIntern::_fmDefaultInstrument[] = { 0x45, 0x4C, 0x45, 0x50, 0x49, 0x41, 0x4E, 0x4F, 0x01, 0x0A, 0x02, 0x01, 0x1E, 0x32, 0x05, 0x00, 0x9C, 0xDC, 0x9C, 0xDC, 0x07, 0x03, 0x14, 0x08, 0x00, 0x03, 0x05, 0x05, 0x55, 0x45, 0x27, 0xA7, 0x04, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const uint16 TownsAudioInterface::_pcmPhase1[] = { +const uint16 TownsAudioInterfaceIntern::_pcmPhase1[] = { 0x879B, 0x0F37, 0x1F58, 0x306E, 0x4288, 0x55B6, 0x6A08, 0x7F8F, 0x965E, 0xAE88, 0xC882, 0xE341 }; -const uint16 TownsAudioInterface::_pcmPhase2[] = { +const uint16 TownsAudioInterfaceIntern::_pcmPhase2[] = { 0xFEFE, 0xF1A0, 0xE411, 0xD744, 0xCB2F, 0xBFC7, 0xB504, 0xAAE2, 0xA144, 0x9827, 0x8FAC }; @@ -1579,3 +1777,37 @@ void TownsAudio_WaveTable::clear() { data = 0; } +TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) { + _intf = TownsAudioInterfaceIntern::addNewRef(mixer, driver); +} + +TownsAudioInterface::~TownsAudioInterface() { + TownsAudioInterfaceIntern::releaseRef(); + _intf = 0; +} + +bool TownsAudioInterface::init() { + return _intf->init(); +} + +int TownsAudioInterface::callback(int command, ...) { + va_list args; + va_start(args, command); + + int res = _intf->processCommand(command, args); + + va_end(args); + return res; +} + +void TownsAudioInterface::setMusicVolume(int volume) { + _intf->setMusicVolume(volume); +} + +void TownsAudioInterface::setSoundEffectVolume(int volume) { + _intf->setSoundEffectVolume(volume); +} + +void TownsAudioInterface::setSoundEffectChanMask(int mask) { + _intf->setSoundEffectChanMask(mask); +} \ No newline at end of file diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.h b/audio/softsynth/fmtowns_pc98/towns_audio.h index f3d863b949..2c58d46d06 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.h +++ b/audio/softsynth/fmtowns_pc98/towns_audio.h @@ -23,7 +23,9 @@ #ifndef TOWNS_AUDIO_H #define TOWNS_AUDIO_H -#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h" +#include "audio/mixer.h" + +class TownsAudioInterfaceIntern; class TownsAudioInterfacePluginDriver { public: @@ -31,10 +33,7 @@ public: virtual void timerCallback(int timerId) = 0; }; -class TownsAudio_PcmChannel; -class TownsAudio_WaveTable; - -class TownsAudioInterface : public TownsPC98_FmSynth { +class TownsAudioInterface { public: TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); ~TownsAudioInterface(); @@ -50,126 +49,7 @@ public: void setSoundEffectChanMask(int mask); private: - void nextTickEx(int32 *buffer, uint32 bufferSize); - - void timerCallbackA(); - void timerCallbackB(); - - typedef int (TownsAudioInterface::*TownsAudioIntfCallback)(va_list &); - const TownsAudioIntfCallback *_intfOpcodes; - - int intf_reset(va_list &args); - int intf_keyOn(va_list &args); - int intf_keyOff(va_list &args); - int intf_setPanPos(va_list &args); - int intf_setInstrument(va_list &args); - int intf_loadInstrument(va_list &args); - int intf_setPitch(va_list &args); - int intf_setLevel(va_list &args); - int intf_chanOff(va_list &args); - int intf_writeReg(va_list &args); - int intf_writeRegBuffer(va_list &args); - int intf_readRegBuffer(va_list &args); - int intf_setTimerA(va_list &args); - int intf_setTimerB(va_list &args); - int intf_enableTimerA(va_list &args); - int intf_enableTimerB(va_list &args); - int intf_loadSamples(va_list &args); - int intf_reserveEffectChannels(va_list &args); - int intf_loadWaveTable(va_list &args); - int intf_unloadWaveTable(va_list &args); - int intf_pcmPlayEffect(va_list &args); - int intf_pcmChanOff(va_list &args); - int intf_pcmEffectPlaying(va_list &args); - int intf_fmKeyOn(va_list &args); - int intf_fmKeyOff(va_list &args); - int intf_fmSetPanPos(va_list &args); - int intf_fmSetInstrument(va_list &args); - int intf_fmLoadInstrument(va_list &args); - int intf_fmSetPitch(va_list &args); - int intf_fmSetLevel(va_list &args); - int intf_fmReset(va_list &args); - int intf_setOutputVolume(va_list &args); - int intf_resetOutputVolume(va_list &args); - int intf_updateOutputVolume(va_list &args); - int intf_cdaToggle(va_list &args); - int intf_pcmUpdateEnvelopeGenerator(va_list &args); - - int intf_notImpl(va_list &args); - - void fmReset(); - int fmKeyOn(int chan, int note, int velo); - int fmKeyOff(int chan); - int fmChanOff(int chan); - int fmSetPanPos(int chan, int mode); - int fmSetInstrument(int chan, int instrId); - int fmLoadInstrument(int instrId, const uint8 *data); - int fmSetPitch(int chan, int pitch); - int fmSetLevel(int chan, int lvl); - - void bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value); - - uint8 _fmChanPlaying; - uint8 _fmChanNote[6]; - int16 _fmChanPitch[6]; - - uint8 *_fmSaveReg[2]; - uint8 *_fmInstruments; - - void pcmReset(); - int pcmKeyOn(int chan, int note, int velo); - int pcmKeyOff(int chan); - int pcmChanOff(int chan); - int pcmSetPanPos(int chan, int mode); - int pcmSetInstrument(int chan, int instrId); - int pcmLoadInstrument(int instrId, const uint8 *data); - int pcmSetPitch(int chan, int pitch); - int pcmSetLevel(int chan, int lvl); - void pcmUpdateEnvelopeGenerator(int chan); - - TownsAudio_PcmChannel *_pcmChan; - uint8 _pcmChanOut; - uint8 _pcmChanReserved; - uint8 _pcmChanKeyPressed; - uint8 _pcmChanEffectPlaying; - uint8 _pcmChanKeyPlaying; - - uint8 _pcmChanNote[8]; - uint8 _pcmChanVelo[8]; - uint8 _pcmChanLevel[8]; - - uint8 _numReservedChannels; - uint8 *_pcmInstruments; - - TownsAudio_WaveTable *_waveTables; - uint8 _numWaveTables; - uint32 _waveTablesTotalDataSize; - - void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w); - - void updateOutputVolume(); - uint8 _outputVolumeFlags; - uint8 _outputLevel[16]; - uint8 _outputMuteFlags; - - const float _baserate; - uint32 _timerBase; - uint32 _tickLength; - uint32 _timer; - - uint16 _musicVolume; - uint16 _sfxVolume; - int _pcmSfxChanMask; - - TownsAudioInterfacePluginDriver *_drv; - bool _ready; - - static const uint8 _chanFlags[]; - static const uint16 _frequency[]; - static const uint8 _carrier[]; - static const uint8 _fmDefaultInstrument[]; - static const uint16 _pcmPhase1[]; - static const uint16 _pcmPhase2[]; + TownsAudioInterfaceIntern *_intf; }; #endif diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp index bbde75eb66..3b46aca14d 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp @@ -26,6 +26,7 @@ #include "audio/musicplugin.h" #include "common/translation.h" #include "common/error.h" +#include "common/system.h" class TownsEmuMusicPlugin : public MusicPluginObject { -- cgit v1.2.3 From 6845f25f541707786f81dded25485c4ff5c8d62d Mon Sep 17 00:00:00 2001 From: athrxx Date: Sat, 30 Apr 2011 15:56:18 +0200 Subject: SCUMM: Adapt code to latest FM-TOWNS audio driver changes --- audio/softsynth/fmtowns_pc98/towns_midi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 658c5a456b..cc390a260b 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -25,8 +25,8 @@ #ifndef TOWNS_MIDI_H #define TOWNS_MIDI_H -#include "audio/mididrv.h" #include "audio/softsynth/fmtowns_pc98/towns_audio.h" +#include "audio/mididrv.h" class MidiChannel_TOWNS; class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver { -- cgit v1.2.3 From 2f9c5de7bedfc02c7b5a99da471dafa518a78379 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sat, 30 Apr 2011 21:11:30 +0200 Subject: FM-TOWNS AUDIO: Implement some midi driver functions --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 324 ++++++++++++++++++++++++---- audio/softsynth/fmtowns_pc98/towns_midi.h | 12 +- 2 files changed, 292 insertions(+), 44 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index c223d44c11..737e977545 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -25,13 +25,62 @@ #include "audio/softsynth/fmtowns_pc98/towns_midi.h" #include "common/textconsole.h" -class MidiChannel_TOWNS : public MidiChannel { +class TownsMidiOutputChannel { +friend class TownsMidiInputChannel; public: - MidiChannel_TOWNS(MidiDriver_TOWNS *driver); - ~MidiChannel_TOWNS(); + TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanId); + ~TownsMidiOutputChannel(); + + void noteOn(uint8 msb, uint16 lsb); + void noteOnAdjust(uint8 msb, uint16 lsb); + void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2); + + void connect(TownsMidiInputChannel *chan); + void disconnect(); + + enum CheckPriorityStatus { + kDisconnected = -3, + kHighPriority = -2 + }; + + int checkPriority(int pri); + +private: + void keyOn(); + void keyOff(); + void internKeyOnFrq(uint16 frq); + void out(uint8 chan, uint8 reg, uint8 val); + + TownsMidiInputChannel *_midi; + TownsMidiOutputChannel *_prev; + TownsMidiOutputChannel *_next; + uint8 _fld_f; + uint8 _note; + uint8 _tl; + uint8 _noteOffMarker; + uint8 _fld_12; + uint8 _fld_13; + uint8 _prg; + uint8 _chan; + + uint16 _freq; + int16 _freqAdjust; + + MidiDriver_TOWNS *_driver; + + static const uint8 _freqMSB[]; + static const uint16 _freqLSB[]; +}; + +class TownsMidiInputChannel : public MidiChannel { +friend class TownsMidiOutputChannel; +public: + TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex); + ~TownsMidiInputChannel(); MidiDriver *device() { return _driver; } - byte getNumber() { return 0; } + byte getNumber() { return _chanIndex; } + bool allocate(); void release(); void send(uint32 b); @@ -43,71 +92,247 @@ public: void controlChange(byte control, byte value); void pitchBendFactor(byte value); void priority(byte value); - void sysEx_customInstrument(uint32 type, const byte *instr); private: + TownsMidiOutputChannel *_outChan; + //TownsMidiInputChannel *_prev; + //TownsMidiInputChannel *_next; + + uint8 *_instrument; + uint8 _prg; + uint8 _chanIndex; + uint8 _effectLevel; + uint8 _priority; + uint8 _vol; + uint8 _volEff; + uint8 _pan; + uint8 _panEff; + uint8 _perc; + uint8 _percS; + uint8 _fld_22; + uint8 _pitchBendFactor; + + bool _allocated; + MidiDriver_TOWNS *_driver; }; -MidiChannel_TOWNS::MidiChannel_TOWNS(MidiDriver_TOWNS *driver) : MidiChannel(), _driver(driver) { +TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex), + _midi(0), _prev(0), _next(0), _fld_f(0), _note(0), _tl(0), _noteOffMarker(0), _fld_12(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) { +} +TownsMidiOutputChannel::~TownsMidiOutputChannel() { } -MidiChannel_TOWNS::~MidiChannel_TOWNS() { +void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) { + _freq = (msb << 7) + lsb; + _freqAdjust = 0; + internKeyOnFrq(_freq); +} +void TownsMidiOutputChannel::noteOnAdjust(uint8 msb, uint16 lsb) { + _freq = (msb << 7) + lsb; + internKeyOnFrq(_freq + _freqAdjust); } -void MidiChannel_TOWNS::release() { +void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) { + const uint8 *pos = data; } -void MidiChannel_TOWNS::send(uint32 b) { +void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) { + if (!chan) + return; + _midi = chan; + _next = chan->_outChan; + _prev = 0; + chan->_outChan = this; + if (_next) + _next->_prev = this; +} +void TownsMidiOutputChannel::disconnect() { + keyOff(); + TownsMidiOutputChannel *p = _prev; + TownsMidiOutputChannel *n = _next; + + if (n) + n->_prev = p; + if (p) + p->_next = n; + else + _midi->_outChan = n; + _midi = 0; } -void MidiChannel_TOWNS::noteOff(byte note) { +int TownsMidiOutputChannel::checkPriority(int pri) { + if (!_midi) + return kDisconnected; + + if (!_next && pri >= _midi->_priority) + return _midi->_priority; + return kHighPriority; } -void MidiChannel_TOWNS::noteOn(byte note, byte velocity) { +void TownsMidiOutputChannel::keyOn() { + out(_chan, 0x28, 0xf0/*0x30*/ /*???*/); +} + +void TownsMidiOutputChannel::keyOff() { + out(_chan, 0x28, 0); +} +void TownsMidiOutputChannel::internKeyOnFrq(uint16 frq) { + uint8 t = (frq << 1) >> 8; + frq = (_freqMSB[t] << 3) | _freqLSB[t] ; + out(_chan, 0xa4, frq >> 8); + out(_chan, 0xa0, frq & 0xff); + out(_chan, 0x28, 0); + out(_chan, 0x28, 0xf0/*0x30*/ /*???*/); } -void MidiChannel_TOWNS::programChange(byte program) { +void TownsMidiOutputChannel::out(uint8 chan, uint8 reg, uint8 val) { + static const uint8 chanRegOffs[] = { 0, 1, 2, 0, 1, 2 }; + static const uint8 keyValOffs[] = { 0, 1, 2, 4, 5, 6 }; + if (reg == 0x28) + val = (val & 0xf0) | keyValOffs[chan]; + if (reg < 0x30) + _driver->_intf->callback(19, 0, reg, val); + else + _driver->_intf->callback(19, chan / 3, (reg & ~3) | chanRegOffs[chan], val); } -void MidiChannel_TOWNS::pitchBend(int16 bend) { +const uint8 TownsMidiOutputChannel::_freqMSB[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x80, 0x81, 0x83, 0x85, + 0x87, 0x88, 0x8A, 0x8C, 0x8E, 0x8F, 0x91, 0x93, 0x95, 0x96, 0x98, 0x9A, + 0x9C, 0x9E, 0x9F, 0xA1, 0xA3, 0xA5, 0xA6, 0xA8, 0xAA, 0xAC, 0xAD, 0xAF, + 0xB1, 0xB3, 0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0xBD, 0xBF, 0xC1, 0xC3, 0xC4, + 0xC6, 0xC8, 0xCA, 0xCB, 0xCD, 0xCF, 0xD1, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, + 0xDB, 0xDD, 0xDF, 0xE1, 0xE2, 0xE4, 0xE6, 0xE8, 0xE9, 0xEB, 0xED, 0xEF +}; +const uint16 TownsMidiOutputChannel::_freqLSB[] = { + 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, + 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x0301, 0x032F, + 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E, + 0x055B, 0x02D6, 0x0301, 0x032F, 0x0360, 0x0393, 0x03C9, 0x0403, + 0x0440, 0x0481, 0x04C6, 0x050E, 0x055B, 0x02D6, 0x0301, 0x032F, + 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E, + 0x055B, 0x02D6, 0x0301, 0x032F, 0x0360, 0x0393, 0x03C9, 0x0403, + 0x0440, 0x0481, 0x04C6, 0x050E, 0x055B, 0x02D6, 0x0301, 0x032F, + 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E, + 0x055B, 0x02D6, 0x0301, 0x032F, 0x0360, 0x0393, 0x03C9, 0x0403, + 0x0440, 0x0481, 0x04C6, 0x050E, 0x055B, 0x02D6, 0x0301, 0x032F, + 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E, + 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, + 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, + 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, + 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B +}; + +TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _outChan(0), _prg(0), _chanIndex(chanIndex), + _effectLevel(0), _priority(0), _vol(0), _volEff(0), _pan(0), _panEff(0), _perc(0), _percS(0), _pitchBendFactor(0), _fld_22(0), _allocated(false) { + _instrument = new uint8[30]; + memset(_instrument, 0, 30); } -void MidiChannel_TOWNS::controlChange(byte control, byte value) { +TownsMidiInputChannel::~TownsMidiInputChannel() { + delete _instrument; +} +bool TownsMidiInputChannel::allocate() { + if (_allocated) + return false; + _allocated = true; + return true; } -void MidiChannel_TOWNS::pitchBendFactor(byte value) { +void TownsMidiInputChannel::release() { + _allocated = false; +} +void TownsMidiInputChannel::send(uint32 b) { + _driver->send(b | _chanIndex); } -void MidiChannel_TOWNS::priority(byte value) { +void TownsMidiInputChannel::noteOff(byte note) { + if (!_outChan) + return; + if (_outChan->_note != note) + return; + + if (_fld_22) + _outChan->_noteOffMarker = 1; + else + _outChan->disconnect(); +} + +void TownsMidiInputChannel::noteOn(byte note, byte velocity) { + TownsMidiOutputChannel *oc = _driver->allocateOutputChannel(_priority); + + if (!oc) + return; + + oc->connect(this); + + + int vol1 = 0; + int vol2 = 0; + oc->setupProgram(_instrument, vol1, vol2); + //oc->noteOn(m, l); + } -void MidiChannel_TOWNS::sysEx_customInstrument(uint32 type, const byte *instr) { +void TownsMidiInputChannel::programChange(byte program) { } +void TownsMidiInputChannel::pitchBend(int16 bend) { + +} + +void TownsMidiInputChannel::controlChange(byte control, byte value) { + +} + +void TownsMidiInputChannel::pitchBendFactor(byte value) { + +} + +void TownsMidiInputChannel::priority(byte value) { + _priority = value; +} + +void TownsMidiInputChannel::sysEx_customInstrument(uint32 type, const byte *instr) { + memcpy(_instrument, instr, 30); +} + MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timerBpara(0), _open(false) { _intf = new TownsAudioInterface(mixer, this); - _channels = new MidiChannel_TOWNS*[16]; - for (int i = 0; i < 16; i++) - _channels[i] = new MidiChannel_TOWNS(this); + + _channels = new TownsMidiInputChannel*[32]; + for (int i = 0; i < 32; i++) + _channels[i] = new TownsMidiInputChannel(this, i); + _out = new TownsMidiOutputChannel*[6]; + for (int i = 0; i < 6; i++) + _out[i] = new TownsMidiOutputChannel(this, i); _tickCounter = 0; _curChan = 0; - //unbuffered write: _intf->callback(17, part, reg, val); - //buffered write: _intf->callback(19, part, reg, val); } MidiDriver_TOWNS::~MidiDriver_TOWNS() { @@ -115,9 +340,12 @@ MidiDriver_TOWNS::~MidiDriver_TOWNS() { delete _intf; setTimerCallback(0, 0); - for (int i = 0; i < 16; i++) + for (int i = 0; i < 32; i++) delete _channels[i]; delete[] _channels; + for (int i = 0; i < 6; i++) + delete _out[i]; + delete[] _out; } int MidiDriver_TOWNS::open() { @@ -154,14 +382,13 @@ void MidiDriver_TOWNS::send(uint32 b) { if (chan == 9) part = &_percussion; else**/ - MidiChannel_TOWNS *c = _channels[b & 0x0F]; + TownsMidiInputChannel *c = _channels[b & 0x0F]; switch (cmd) { case 0x80: - //part->noteOff(param1); + c->noteOff(param1); break; case 0x90: - //part->noteOn(param1, param2); if (param2) c->noteOn(param1, param2); else @@ -179,7 +406,7 @@ void MidiDriver_TOWNS::send(uint32 b) { c->pitchBend((param1 | (param2 << 7)) - 0x2000); break; case 0xF0: - warning("MidiDriver_ADLIB: Receiving SysEx command on a send() call"); + warning("MidiDriver_TOWNS: Receiving SysEx command on a send() call"); break; default: @@ -193,25 +420,17 @@ void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager: } uint32 MidiDriver_TOWNS::getBaseTempo() { - return 0; + return 4167; } MidiChannel *MidiDriver_TOWNS::allocateChannel() { - MidiChannel *res = 0; - - for (int i = 0; i < 6; i++) { - if (++_curChan == 6) - _curChan = 0; - - //if (_channels[i]-> //// ) - // return _channels[i]; - + for (int i = 0; i < 32; ++i) { + TownsMidiInputChannel *chan = _channels[i]; + if (chan->allocate()) + return chan; } - //if (res) - // res->noteOff(); - - return res; + return 0; } MidiChannel *MidiDriver_TOWNS::getPercussionChannel() { @@ -237,3 +456,26 @@ void MidiDriver_TOWNS::timerCallback(int timerId) { break; } } + +TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) { + TownsMidiOutputChannel *res = 0; + + for (int i = 0; i < 6; i++) { + if (++_curChan == 6) + _curChan = 0; + + int s = _out[i]->checkPriority(pri); + if (s == TownsMidiOutputChannel::kDisconnected) + return _out[i]; + + if (s != TownsMidiOutputChannel::kHighPriority) { + pri = s; + res = _out[i]; + } + } + + if (res) + res->disconnect(); + + return res; +} \ No newline at end of file diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index cc390a260b..115142911a 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -28,9 +28,12 @@ #include "audio/softsynth/fmtowns_pc98/towns_audio.h" #include "audio/mididrv.h" -class MidiChannel_TOWNS; +class TownsMidiOutputChannel; +class TownsMidiInputChannel; + class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver { -friend class MidiChannel_TOWNS; +friend class TownsMidiInputChannel; +friend class TownsMidiOutputChannel; public: MidiDriver_TOWNS(Audio::Mixer *mixer); ~MidiDriver_TOWNS(); @@ -53,7 +56,10 @@ public: TownsAudioInterface *intf() { return _intf; } private: - MidiChannel_TOWNS **_channels; + TownsMidiOutputChannel *allocateOutputChannel(int pri); + + TownsMidiInputChannel **_channels; + TownsMidiOutputChannel **_out; Common::TimerManager::TimerProc _timerBproc; void *_timerBpara; -- cgit v1.2.3 From d4325a0411f2f6c86a117543a4dcbf588ac84fe7 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 1 May 2011 03:57:31 +0200 Subject: FM-TOWNS AUDIO: Implement some more midi driver code --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 178 ++++++++++++++++++++++++---- audio/softsynth/fmtowns_pc98/towns_midi.h | 11 ++ 2 files changed, 163 insertions(+), 26 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 737e977545..86ff7e20af 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -34,6 +34,7 @@ public: void noteOn(uint8 msb, uint16 lsb); void noteOnAdjust(uint8 msb, uint16 lsb); void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2); + void noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr); void connect(TownsMidiInputChannel *chan); void disconnect(); @@ -49,25 +50,45 @@ private: void keyOn(); void keyOff(); void internKeyOnFrq(uint16 frq); - void out(uint8 chan, uint8 reg, uint8 val); + void out(uint8 reg, uint8 val); TownsMidiInputChannel *_midi; TownsMidiOutputChannel *_prev; TownsMidiOutputChannel *_next; - uint8 _fld_f; + uint8 _fld_c; + uint8 _chan; uint8 _note; - uint8 _tl; + uint8 _tl2; + uint8 _tl1; uint8 _noteOffMarker; - uint8 _fld_12; + uint32 _duration; uint8 _fld_13; - uint8 _prg; - uint8 _chan; + uint8 _prg; uint16 _freq; int16 _freqAdjust; + struct StateA { + uint8 a[50]; + } *_stateA; + + struct StateB { + uint8 b1; + uint8 b2; + uint8 b3; + uint8 b4; + uint8 b5; + uint8 b6; + uint8 b7; + uint8 b8; + uint8 b9; + uint8 b10; + uint8 b11; + } *_stateB; + MidiDriver_TOWNS *_driver; + static const uint8 _chanMap[]; static const uint8 _freqMSB[]; static const uint16 _freqLSB[]; }; @@ -105,24 +126,33 @@ private: uint8 _effectLevel; uint8 _priority; uint8 _vol; - uint8 _volEff; + uint8 _tl; uint8 _pan; uint8 _panEff; - uint8 _perc; + int8 _transpose; uint8 _percS; uint8 _fld_22; uint8 _pitchBendFactor; + uint16 _freqLSB; bool _allocated; MidiDriver_TOWNS *_driver; + + static const uint8 _programAdjustLevel[]; }; TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex), - _midi(0), _prev(0), _next(0), _fld_f(0), _note(0), _tl(0), _noteOffMarker(0), _fld_12(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) { + _midi(0), _prev(0), _next(0), _fld_c(0), _tl2(0), _note(0), _tl1(0), _noteOffMarker(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) { + _stateA = new StateA[2]; + memset(_stateA, 0, 2 * sizeof(StateA)); + _stateB = new StateB[2]; + memset(_stateB, 0, 2 * sizeof(StateB)); } TownsMidiOutputChannel::~TownsMidiOutputChannel() { + delete[] _stateA; + delete[] _stateB; } void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) { @@ -137,8 +167,54 @@ void TownsMidiOutputChannel::noteOnAdjust(uint8 msb, uint16 lsb) { } void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) { + static const uint8 mul[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 }; const uint8 *pos = data; + uint8 chan = _chanMap[_chan]; + + uint8 mulAmsFms1 = _driver->_chanState[chan].mulAmsFms = *pos++; + uint8 tl1 = _driver->_chanState[chan].tl = (*pos++ | 0x3f) - vol1; + uint8 attDec1 = _driver->_chanState[chan].attDec = !(*pos++); + uint8 sus1 = _driver->_chanState[chan].sus = !(*pos++); + uint8 unk1 = _driver->_chanState[chan].unk = *pos++; + chan += 3; + + out(0x30, mul[mulAmsFms1 & 0x0f]); + out(0x40, (tl1 & 0x3f) + 15); + out(0x50, ((attDec1 >> 4) << 1) | ((attDec1 >> 4) & 1)); + out(0x60, ((attDec1 << 1) | (attDec1 & 1)) & 0x1f); + out(0x70, (mulAmsFms1 & 0x20) ^ 0x20 ? ((sus1 & 0x0f) << 1) | 1: 0); + out(0x80, sus1); + + uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = *pos++; + uint8 tl2 = _driver->_chanState[chan].tl = (*pos++ | 0x3f) - vol2; + uint8 attDec2 = _driver->_chanState[chan].attDec = !(*pos++); + uint8 sus2 = _driver->_chanState[chan].sus = !(*pos++); + uint8 unk2 = _driver->_chanState[chan].unk = *pos++; + + uint8 mul2 = mul[mulAmsFms2 & 0x0f]; + tl2 = (tl2 & 0x3f) + 15; + uint8 ar2 = ((attDec2 >> 4) << 1) | ((attDec2 >> 4) & 1); + uint8 dec2 = ((attDec2 << 1) | (attDec2 & 1)) & 0x1f; + uint8 sus2r = (mulAmsFms2 & 0x20) ^ 0x20 ? ((sus2 & 0x0f) << 1) | 1: 0; + + for (int i = 4; i < 16; i += 4) { + out(0x30 + i, mul2); + out(0x40 + i, tl2); + out(0x50 + i, ar2); + out(0x60 + i, dec2); + out(0x70 + i, sus2r); + out(0x80 + i, sus2); + } + + uint8 t = _driver->_chanState[chan /*_chan*/ /*???*/].fgAlg = *pos; + out(0xb0, ((t & 0x0e) << 2) | (((t & 1) << 1) + 5)); + t = mulAmsFms1 | mulAmsFms2; + out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5)); +} +void TownsMidiOutputChannel::noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr) { + StateA *a = &_stateA[index]; + StateB *b = &_stateB[index]; } void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) { @@ -177,34 +253,38 @@ int TownsMidiOutputChannel::checkPriority(int pri) { } void TownsMidiOutputChannel::keyOn() { - out(_chan, 0x28, 0xf0/*0x30*/ /*???*/); + out(0x28, 0xf0/*0x30*/ /*???*/); } void TownsMidiOutputChannel::keyOff() { - out(_chan, 0x28, 0); + out(0x28, 0); } void TownsMidiOutputChannel::internKeyOnFrq(uint16 frq) { uint8 t = (frq << 1) >> 8; frq = (_freqMSB[t] << 3) | _freqLSB[t] ; - out(_chan, 0xa4, frq >> 8); - out(_chan, 0xa0, frq & 0xff); - out(_chan, 0x28, 0); - out(_chan, 0x28, 0xf0/*0x30*/ /*???*/); + out(0xa4, frq >> 8); + out(0xa0, frq & 0xff); + out(0x28, 0); + out(0x28, 0xf0/*0x30*/ /*???*/); } -void TownsMidiOutputChannel::out(uint8 chan, uint8 reg, uint8 val) { +void TownsMidiOutputChannel::out(uint8 reg, uint8 val) { static const uint8 chanRegOffs[] = { 0, 1, 2, 0, 1, 2 }; static const uint8 keyValOffs[] = { 0, 1, 2, 4, 5, 6 }; if (reg == 0x28) - val = (val & 0xf0) | keyValOffs[chan]; + val = (val & 0xf0) | keyValOffs[_chan]; if (reg < 0x30) - _driver->_intf->callback(19, 0, reg, val); + _driver->_intf->callback(17, 0, reg, val); else - _driver->_intf->callback(19, chan / 3, (reg & ~3) | chanRegOffs[chan], val); + _driver->_intf->callback(17, _chan / 3, (reg & ~3) | chanRegOffs[_chan], val); } +const uint8 TownsMidiOutputChannel::_chanMap[] = { + 0, 1, 2, 8, 9, 10 +}; + const uint8 TownsMidiOutputChannel::_freqMSB[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -244,7 +324,7 @@ const uint16 TownsMidiOutputChannel::_freqLSB[] = { }; TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _outChan(0), _prg(0), _chanIndex(chanIndex), - _effectLevel(0), _priority(0), _vol(0), _volEff(0), _pan(0), _panEff(0), _perc(0), _percS(0), _pitchBendFactor(0), _fld_22(0), _allocated(false) { + _effectLevel(0), _priority(0), _vol(0), _tl(0), _pan(0), _panEff(0), _transpose(0), _percS(0), _pitchBendFactor(0), _fld_22(0), _freqLSB(0), _allocated(false) { _instrument = new uint8[30]; memset(_instrument, 0, 30); } @@ -289,12 +369,31 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { oc->connect(this); + oc->_fld_c = _instrument[10] & 1; + oc->_note = note; + oc->_noteOffMarker = 0; + oc->_duration = _instrument[29] * 72; - int vol1 = 0; - int vol2 = 0; - oc->setupProgram(_instrument, vol1, vol2); - //oc->noteOn(m, l); - + oc->_tl1 = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; + if (oc->_tl1 > 63) + oc->_tl1 = 63; + + oc->_tl2 = (_instrument[6] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)]; + if (oc->_tl2 > 63) + oc->_tl2 = 63; + + oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_tl1 << 5)]] : oc->_tl1, _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_tl2 << 5)]]); + oc->noteOn(note + _transpose, _freqLSB); + + if (_instrument[11] & 0x80) + oc->noteOnSubSubSub_s1(0, _instrument[11], &_instrument[12]); + else + oc->_stateA[0].a[0] = 0; + + if (_instrument[20] & 0x80) + oc->noteOnSubSubSub_s1(1, _instrument[20], &_instrument[21]); + else + oc->_stateA[1].a[0] = 0; } void TownsMidiInputChannel::programChange(byte program) { @@ -321,16 +420,39 @@ void TownsMidiInputChannel::sysEx_customInstrument(uint32 type, const byte *inst memcpy(_instrument, instr, 30); } +const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { + 0x00, 0x04, 0x07, 0x0B, 0x0D, 0x10, 0x12, 0x14, + 0x16, 0x18, 0x1A, 0x1B, 0x1D, 0x1E, 0x1F, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2A, 0x2B, 0x2C, 0x2C, 0x2D, 0x2E, 0x2F, 0x2F, + 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x35, + 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39, + 0x39, 0x3A, 0x3A, 0x3B, 0x3B, 0x3C, 0x3C, 0x3C, + 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F +}; + MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timerBpara(0), _open(false) { _intf = new TownsAudioInterface(mixer, this); _channels = new TownsMidiInputChannel*[32]; for (int i = 0; i < 32; i++) _channels[i] = new TownsMidiInputChannel(this, i); + _out = new TownsMidiOutputChannel*[6]; for (int i = 0; i < 6; i++) _out[i] = new TownsMidiOutputChannel(this, i); + _chanState = new ChanState[32]; + memset(_chanState, 0, 32 * sizeof(ChanState)); + + _chanOutputLevel = new uint8[2048]; + for (int i = 0; i < 64; i++) { + for (int ii = 0; ii < 32; ii++) + _chanOutputLevel[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff; + } + for (int i = 0; i < 64; i++) + _chanOutputLevel[i << 5] = 0; + _tickCounter = 0; _curChan = 0; } @@ -343,9 +465,13 @@ MidiDriver_TOWNS::~MidiDriver_TOWNS() { for (int i = 0; i < 32; i++) delete _channels[i]; delete[] _channels; + for (int i = 0; i < 6; i++) delete _out[i]; delete[] _out; + + delete[] _chanState; + delete[] _chanOutputLevel; } int MidiDriver_TOWNS::open() { @@ -478,4 +604,4 @@ TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) { res->disconnect(); return res; -} \ No newline at end of file +} diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 115142911a..6ff8a99cda 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -61,6 +61,15 @@ private: TownsMidiInputChannel **_channels; TownsMidiOutputChannel **_out; + struct ChanState { + uint8 mulAmsFms; + uint8 tl; + uint8 attDec; + uint8 sus; + uint8 fgAlg; + uint8 unk; + } *_chanState; + Common::TimerManager::TimerProc _timerBproc; void *_timerBpara; @@ -70,6 +79,8 @@ private: uint8 _curChan; bool _open; + + uint8 *_chanOutputLevel; }; #endif -- cgit v1.2.3 From 8fe9e89c6c7c0b232b492fc9fe771e882d442718 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 1 May 2011 15:11:15 +0200 Subject: FM-TOWNS AUDIO: Some more midi driver code --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 63 ++++++++++++++++++----------- 1 file changed, 40 insertions(+), 23 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 86ff7e20af..1eb9f13759 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -49,7 +49,7 @@ public: private: void keyOn(); void keyOff(); - void internKeyOnFrq(uint16 frq); + void internKeySetFreq(uint16 frq); void out(uint8 reg, uint8 val); TownsMidiInputChannel *_midi; @@ -158,24 +158,29 @@ TownsMidiOutputChannel::~TownsMidiOutputChannel() { void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) { _freq = (msb << 7) + lsb; _freqAdjust = 0; - internKeyOnFrq(_freq); + internKeySetFreq(_freq); } void TownsMidiOutputChannel::noteOnAdjust(uint8 msb, uint16 lsb) { _freq = (msb << 7) + lsb; - internKeyOnFrq(_freq + _freqAdjust); + internKeySetFreq(_freq + _freqAdjust); } void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) { + // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7), + // since it is just a modified AdLib driver. It also uses AdLib programs. + // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS + // music being so bad compared to AdLib (unsuitable data is just forced into the + // wrong audio device). + static const uint8 mul[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 }; - const uint8 *pos = data; uint8 chan = _chanMap[_chan]; - - uint8 mulAmsFms1 = _driver->_chanState[chan].mulAmsFms = *pos++; - uint8 tl1 = _driver->_chanState[chan].tl = (*pos++ | 0x3f) - vol1; - uint8 attDec1 = _driver->_chanState[chan].attDec = !(*pos++); - uint8 sus1 = _driver->_chanState[chan].sus = !(*pos++); - uint8 unk1 = _driver->_chanState[chan].unk = *pos++; + + uint8 mulAmsFms1 = _driver->_chanState[chan].mulAmsFms = data[0]; + uint8 tl1 = _driver->_chanState[chan].tl = (data[1] | 0x3f) - vol1; + uint8 attDec1 = _driver->_chanState[chan].attDec = ~data[2]; + uint8 sus1 = _driver->_chanState[chan].sus = ~data[3]; + uint8 unk1 = _driver->_chanState[chan].unk = data[4]; chan += 3; out(0x30, mul[mulAmsFms1 & 0x0f]); @@ -185,11 +190,11 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v out(0x70, (mulAmsFms1 & 0x20) ^ 0x20 ? ((sus1 & 0x0f) << 1) | 1: 0); out(0x80, sus1); - uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = *pos++; - uint8 tl2 = _driver->_chanState[chan].tl = (*pos++ | 0x3f) - vol2; - uint8 attDec2 = _driver->_chanState[chan].attDec = !(*pos++); - uint8 sus2 = _driver->_chanState[chan].sus = !(*pos++); - uint8 unk2 = _driver->_chanState[chan].unk = *pos++; + uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = data[5]; + uint8 tl2 = _driver->_chanState[chan].tl = (data[6] | 0x3f) - vol2; + uint8 attDec2 = _driver->_chanState[chan].attDec = ~data[7]; + uint8 sus2 = _driver->_chanState[chan].sus = ~data[8]; + uint8 unk2 = _driver->_chanState[chan].unk = data[9]; uint8 mul2 = mul[mulAmsFms2 & 0x0f]; tl2 = (tl2 & 0x3f) + 15; @@ -206,9 +211,11 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v out(0x80 + i, sus2); } - uint8 t = _driver->_chanState[chan /*_chan*/ /*???*/].fgAlg = *pos; - out(0xb0, ((t & 0x0e) << 2) | (((t & 1) << 1) + 5)); - t = mulAmsFms1 | mulAmsFms2; + _driver->_chanState[chan].fgAlg = data[10]; + uint8 alg = 5 + 2 * (data[10] & 1); + uint8 fb = 4 * (data[10] & 0x0e); + out(0xb0, fb | alg); + uint8 t = mulAmsFms1 | mulAmsFms2; out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5)); } @@ -253,20 +260,30 @@ int TownsMidiOutputChannel::checkPriority(int pri) { } void TownsMidiOutputChannel::keyOn() { - out(0x28, 0xf0/*0x30*/ /*???*/); + // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7), + // since it is just a modified AdLib driver. It also uses AdLib programs. + // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS + // music being so bad compared to AdLib (unsuitable data is just forced into the + // wrong audio device). + out(0x28, 0x30); } void TownsMidiOutputChannel::keyOff() { out(0x28, 0); } -void TownsMidiOutputChannel::internKeyOnFrq(uint16 frq) { +void TownsMidiOutputChannel::internKeySetFreq(uint16 frq) { uint8 t = (frq << 1) >> 8; - frq = (_freqMSB[t] << 3) | _freqLSB[t] ; + frq = (_freqMSB[t] << 11) | _freqLSB[t] ; out(0xa4, frq >> 8); out(0xa0, frq & 0xff); out(0x28, 0); - out(0x28, 0xf0/*0x30*/ /*???*/); + // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7), + // since it is just a modified AdLib driver. It also uses AdLib programs. + // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS + // music being so bad compared to AdLib (unsuitable data is just forced into the + // wrong audio device). + out(0x28, 0x30); } void TownsMidiOutputChannel::out(uint8 reg, uint8 val) { @@ -574,7 +591,7 @@ void MidiDriver_TOWNS::timerCallback(int timerId) { _tickCounter += 10000; while (_tickCounter >= 4167) { _tickCounter -= 4167; - //_timerBproc(_timerBpara); + _timerBproc(_timerBpara); } } break; -- cgit v1.2.3 From 25814e64ac091e70c1a5419c57184acb7dd05e8a Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 1 May 2011 18:02:27 +0200 Subject: FM-TOWNS AUDIO: Implement some midi commands --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 132 ++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 27 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 1eb9f13759..81f561a84c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -32,9 +32,10 @@ public: ~TownsMidiOutputChannel(); void noteOn(uint8 msb, uint16 lsb); - void noteOnAdjust(uint8 msb, uint16 lsb); + void noteOnPitchBend(uint8 msb, uint16 lsb); void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2); void noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr); + void setModWheel(uint8 value); void connect(TownsMidiInputChannel *chan); void disconnect(); @@ -60,7 +61,7 @@ private: uint8 _note; uint8 _tl2; uint8 _tl1; - uint8 _noteOffMarker; + uint8 _sustainNoteOff; uint32 _duration; uint8 _fld_13; uint8 _prg; @@ -69,7 +70,9 @@ private: int16 _freqAdjust; struct StateA { - uint8 a[50]; + uint8 active; + uint8 a[48]; + uint8 modWheel; } *_stateA; struct StateB { @@ -78,7 +81,7 @@ private: uint8 b3; uint8 b4; uint8 b5; - uint8 b6; + uint8 mwu; uint8 b7; uint8 b8; uint8 b9; @@ -113,9 +116,15 @@ public: void controlChange(byte control, byte value); void pitchBendFactor(byte value); void priority(byte value); - void sysEx_customInstrument(uint32 type, const byte *instr); + void sysEx_customInstrument(uint32 type, const byte *instr); private: + void controlModulationWheel(byte value); + void controlVolume(byte value); + void controlPanPos(byte value); + void controlSustain(byte value); + void controlRelease(); + TownsMidiOutputChannel *_outChan; //TownsMidiInputChannel *_prev; //TownsMidiInputChannel *_next; @@ -125,14 +134,18 @@ private: uint8 _chanIndex; uint8 _effectLevel; uint8 _priority; - uint8 _vol; + uint8 _ctrlVolume; uint8 _tl; uint8 _pan; uint8 _panEff; - int8 _transpose; uint8 _percS; - uint8 _fld_22; + int8 _transpose; + uint8 _fld_1f; + int8 _detune; + uint8 _modWheel; + uint8 _sustain; uint8 _pitchBendFactor; + int16 _pitchBend; uint16 _freqLSB; bool _allocated; @@ -143,7 +156,7 @@ private: }; TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex), - _midi(0), _prev(0), _next(0), _fld_c(0), _tl2(0), _note(0), _tl1(0), _noteOffMarker(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) { + _midi(0), _prev(0), _next(0), _fld_c(0), _tl2(0), _note(0), _tl1(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) { _stateA = new StateA[2]; memset(_stateA, 0, 2 * sizeof(StateA)); _stateB = new StateB[2]; @@ -161,7 +174,7 @@ void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) { internKeySetFreq(_freq); } -void TownsMidiOutputChannel::noteOnAdjust(uint8 msb, uint16 lsb) { +void TownsMidiOutputChannel::noteOnPitchBend(uint8 msb, uint16 lsb) { _freq = (msb << 7) + lsb; internKeySetFreq(_freq + _freqAdjust); } @@ -224,6 +237,14 @@ void TownsMidiOutputChannel::noteOnSubSubSub_s1(int index, uint8 c, const uint8 StateB *b = &_stateB[index]; } +void TownsMidiOutputChannel::setModWheel(uint8 value) { + if (_stateA[0].active && _stateB[0].mwu) + _stateA[0].modWheel = value >> 2; + + if (_stateA[1].active && _stateB[1].mwu) + _stateA[1].modWheel = value >> 2; +} + void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) { if (!chan) return; @@ -341,7 +362,8 @@ const uint16 TownsMidiOutputChannel::_freqLSB[] = { }; TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _outChan(0), _prg(0), _chanIndex(chanIndex), - _effectLevel(0), _priority(0), _vol(0), _tl(0), _pan(0), _panEff(0), _transpose(0), _percS(0), _pitchBendFactor(0), _fld_22(0), _freqLSB(0), _allocated(false) { + _effectLevel(0), _priority(0), _ctrlVolume(0), _tl(0), _pan(0), _panEff(0), _transpose(0), _percS(0), _pitchBendFactor(0), _pitchBend(0), _sustain(0), _freqLSB(0), + _fld_1f(0), _detune(0), _modWheel(0), _allocated(false) { _instrument = new uint8[30]; memset(_instrument, 0, 30); } @@ -372,8 +394,8 @@ void TownsMidiInputChannel::noteOff(byte note) { if (_outChan->_note != note) return; - if (_fld_22) - _outChan->_noteOffMarker = 1; + if (_sustain) + _outChan->_sustainNoteOff = 1; else _outChan->disconnect(); } @@ -388,7 +410,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { oc->_fld_c = _instrument[10] & 1; oc->_note = note; - oc->_noteOffMarker = 0; + oc->_sustainNoteOff = 0; oc->_duration = _instrument[29] * 72; oc->_tl1 = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; @@ -405,28 +427,49 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { if (_instrument[11] & 0x80) oc->noteOnSubSubSub_s1(0, _instrument[11], &_instrument[12]); else - oc->_stateA[0].a[0] = 0; + oc->_stateA[0].active = 0; if (_instrument[20] & 0x80) oc->noteOnSubSubSub_s1(1, _instrument[20], &_instrument[21]); else - oc->_stateA[1].a[0] = 0; + oc->_stateA[1].active = 0; } void TownsMidiInputChannel::programChange(byte program) { - + // Dysfunctional since this is all done inside the imuse code } void TownsMidiInputChannel::pitchBend(int16 bend) { - + _pitchBend = bend; + _freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune; + for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) + oc->noteOnPitchBend(oc->_note + oc->_midi->_transpose, _freqLSB); } void TownsMidiInputChannel::controlChange(byte control, byte value) { - + switch (control) { + case 1: + controlModulationWheel(value); + break; + case 7: + controlVolume(value); + break; + case 10: + controlPanPos(value); + break; + case 64: + controlSustain(value); + break; + default: + break; + } } void TownsMidiInputChannel::pitchBendFactor(byte value) { - + _pitchBendFactor = value; + _freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune; + for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) + oc->noteOnPitchBend(oc->_note + oc->_midi->_transpose, _freqLSB); } void TownsMidiInputChannel::priority(byte value) { @@ -437,6 +480,47 @@ void TownsMidiInputChannel::sysEx_customInstrument(uint32 type, const byte *inst memcpy(_instrument, instr, 30); } +void TownsMidiInputChannel::controlModulationWheel(byte value) { + _modWheel = value; + for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) + oc->setModWheel(value); +} + +void TownsMidiInputChannel::controlVolume(byte value) { + /* This is all done inside the imuse code + + uint16 v1 = _ctrlVolume + 1; + uint16 v2 = value; + if (_chanIndex != 16) { + _ctrlVolume = value; + v2 = value; + } + _tl = (v1 * v2) >> 7;*/ + + _tl = value; + + /* nullsub + _outChan->setVolume(_tl); + */ +} + +void TownsMidiInputChannel::controlPanPos(byte value) { + // not supported +} + +void TownsMidiInputChannel::controlSustain(byte value) { + _sustain = value; + if (!value) + controlRelease(); +} + +void TownsMidiInputChannel::controlRelease() { + for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) { + if (oc->_sustainNoteOff) + oc->disconnect(); + } +} + const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { 0x00, 0x04, 0x07, 0x0B, 0x0D, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1B, 0x1D, 0x1E, 0x1F, 0x21, @@ -521,10 +605,6 @@ void MidiDriver_TOWNS::send(uint32 b) { byte param1 = (b >> 8) & 0xFF; byte cmd = b & 0xF0; - /*AdLibPart *part; - if (chan == 9) - part = &_percussion; - else**/ TownsMidiInputChannel *c = _channels[b & 0x0F]; switch (cmd) { @@ -538,14 +618,12 @@ void MidiDriver_TOWNS::send(uint32 b) { c->noteOff(param1); break; case 0xB0: - // supported: 1, 7, 0x40 c->controlChange(param1, param2); break; case 0xC0: c->programChange(param1); break; case 0xE0: - //part->pitchBend((param1 | (param2 << 7)) - 0x2000); c->pitchBend((param1 | (param2 << 7)) - 0x2000); break; case 0xF0: @@ -577,7 +655,7 @@ MidiChannel *MidiDriver_TOWNS::allocateChannel() { } MidiChannel *MidiDriver_TOWNS::getPercussionChannel() { - return 0; + return 0;//_channels[16]; } void MidiDriver_TOWNS::timerCallback(int timerId) { -- cgit v1.2.3 From bd2c84be89068757531399b32e099ec7287ee2a6 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 1 May 2011 22:43:36 +0200 Subject: FM-TOWNS AUDIO: More midi driver code (effect processing) --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 206 ++++++++++++++++++++++------ audio/softsynth/fmtowns_pc98/towns_midi.h | 11 +- 2 files changed, 166 insertions(+), 51 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 81f561a84c..5b2dc7b48f 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -25,6 +25,38 @@ #include "audio/softsynth/fmtowns_pc98/towns_midi.h" #include "common/textconsole.h" +struct ChanState { + uint8 get(uint8 type) { + switch (type) { + case 0: + return unk1; + case 1: + return mulAmsFms; + case 2: + return tl; + case 3: + return attDec; + case 4: + return sus; + case 5: + return fgAlg; + case 6: + return unk2; + default: + break; + } + return 0; + } + + uint8 unk1; + uint8 mulAmsFms; + uint8 tl; + uint8 attDec; + uint8 sus; + uint8 fgAlg; + uint8 unk2; +}; + class TownsMidiOutputChannel { friend class TownsMidiInputChannel; public: @@ -34,7 +66,7 @@ public: void noteOn(uint8 msb, uint16 lsb); void noteOnPitchBend(uint8 msb, uint16 lsb); void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2); - void noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr); + void setupEffects(int index, uint8 c, const uint8 *effectData); void setModWheel(uint8 value); void connect(TownsMidiInputChannel *chan); @@ -48,6 +80,43 @@ public: int checkPriority(int pri); private: + struct StateA { + uint8 active; + uint8 fld_1; + uint8 fld_2; + uint8 fld_3; + uint8 fld_4; + uint8 fld_5; + uint8 fld_6; + uint8 fld_7; + uint8 fld_8; + uint32 fld_9; + uint32 effectState; + uint8 fld_11; + uint8 fld_12; + uint8 fld_13; + uint8 fld_14; + uint8 fld_15; + uint8 fld_16; + uint8 fld_17; + uint8 fld_18; + uint8 fld_19; + uint8 fld_1a; + uint8 modWheelImpact; + uint8 modWheel; + } *_stateA; + + struct StateB { + uint32 fld_0; + uint8 type; + uint8 useModWheel; + uint8 fld_6; + StateA *a; + } *_stateB; + + uint32 getEffectState(uint8 type); + void processEffect(StateA *a, const uint8 *effectData); + void keyOn(); void keyOff(); void internKeySetFreq(uint16 frq); @@ -59,8 +128,8 @@ private: uint8 _fld_c; uint8 _chan; uint8 _note; - uint8 _tl2; - uint8 _tl1; + uint8 _carrierTl; + uint8 _modulatorTl; uint8 _sustainNoteOff; uint32 _duration; uint8 _fld_13; @@ -69,29 +138,11 @@ private: uint16 _freq; int16 _freqAdjust; - struct StateA { - uint8 active; - uint8 a[48]; - uint8 modWheel; - } *_stateA; - - struct StateB { - uint8 b1; - uint8 b2; - uint8 b3; - uint8 b4; - uint8 b5; - uint8 mwu; - uint8 b7; - uint8 b8; - uint8 b9; - uint8 b10; - uint8 b11; - } *_stateB; - MidiDriver_TOWNS *_driver; static const uint8 _chanMap[]; + static const uint8 _chanMap2[]; + static const uint8 _effectDefs[]; static const uint8 _freqMSB[]; static const uint16 _freqLSB[]; }; @@ -123,11 +174,10 @@ private: void controlVolume(byte value); void controlPanPos(byte value); void controlSustain(byte value); - void controlRelease(); + + void releasePedal(); TownsMidiOutputChannel *_outChan; - //TownsMidiInputChannel *_prev; - //TownsMidiInputChannel *_next; uint8 *_instrument; uint8 _prg; @@ -156,7 +206,7 @@ private: }; TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex), - _midi(0), _prev(0), _next(0), _fld_c(0), _tl2(0), _note(0), _tl1(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) { + _midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) { _stateA = new StateA[2]; memset(_stateA, 0, 2 * sizeof(StateA)); _stateB = new StateB[2]; @@ -193,7 +243,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v uint8 tl1 = _driver->_chanState[chan].tl = (data[1] | 0x3f) - vol1; uint8 attDec1 = _driver->_chanState[chan].attDec = ~data[2]; uint8 sus1 = _driver->_chanState[chan].sus = ~data[3]; - uint8 unk1 = _driver->_chanState[chan].unk = data[4]; + uint8 unk1 = _driver->_chanState[chan].unk2 = data[4]; chan += 3; out(0x30, mul[mulAmsFms1 & 0x0f]); @@ -207,7 +257,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v uint8 tl2 = _driver->_chanState[chan].tl = (data[6] | 0x3f) - vol2; uint8 attDec2 = _driver->_chanState[chan].attDec = ~data[7]; uint8 sus2 = _driver->_chanState[chan].sus = ~data[8]; - uint8 unk2 = _driver->_chanState[chan].unk = data[9]; + uint8 unk2 = _driver->_chanState[chan].unk2 = data[9]; uint8 mul2 = mul[mulAmsFms2 & 0x0f]; tl2 = (tl2 & 0x3f) + 15; @@ -232,16 +282,50 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5)); } -void TownsMidiOutputChannel::noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr) { +void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effectData) { + uint16 maxVal[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F }; + uint8 para1[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 }; + StateA *a = &_stateA[index]; StateB *b = &_stateB[index]; + + b->fld_0 = 0; + b->useModWheel = c & 0x40; + a->fld_11 = c & 0x20; + b->fld_6 = c & 0x10; + b->type = para1[c & 0x0f]; + a->fld_9 = maxVal[c & 0x0f]; + a->fld_1a = 0x1f; + a->modWheelImpact = b->useModWheel ? _midi->_modWheel >> 2 : 0x1f; + + switch (b->type) { + case 0: + a->effectState = _carrierTl; + break; + case 13: + a->effectState = _modulatorTl; + break; + case 30: + a->effectState = 0x1f; + b->a->modWheelImpact = 0; + break; + case 31: + a->effectState = 0; + b->a->fld_1a = 0; + break; + default: + a->effectState = getEffectState(b->type); + break; + } + + processEffect(a, effectData); } void TownsMidiOutputChannel::setModWheel(uint8 value) { - if (_stateA[0].active && _stateB[0].mwu) + if (_stateA[0].active && _stateB[0].type) _stateA[0].modWheel = value >> 2; - if (_stateA[1].active && _stateB[1].mwu) + if (_stateA[1].active && _stateB[1].type) _stateA[1].modWheel = value >> 2; } @@ -280,6 +364,30 @@ int TownsMidiOutputChannel::checkPriority(int pri) { return kHighPriority; } +uint32 TownsMidiOutputChannel::getEffectState(uint8 type) { + uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan); + + if (type == 28) + return 15; + else if (type == 29) + return 383; + else if (type > 29) + return 0; + else if (type > 12) + type -= 13; + + uint32 res = 0; + uint8 cs = (_driver->_chanState[chan].get(_effectDefs[type * 4] >> 5) & _effectDefs[type * 4 + 2]) >> _effectDefs[type * 4 + 1]; + if (_effectDefs[type * 4 + 3]) + res = _effectDefs[type * 4 + 3] - cs; + + return res; +} + +void TownsMidiOutputChannel::processEffect(StateA *a, const uint8 *effectData) { + +} + void TownsMidiOutputChannel::keyOn() { // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7), // since it is just a modified AdLib driver. It also uses AdLib programs. @@ -323,6 +431,18 @@ const uint8 TownsMidiOutputChannel::_chanMap[] = { 0, 1, 2, 8, 9, 10 }; +const uint8 TownsMidiOutputChannel::_chanMap2[] = { + 3, 4, 5, 11, 12, 13 +}; + +const uint8 TownsMidiOutputChannel::_effectDefs[] = { + 0x40, 0x00, 0x3F, 0x3F, 0xE0, 0x02, 0x00, 0x00, 0x40, 0x06, 0xC0, 0x00, + 0x20, 0x00, 0x0F, 0x00, 0x60, 0x04, 0xF0, 0x0F, 0x60, 0x00, 0x0F, 0x0F, + 0x80, 0x04, 0xF0, 0x0F, 0x80, 0x00, 0x0F, 0x0F, 0xE0, 0x00, 0x03, 0x00, + 0x20, 0x07, 0x80, 0x00, 0x20, 0x06, 0x40, 0x00, 0x20, 0x05, 0x20, 0x00, + 0x20, 0x04, 0x10, 0x00, 0xC0, 0x00, 0x01, 0x00, 0xC0, 0x01, 0x0E, 0x00 +}; + const uint8 TownsMidiOutputChannel::_freqMSB[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -413,24 +533,24 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { oc->_sustainNoteOff = 0; oc->_duration = _instrument[29] * 72; - oc->_tl1 = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; - if (oc->_tl1 > 63) - oc->_tl1 = 63; + oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; + if (oc->_modulatorTl > 63) + oc->_modulatorTl = 63; - oc->_tl2 = (_instrument[6] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)]; - if (oc->_tl2 > 63) - oc->_tl2 = 63; + oc->_carrierTl = (_instrument[6] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)]; + if (oc->_carrierTl > 63) + oc->_carrierTl = 63; - oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_tl1 << 5)]] : oc->_tl1, _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_tl2 << 5)]]); + oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]); oc->noteOn(note + _transpose, _freqLSB); if (_instrument[11] & 0x80) - oc->noteOnSubSubSub_s1(0, _instrument[11], &_instrument[12]); + oc->setupEffects(0, _instrument[11], &_instrument[12]); else oc->_stateA[0].active = 0; if (_instrument[20] & 0x80) - oc->noteOnSubSubSub_s1(1, _instrument[20], &_instrument[21]); + oc->setupEffects(1, _instrument[20], &_instrument[21]); else oc->_stateA[1].active = 0; } @@ -511,10 +631,10 @@ void TownsMidiInputChannel::controlPanPos(byte value) { void TownsMidiInputChannel::controlSustain(byte value) { _sustain = value; if (!value) - controlRelease(); + releasePedal(); } -void TownsMidiInputChannel::controlRelease() { +void TownsMidiInputChannel::releasePedal() { for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) { if (oc->_sustainNoteOff) oc->disconnect(); diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 6ff8a99cda..8cffdd71da 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -28,8 +28,10 @@ #include "audio/softsynth/fmtowns_pc98/towns_audio.h" #include "audio/mididrv.h" + class TownsMidiOutputChannel; class TownsMidiInputChannel; +struct ChanState; class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver { friend class TownsMidiInputChannel; @@ -61,14 +63,7 @@ private: TownsMidiInputChannel **_channels; TownsMidiOutputChannel **_out; - struct ChanState { - uint8 mulAmsFms; - uint8 tl; - uint8 attDec; - uint8 sus; - uint8 fgAlg; - uint8 unk; - } *_chanState; + ChanState *_chanState; Common::TimerManager::TimerProc _timerBproc; void *_timerBpara; -- cgit v1.2.3 From d9772ff88f29e37fa7b91b7b6e43d846bcfad008 Mon Sep 17 00:00:00 2001 From: athrxx Date: Mon, 2 May 2011 02:46:22 +0200 Subject: FM-TOWNS AUDIO: Some renaming in the euphony driver code --- audio/softsynth/fmtowns_pc98/towns_euphony.cpp | 34 +++++----- audio/softsynth/fmtowns_pc98/towns_euphony.h | 16 ++--- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 86 ++++++++++++++------------ audio/softsynth/fmtowns_pc98/towns_midi.h | 7 +-- 4 files changed, 75 insertions(+), 68 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp index 49c156f142..cb6cfc53f3 100644 --- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp @@ -27,7 +27,7 @@ TownsEuphonyDriver::TownsEuphonyDriver(Audio::Mixer *mixer) : _activeChannels(0), _sustainChannels(0), _assignedChannels(0), _paraCount(0), _command(0), _tEnable(0), _tMode(0), _tOrdr(0), _tLevel(0), - _tTranspose(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0), + _tDetune(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0), _tempoControlMode(0) { _para[0] = _para[1] = 0; _intf = new TownsAudioInterface(mixer, this); @@ -44,7 +44,7 @@ TownsEuphonyDriver::~TownsEuphonyDriver() { delete[] _tMode; delete[] _tOrdr; delete[] _tLevel; - delete[] _tTranspose; + delete[] _tDetune; } bool TownsEuphonyDriver::init() { @@ -59,7 +59,7 @@ bool TownsEuphonyDriver::init() { delete[] _tMode; delete[] _tOrdr; delete[] _tLevel; - delete[] _tTranspose; + delete[] _tDetune; _activeChannels = new int8[16]; _sustainChannels = new int8[16]; @@ -70,7 +70,7 @@ bool TownsEuphonyDriver::init() { _tMode = new uint8[32]; _tOrdr = new uint8[32]; _tLevel = new int8[32]; - _tTranspose = new int8[32]; + _tDetune = new int8[32]; reset(); @@ -220,21 +220,21 @@ void TownsEuphonyDriver::setOutputVolume(int mode, int volLeft, int volRight) { _intf->callback(67, mode, volLeft, volRight); } -int TownsEuphonyDriver::chanEnable(int tableEntry, int val) { +int TownsEuphonyDriver::configChan_enable(int tableEntry, int val) { if (tableEntry > 31) return 3; _tEnable[tableEntry] = val; return 0; } -int TownsEuphonyDriver::chanMode(int tableEntry, int val) { +int TownsEuphonyDriver::configChan_setMode(int tableEntry, int val) { if (tableEntry > 31) return 3; _tMode[tableEntry] = val; return 0; } -int TownsEuphonyDriver::chanOrdr(int tableEntry, int val) { +int TownsEuphonyDriver::configChan_remap(int tableEntry, int val) { if (tableEntry > 31) return 3; if (val < 16) @@ -242,7 +242,7 @@ int TownsEuphonyDriver::chanOrdr(int tableEntry, int val) { return 0; } -int TownsEuphonyDriver::chanVolumeShift(int tableEntry, int val) { +int TownsEuphonyDriver::configChan_adjustVolume(int tableEntry, int val) { if (tableEntry > 31) return 3; if (val <= 40) @@ -250,11 +250,11 @@ int TownsEuphonyDriver::chanVolumeShift(int tableEntry, int val) { return 0; } -int TownsEuphonyDriver::chanNoteShift(int tableEntry, int val) { +int TownsEuphonyDriver::configChan_setDetune(int tableEntry, int val) { if (tableEntry > 31) return 3; if (val <= 40) - _tTranspose[tableEntry] = (int8)(val & 0xff); + _tDetune[tableEntry] = (int8)(val & 0xff); return 0; } @@ -325,7 +325,7 @@ void TownsEuphonyDriver::resetTables() { for (int i = 0; i < 32; i++) _tOrdr[i] = i & 0x0f; memset(_tLevel, 0, 32); - memset(_tTranspose, 0, 32); + memset(_tDetune, 0, 32); } void TownsEuphonyDriver::resetTempo() { @@ -672,8 +672,8 @@ bool TownsEuphonyDriver::evtSetupNote() { uint8 velo = _musicPos[5]; sendEvent(mode, evt); - sendEvent(mode, applyNoteShift(note)); - sendEvent(mode, applyVolumeShift(velo)); + sendEvent(mode, applyDetune(note)); + sendEvent(mode, applyVolumeAdjust(velo)); jumpNextLoop(); if (_musicPos[0] == 0xfe || _musicPos[0] == 0xfd) @@ -712,7 +712,7 @@ bool TownsEuphonyDriver::evtPolyphonicAftertouch() { uint8 mode = _tMode[_musicPos[1]]; sendEvent(mode, evt); - sendEvent(mode, applyNoteShift(_musicPos[4])); + sendEvent(mode, applyDetune(_musicPos[4])); sendEvent(mode, _musicPos[5]); return false; @@ -780,8 +780,8 @@ bool TownsEuphonyDriver::evtModeOrdrChange() { return false; } -uint8 TownsEuphonyDriver::applyNoteShift(uint8 in) { - int out = _tTranspose[_musicPos[1]]; +uint8 TownsEuphonyDriver::applyDetune(uint8 in) { + int out = _tDetune[_musicPos[1]]; if (!out) return in; out += (in & 0x7f); @@ -795,7 +795,7 @@ uint8 TownsEuphonyDriver::applyNoteShift(uint8 in) { return out & 0xff; } -uint8 TownsEuphonyDriver::applyVolumeShift(uint8 in) { +uint8 TownsEuphonyDriver::applyVolumeAdjust(uint8 in) { int out = _tLevel[_musicPos[1]]; out += (in & 0x7f); out = CLIP(out, 1, 127); diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.h b/audio/softsynth/fmtowns_pc98/towns_euphony.h index a8f22f593a..ae36d1232b 100644 --- a/audio/softsynth/fmtowns_pc98/towns_euphony.h +++ b/audio/softsynth/fmtowns_pc98/towns_euphony.h @@ -55,11 +55,11 @@ public: void setOutputVolume(int chanType, int volLeft, int volRight); - int chanEnable(int tableEntry, int val); - int chanMode(int tableEntry, int val); - int chanOrdr(int tableEntry, int val); - int chanVolumeShift(int tableEntry, int val); - int chanNoteShift(int tableEntry, int val); + int configChan_enable(int tableEntry, int val); + int configChan_setMode(int tableEntry, int val); + int configChan_remap(int tableEntry, int val); + int configChan_adjustVolume(int tableEntry, int val); + int configChan_setDetune(int tableEntry, int val); int assignChannel(int chan, int tableEntry); @@ -111,8 +111,8 @@ private: return false; } - uint8 applyNoteShift(uint8 in); - uint8 applyVolumeShift(uint8 in); + uint8 applyDetune(uint8 in); + uint8 applyVolumeAdjust(uint8 in); void sendNoteOff(); void sendNoteOn(); @@ -136,7 +136,7 @@ private: uint8 *_tMode; uint8 *_tOrdr; int8 *_tLevel; - int8 *_tTranspose; + int8 *_tDetune; struct DlEvent { uint8 evt; diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 5b2dc7b48f..c492a97122 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -25,38 +25,6 @@ #include "audio/softsynth/fmtowns_pc98/towns_midi.h" #include "common/textconsole.h" -struct ChanState { - uint8 get(uint8 type) { - switch (type) { - case 0: - return unk1; - case 1: - return mulAmsFms; - case 2: - return tl; - case 3: - return attDec; - case 4: - return sus; - case 5: - return fgAlg; - case 6: - return unk2; - default: - break; - } - return 0; - } - - uint8 unk1; - uint8 mulAmsFms; - uint8 tl; - uint8 attDec; - uint8 sus; - uint8 fgAlg; - uint8 unk2; -}; - class TownsMidiOutputChannel { friend class TownsMidiInputChannel; public: @@ -119,7 +87,7 @@ private: void keyOn(); void keyOff(); - void internKeySetFreq(uint16 frq); + void keyOnSetFreq(uint16 frq); void out(uint8 reg, uint8 val); TownsMidiInputChannel *_midi; @@ -205,6 +173,47 @@ private: static const uint8 _programAdjustLevel[]; }; +class TownsMidiChanState { +public: + TownsMidiChanState(); + ~TownsMidiChanState() {} + uint8 get(uint8 type); + + uint8 unk1; + uint8 mulAmsFms; + uint8 tl; + uint8 attDec; + uint8 sus; + uint8 fgAlg; + uint8 unk2; +}; + +TownsMidiChanState::TownsMidiChanState() { + unk1 = mulAmsFms = tl = attDec = sus = fgAlg = unk2 = 0; +} + +uint8 TownsMidiChanState::get(uint8 type) { + switch (type) { + case 0: + return unk1; + case 1: + return mulAmsFms; + case 2: + return tl; + case 3: + return attDec; + case 4: + return sus; + case 5: + return fgAlg; + case 6: + return unk2; + default: + break; + } + return 0; +} + TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex), _midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) { _stateA = new StateA[2]; @@ -221,12 +230,12 @@ TownsMidiOutputChannel::~TownsMidiOutputChannel() { void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) { _freq = (msb << 7) + lsb; _freqAdjust = 0; - internKeySetFreq(_freq); + keyOnSetFreq(_freq); } void TownsMidiOutputChannel::noteOnPitchBend(uint8 msb, uint16 lsb) { _freq = (msb << 7) + lsb; - internKeySetFreq(_freq + _freqAdjust); + keyOnSetFreq(_freq + _freqAdjust); } void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) { @@ -401,7 +410,7 @@ void TownsMidiOutputChannel::keyOff() { out(0x28, 0); } -void TownsMidiOutputChannel::internKeySetFreq(uint16 frq) { +void TownsMidiOutputChannel::keyOnSetFreq(uint16 frq) { uint8 t = (frq << 1) >> 8; frq = (_freqMSB[t] << 11) | _freqLSB[t] ; out(0xa4, frq >> 8); @@ -556,7 +565,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { } void TownsMidiInputChannel::programChange(byte program) { - // Dysfunctional since this is all done inside the imuse code + // Dysfunctional since this is all done inside the imuse code } void TownsMidiInputChannel::pitchBend(int16 bend) { @@ -663,8 +672,7 @@ MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timer for (int i = 0; i < 6; i++) _out[i] = new TownsMidiOutputChannel(this, i); - _chanState = new ChanState[32]; - memset(_chanState, 0, 32 * sizeof(ChanState)); + _chanState = new TownsMidiChanState[32]; _chanOutputLevel = new uint8[2048]; for (int i = 0; i < 64; i++) { diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 8cffdd71da..005c77cedf 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -31,7 +31,7 @@ class TownsMidiOutputChannel; class TownsMidiInputChannel; -struct ChanState; +class TownsMidiChanState; class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver { friend class TownsMidiInputChannel; @@ -61,9 +61,8 @@ private: TownsMidiOutputChannel *allocateOutputChannel(int pri); TownsMidiInputChannel **_channels; - TownsMidiOutputChannel **_out; - - ChanState *_chanState; + TownsMidiOutputChannel **_out; + TownsMidiChanState *_chanState; Common::TimerManager::TimerProc _timerBproc; void *_timerBpara; -- cgit v1.2.3 From 9fa1b9aa361d204ca98e60917c4c7e2e3b3c4f64 Mon Sep 17 00:00:00 2001 From: athrxx Date: Mon, 2 May 2011 23:41:55 +0200 Subject: FM-TOWNS AUDIO: More midi driver code --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 154 +++++++++++++++++++++------- audio/softsynth/fmtowns_pc98/towns_midi.h | 7 +- 2 files changed, 123 insertions(+), 38 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index c492a97122..0cf8a0d581 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -49,28 +49,25 @@ public: private: struct StateA { - uint8 active; - uint8 fld_1; - uint8 fld_2; - uint8 fld_3; - uint8 fld_4; - uint8 fld_5; - uint8 fld_6; - uint8 fld_7; - uint8 fld_8; - uint32 fld_9; - uint32 effectState; + uint8 numLoop; + int32 fld_1; + uint32 fld_5; + int32 fld_9; + int32 effectState; uint8 fld_11; - uint8 fld_12; - uint8 fld_13; - uint8 fld_14; - uint8 fld_15; - uint8 fld_16; - uint8 fld_17; - uint8 fld_18; - uint8 fld_19; + uint8 ar1[4]; + uint8 ar2[4]; uint8 fld_1a; uint8 modWheelImpact; + uint8 fld_1c; + uint32 fld_1d; + uint32 fld_21; + uint32 fld_25; + int8 dir; + uint32 fld_2a; + uint8 fld_2b; + uint8 fld_2c; + uint8 fld_2d; uint8 modWheel; } *_stateA; @@ -83,7 +80,9 @@ private: } *_stateB; uint32 getEffectState(uint8 type); - void processEffect(StateA *a, const uint8 *effectData); + void initEffect(StateA *a, const uint8 *effectData); + void updateEffect(StateA *a); + int lookupVolume(int a, int b); void keyOn(); void keyOff(); @@ -101,7 +100,7 @@ private: uint8 _sustainNoteOff; uint32 _duration; uint8 _fld_13; - uint8 _prg; + uint8 _prg; uint16 _freq; int16 _freqAdjust; @@ -111,6 +110,7 @@ private: static const uint8 _chanMap[]; static const uint8 _chanMap2[]; static const uint8 _effectDefs[]; + static const uint16 _effectData[]; static const uint8 _freqMSB[]; static const uint16 _freqLSB[]; }; @@ -327,14 +327,14 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec break; } - processEffect(a, effectData); + initEffect(a, effectData); } void TownsMidiOutputChannel::setModWheel(uint8 value) { - if (_stateA[0].active && _stateB[0].type) + if (_stateA[0].numLoop && _stateB[0].type) _stateA[0].modWheel = value >> 2; - if (_stateA[1].active && _stateB[1].type) + if (_stateA[1].numLoop && _stateB[1].type) _stateA[1].modWheel = value >> 2; } @@ -393,8 +393,81 @@ uint32 TownsMidiOutputChannel::getEffectState(uint8 type) { return res; } -void TownsMidiOutputChannel::processEffect(StateA *a, const uint8 *effectData) { +void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) { + a->numLoop = 1; + a->fld_1 = 0; + a->fld_1c = 0x1f; + a->fld_5 = effectData[0]; + a->ar1[0] = effectData[1]; + a->ar1[1] = effectData[3]; + a->ar1[2] = effectData[5]; + a->ar1[3] = effectData[6]; + a->ar2[0] = effectData[2]; + a->ar2[1] = effectData[3]; + a->ar2[2] = 0; + a->ar2[3] = effectData[7]; + updateEffect(a); +} + +void TownsMidiOutputChannel::updateEffect(StateA *a) { + uint8 c = --a->numLoop; + uint16 v = a->ar1[c]; + int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->fld_1a]]; + + if (v & 0x80) + e = _driver->randomValue(e); + + if (!e) + e = 1; + + a->fld_1d = a->fld_21 = e; + int32 d = 0; + if (c + 1 != 3) { + v = a->ar2[c]; + e = lookupVolume(a->fld_9, (v & 0x7f) - 31); + + if (v & 0x80) + e = _driver->randomValue(e); + + if (e + a->effectState > a->fld_9) { + e = a->fld_9 - a->effectState; + } else { + if (e + a->effectState + 1 <= 0) + e = -e; + } + + d = e - a->fld_1; + } + + a->fld_25 = d / a->fld_1d; + a->dir = d < 0 ? -1 : 1; + a->fld_2a = d % a->fld_1d; + + a->fld_2b = a->fld_2c = a->fld_2d = a->modWheel = 0; +} + +int TownsMidiOutputChannel::lookupVolume(int a, int b) { + if (b == 0) + return 0; + + if (b == 31) + return a; + + if (a > 63) + return ((a + 1) * b) >> 5; + + if (b < 0) { + if (a < 0) + return _driver->_chanOutputLevel[(-a << 5) - b]; + else + return -_driver->_chanOutputLevel[(a << 5) - b]; + } else { + if (a < 0) + return -_driver->_chanOutputLevel[(-a << 5) + b]; + else + return _driver->_chanOutputLevel[(-a << 5) + b]; + } } void TownsMidiOutputChannel::keyOn() { @@ -452,6 +525,13 @@ const uint8 TownsMidiOutputChannel::_effectDefs[] = { 0x20, 0x04, 0x10, 0x00, 0xC0, 0x00, 0x01, 0x00, 0xC0, 0x01, 0x0E, 0x00 }; +const uint16 TownsMidiOutputChannel::_effectData[] = { + 0x0001, 0x0002, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, + 0x000A, 0x000C, 0x000E, 0x0010, 0x0012, 0x0015, 0x0018, 0x001E, + 0x0024, 0x0032, 0x0040, 0x0052, 0x0064, 0x0088, 0x00A0, 0x00C0, + 0x00F0, 0x0114, 0x0154, 0x01CC, 0x0258, 0x035C, 0x04B0, 0x0640 +}; + const uint8 TownsMidiOutputChannel::_freqMSB[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -556,12 +636,12 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { if (_instrument[11] & 0x80) oc->setupEffects(0, _instrument[11], &_instrument[12]); else - oc->_stateA[0].active = 0; + oc->_stateA[0].numLoop = 0; if (_instrument[20] & 0x80) oc->setupEffects(1, _instrument[20], &_instrument[21]); else - oc->_stateA[1].active = 0; + oc->_stateA[1].numLoop = 0; } void TownsMidiInputChannel::programChange(byte program) { @@ -661,7 +741,7 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F }; -MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timerBpara(0), _open(false) { +MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter(0), _curChan(0), _rand(1), _open(false) { _intf = new TownsAudioInterface(mixer, this); _channels = new TownsMidiInputChannel*[32]; @@ -681,9 +761,6 @@ MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timer } for (int i = 0; i < 64; i++) _chanOutputLevel[i << 5] = 0; - - _tickCounter = 0; - _curChan = 0; } MidiDriver_TOWNS::~MidiDriver_TOWNS() { @@ -764,8 +841,8 @@ void MidiDriver_TOWNS::send(uint32 b) { } void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { - _timerBproc = timer_proc; - _timerBpara = timer_param; + _timerProc = timer_proc; + _timerProcPara = timer_param; } uint32 MidiDriver_TOWNS::getBaseTempo() { @@ -792,12 +869,12 @@ void MidiDriver_TOWNS::timerCallback(int timerId) { switch (timerId) { case 1: - if (_timerBproc) { - _timerBproc(_timerBpara); + if (_timerProc) { + _timerProc(_timerProcPara); _tickCounter += 10000; while (_tickCounter >= 4167) { _tickCounter -= 4167; - _timerBproc(_timerBpara); + _timerProc(_timerProcPara); } } break; @@ -828,3 +905,8 @@ TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) { return res; } + +int MidiDriver_TOWNS::randomValue(int para) { + _rand = (_rand & 1) ? (_rand >> 1) ^ 0xb8 : (_rand >> 1); + return (_rand * para) >> 8; +} diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 005c77cedf..1a4a8613ca 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -59,18 +59,21 @@ public: private: TownsMidiOutputChannel *allocateOutputChannel(int pri); + + int randomValue(int para); TownsMidiInputChannel **_channels; TownsMidiOutputChannel **_out; TownsMidiChanState *_chanState; - Common::TimerManager::TimerProc _timerBproc; - void *_timerBpara; + Common::TimerManager::TimerProc _timerProc; + void *_timerProcPara; TownsAudioInterface *_intf; uint32 _tickCounter; uint8 _curChan; + uint8 _rand; bool _open; -- cgit v1.2.3 From ca0e9cca3d50759e86aaa54bdfa5d5c5fdf85efb Mon Sep 17 00:00:00 2001 From: athrxx Date: Tue, 3 May 2011 19:12:04 +0200 Subject: FM-TOWNS AUDIO: Start fixing midi driver tempo --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 77 +++++++++++++++++++++++------ audio/softsynth/fmtowns_pc98/towns_midi.h | 8 ++- 2 files changed, 67 insertions(+), 18 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 0cf8a0d581..c28f9a12a0 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -40,6 +40,8 @@ public: void connect(TownsMidiInputChannel *chan); void disconnect(); + bool update(); + enum CheckPriorityStatus { kDisconnected = -3, kHighPriority = -2 @@ -81,7 +83,9 @@ private: uint32 getEffectState(uint8 type); void initEffect(StateA *a, const uint8 *effectData); - void updateEffect(StateA *a); + void updateEffectOuter3(StateA *a, StateB *b); + void updateEffectOuter(StateA *a, StateB *b); + void updateEffect(StateA *a); int lookupVolume(int a, int b); void keyOn(); @@ -98,10 +102,8 @@ private: uint8 _carrierTl; uint8 _modulatorTl; uint8 _sustainNoteOff; - uint32 _duration; - uint8 _fld_13; - uint8 _prg; - + int32 _duration; + uint16 _freq; int16 _freqAdjust; @@ -215,7 +217,7 @@ uint8 TownsMidiChanState::get(uint8 type) { } TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex), - _midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) { + _midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) { _stateA = new StateA[2]; memset(_stateA, 0, 2 * sizeof(StateA)); _stateB = new StateB[2]; @@ -363,6 +365,24 @@ void TownsMidiOutputChannel::disconnect() { _midi = 0; } +bool TownsMidiOutputChannel::update() { + if (!_midi) + return false; + + _duration -= 17; + if (_duration <=0) { + disconnect(); + return true; + } + + for (int i = 0; i < 2; i++) { + if (_stateA[i].numLoop) + updateEffectOuter3(&_stateA[i], &_stateB[i]); + } + + return false; +} + int TownsMidiOutputChannel::checkPriority(int pri) { if (!_midi) return kDisconnected; @@ -409,6 +429,14 @@ void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) { updateEffect(a); } +void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) { + +} + +void TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { + +} + void TownsMidiOutputChannel::updateEffect(StateA *a) { uint8 c = --a->numLoop; uint16 v = a->ar1[c]; @@ -741,7 +769,7 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F }; -MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter(0), _curChan(0), _rand(1), _open(false) { +MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter1(0), _tickCounter2(0), _curChan(0), _rand(1), _open(false) { _intf = new TownsAudioInterface(mixer, this); _channels = new TownsMidiInputChannel*[32]; @@ -846,7 +874,7 @@ void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager: } uint32 MidiDriver_TOWNS::getBaseTempo() { - return 4167; + return 10080; } MidiChannel *MidiDriver_TOWNS::allocateChannel() { @@ -869,14 +897,14 @@ void MidiDriver_TOWNS::timerCallback(int timerId) { switch (timerId) { case 1: - if (_timerProc) { - _timerProc(_timerProcPara); - _tickCounter += 10000; - while (_tickCounter >= 4167) { - _tickCounter -= 4167; - _timerProc(_timerProcPara); - } - } + updateParser(); + updateOutputChannels(); + + /*_tickCounter1 += 10000; + while (_tickCounter1 >= 4167) { + _tickCounter1 -= 4167; + unkUpdate(); + }*/ break; default: break; @@ -906,6 +934,23 @@ TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) { return res; } +void MidiDriver_TOWNS::updateParser() { + if (_timerProc) + _timerProc(_timerProcPara); +} + +void MidiDriver_TOWNS::updateOutputChannels() { + _tickCounter2 += 10000; + while (_tickCounter2 >= 16667) { + _tickCounter2 -= 16667; + for (int i = 0; i < 6; i++) { + TownsMidiOutputChannel *oc = _out[i]; + if (oc->update()) + return; + } + } +} + int MidiDriver_TOWNS::randomValue(int para) { _rand = (_rand & 1) ? (_rand >> 1) ^ 0xb8 : (_rand >> 1); return (_rand * para) >> 8; diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 1a4a8613ca..a525226959 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -59,7 +59,10 @@ public: private: TownsMidiOutputChannel *allocateOutputChannel(int pri); - + + void updateParser(); + void updateOutputChannels(); + int randomValue(int para); TownsMidiInputChannel **_channels; @@ -71,7 +74,8 @@ private: TownsAudioInterface *_intf; - uint32 _tickCounter; + uint32 _tickCounter1; + uint32 _tickCounter2; uint8 _curChan; uint8 _rand; -- cgit v1.2.3 From 75770ae691438217b7ee613fbfed1f51562d794d Mon Sep 17 00:00:00 2001 From: athrxx Date: Tue, 3 May 2011 22:14:34 +0200 Subject: FM-TOWNS AUDIO: Fix mod wheel setting --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 42 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index c28f9a12a0..0c04044a76 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -59,18 +59,15 @@ private: uint8 fld_11; uint8 ar1[4]; uint8 ar2[4]; - uint8 fld_1a; - uint8 modWheelImpact; + int8 modWheelSensitivity; + uint8 modWheelState; uint8 fld_1c; uint32 fld_1d; uint32 fld_21; uint32 fld_25; int8 dir; uint32 fld_2a; - uint8 fld_2b; - uint8 fld_2c; - uint8 fld_2d; - uint8 modWheel; + uint32 fld_2e; } *_stateA; struct StateB { @@ -84,7 +81,7 @@ private: uint32 getEffectState(uint8 type); void initEffect(StateA *a, const uint8 *effectData); void updateEffectOuter3(StateA *a, StateB *b); - void updateEffectOuter(StateA *a, StateB *b); + int updateEffectOuter(StateA *a, StateB *b); void updateEffect(StateA *a); int lookupVolume(int a, int b); @@ -306,8 +303,8 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec b->fld_6 = c & 0x10; b->type = para1[c & 0x0f]; a->fld_9 = maxVal[c & 0x0f]; - a->fld_1a = 0x1f; - a->modWheelImpact = b->useModWheel ? _midi->_modWheel >> 2 : 0x1f; + a->modWheelSensitivity = 0x1f; + a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 0x1f; switch (b->type) { case 0: @@ -318,11 +315,11 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec break; case 30: a->effectState = 0x1f; - b->a->modWheelImpact = 0; + b->a->modWheelState = 0; break; case 31: a->effectState = 0; - b->a->fld_1a = 0; + b->a->modWheelSensitivity = 0; break; default: a->effectState = getEffectState(b->type); @@ -334,10 +331,10 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec void TownsMidiOutputChannel::setModWheel(uint8 value) { if (_stateA[0].numLoop && _stateB[0].type) - _stateA[0].modWheel = value >> 2; + _stateA[0].modWheelState = value >> 2; if (_stateA[1].numLoop && _stateB[1].type) - _stateA[1].modWheel = value >> 2; + _stateA[1].modWheelState = value >> 2; } void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) { @@ -369,10 +366,12 @@ bool TownsMidiOutputChannel::update() { if (!_midi) return false; - _duration -= 17; - if (_duration <=0) { - disconnect(); - return true; + if (_duration) { + _duration -= 17; + if (_duration <=0) { + disconnect(); + return true; + } } for (int i = 0; i < 2; i++) { @@ -433,14 +432,14 @@ void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) { } -void TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { - +int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { + return 0; } void TownsMidiOutputChannel::updateEffect(StateA *a) { uint8 c = --a->numLoop; uint16 v = a->ar1[c]; - int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->fld_1a]]; + int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]]; if (v & 0x80) e = _driver->randomValue(e); @@ -471,8 +470,7 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) { a->fld_25 = d / a->fld_1d; a->dir = d < 0 ? -1 : 1; a->fld_2a = d % a->fld_1d; - - a->fld_2b = a->fld_2c = a->fld_2d = a->modWheel = 0; + a->fld_2e = 0; } int TownsMidiOutputChannel::lookupVolume(int a, int b) { -- cgit v1.2.3 From 88896117da13a9222b7bf27bb2890705cf48d5ef Mon Sep 17 00:00:00 2001 From: athrxx Date: Wed, 4 May 2011 17:57:39 +0200 Subject: FM-TOWNS AUDIO: Some more midi driver code --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 3 +- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 101 ++++++++++++++++++++++----- 2 files changed, 85 insertions(+), 19 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 065532f526..33606128bf 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -467,6 +467,7 @@ int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) { if (command < 0 || command > 81) return 4; + Common::StackLock lock(_mutex); return (this->*_intfOpcodes[command])(args); } @@ -918,7 +919,7 @@ int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) { left = (left & 0x7e) >> 1; right = (right & 0x7e) >> 1; - if (chan) + if (chan == 12) _outputVolumeFlags |= flags[chanType]; else _outputVolumeFlags &= ~flags[chanType]; diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 0c04044a76..7072149d2d 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -53,9 +53,9 @@ private: struct StateA { uint8 numLoop; int32 fld_1; - uint32 fld_5; + int32 duration; int32 fld_9; - int32 effectState; + int16 effectState; uint8 fld_11; uint8 ar1[4]; uint8 ar2[4]; @@ -63,7 +63,7 @@ private: uint8 modWheelState; uint8 fld_1c; uint32 fld_1d; - uint32 fld_21; + int32 fld_21; uint32 fld_25; int8 dir; uint32 fld_2a; @@ -71,14 +71,14 @@ private: } *_stateA; struct StateB { - uint32 fld_0; + int8 inc; uint8 type; uint8 useModWheel; uint8 fld_6; StateA *a; } *_stateB; - uint32 getEffectState(uint8 type); + uint16 getEffectState(uint8 type); void initEffect(StateA *a, const uint8 *effectData); void updateEffectOuter3(StateA *a, StateB *b); int updateEffectOuter(StateA *a, StateB *b); @@ -292,19 +292,19 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effectData) { uint16 maxVal[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F }; - uint8 para1[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 }; + uint8 effectType[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 }; StateA *a = &_stateA[index]; StateB *b = &_stateB[index]; - b->fld_0 = 0; + b->inc = 0; b->useModWheel = c & 0x40; a->fld_11 = c & 0x20; b->fld_6 = c & 0x10; - b->type = para1[c & 0x0f]; + b->type = effectType[c & 0x0f]; a->fld_9 = maxVal[c & 0x0f]; - a->modWheelSensitivity = 0x1f; - a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 0x1f; + a->modWheelSensitivity = 31; + a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 31; switch (b->type) { case 0: @@ -314,7 +314,7 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec a->effectState = _modulatorTl; break; case 30: - a->effectState = 0x1f; + a->effectState = 31; b->a->modWheelState = 0; break; case 31: @@ -392,7 +392,7 @@ int TownsMidiOutputChannel::checkPriority(int pri) { return kHighPriority; } -uint32 TownsMidiOutputChannel::getEffectState(uint8 type) { +uint16 TownsMidiOutputChannel::getEffectState(uint8 type) { uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan); if (type == 28) @@ -415,8 +415,8 @@ uint32 TownsMidiOutputChannel::getEffectState(uint8 type) { void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) { a->numLoop = 1; a->fld_1 = 0; - a->fld_1c = 0x1f; - a->fld_5 = effectData[0]; + a->fld_1c = 31; + a->duration = effectData[0] * 63; a->ar1[0] = effectData[1]; a->ar1[1] = effectData[3]; a->ar1[2] = effectData[5]; @@ -429,15 +429,80 @@ void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) { } void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) { + uint8 f = updateEffectOuter(a, b); + + if (f & 1) { + switch (b->type) { + case 0: + _carrierTl = (a->effectState & 0xff) + b->inc; /*???*/ + break; + case 13: + _modulatorTl = (a->effectState & 0xff) + b->inc; /*???*/ + break; + case 30: + b->a->modWheelState = b->inc; + break; + case 31: + b->a->modWheelSensitivity = b->inc; + break; + default: + break; + } + } + if (f & 2) { + if (b->fld_6) + keyOn(); + } } int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { - return 0; + if (a->duration) { + a->duration -= 17; + if (a->duration <= 0) { + a->numLoop = 0; + return 0; + } + } + + int32 t = a->fld_1 + a->fld_25; + + a->fld_2e += a->fld_2a; + if (a->fld_2e >= a->fld_1d) { + a->fld_2e -= a->fld_1d; + t += a->dir; + } + + int retFlags = 0; + + if (t != a->fld_1 || a->modWheelState != a->fld_1c) { + a->fld_1 = t; + a->fld_1c = a->modWheelState; + t = lookupVolume(t, a->modWheelState); + if (t != b->inc) + b->inc = t; + retFlags |= 1; + } + + if (--a->fld_21 != 0) + return retFlags; + + if (++a->numLoop > 4) { + if (a->fld_11 == 0) { + a->numLoop = 0; + return retFlags; + } + a->numLoop = 1; + retFlags |= 2; + } + + updateEffect(a); + + return retFlags; } void TownsMidiOutputChannel::updateEffect(StateA *a) { - uint8 c = --a->numLoop; + uint8 c = a->numLoop - 1; uint16 v = a->ar1[c]; int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]]; @@ -461,7 +526,7 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) { e = a->fld_9 - a->effectState; } else { if (e + a->effectState + 1 <= 0) - e = -e; + e = -a->effectState; } d = e - a->fld_1; @@ -646,7 +711,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { oc->_fld_c = _instrument[10] & 1; oc->_note = note; oc->_sustainNoteOff = 0; - oc->_duration = _instrument[29] * 72; + oc->_duration = _instrument[29] * 63; oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; if (oc->_modulatorTl > 63) -- cgit v1.2.3 From 90a300d86cf25ddaa15b8080f3551076a4f6e3ee Mon Sep 17 00:00:00 2001 From: athrxx Date: Thu, 5 May 2011 23:02:01 +0200 Subject: FM-TOWNS AUDIO: Improve thread safety --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 13 +++++---- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 32 ++++++++++++---------- audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp | 10 ++++--- .../softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 30 ++++++++++++++------ audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 8 +++++- 5 files changed, 59 insertions(+), 34 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 33606128bf..51c2000514 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -411,13 +411,13 @@ bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDrive if (_refCount <= 1) return true; - Common::StackLock lock(_mutex); - if (_drv) { if (driver && driver != _drv) return false; } else { + lock(); _drv = driver; + unlock(); } return true; @@ -467,8 +467,11 @@ int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) { if (command < 0 || command > 81) return 4; - Common::StackLock lock(_mutex); - return (this->*_intfOpcodes[command])(args); + lock(); + int res = (this->*_intfOpcodes[command])(args); + unlock(); + + return res; } void TownsAudioInterfaceIntern::setMusicVolume(int volume) { @@ -539,13 +542,11 @@ void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) { } void TownsAudioInterfaceIntern::timerCallbackA() { - Common::StackLock lock(_mutex); if (_drv && _ready) _drv->timerCallback(0); } void TownsAudioInterfaceIntern::timerCallbackB() { - Common::StackLock lock(_mutex); if (_ready) { if (_drv) _drv->timerCallback(1); diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 7072149d2d..ff14bb158a 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -52,7 +52,7 @@ public: private: struct StateA { uint8 numLoop; - int32 fld_1; + uint32 fld_1; int32 duration; int32 fld_9; int16 effectState; @@ -60,10 +60,10 @@ private: uint8 ar1[4]; uint8 ar2[4]; int8 modWheelSensitivity; - uint8 modWheelState; + int8 modWheelState; uint8 fld_1c; uint32 fld_1d; - int32 fld_21; + uint32 fld_21; uint32 fld_25; int8 dir; uint32 fld_2a; @@ -71,14 +71,14 @@ private: } *_stateA; struct StateB { - int8 inc; + int16 inc; uint8 type; uint8 useModWheel; uint8 fld_6; StateA *a; } *_stateB; - uint16 getEffectState(uint8 type); + int16 getEffectState(uint8 type); void initEffect(StateA *a, const uint8 *effectData); void updateEffectOuter3(StateA *a, StateB *b); int updateEffectOuter(StateA *a, StateB *b); @@ -159,7 +159,7 @@ private: int8 _transpose; uint8 _fld_1f; int8 _detune; - uint8 _modWheel; + int8 _modWheel; uint8 _sustain; uint8 _pitchBendFactor; int16 _pitchBend; @@ -392,7 +392,7 @@ int TownsMidiOutputChannel::checkPriority(int pri) { return kHighPriority; } -uint16 TownsMidiOutputChannel::getEffectState(uint8 type) { +int16 TownsMidiOutputChannel::getEffectState(uint8 type) { uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan); if (type == 28) @@ -404,7 +404,7 @@ uint16 TownsMidiOutputChannel::getEffectState(uint8 type) { else if (type > 12) type -= 13; - uint32 res = 0; + int32 res = 0; uint8 cs = (_driver->_chanState[chan].get(_effectDefs[type * 4] >> 5) & _effectDefs[type * 4 + 2]) >> _effectDefs[type * 4 + 1]; if (_effectDefs[type * 4 + 3]) res = _effectDefs[type * 4 + 3] - cs; @@ -422,7 +422,7 @@ void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) { a->ar1[2] = effectData[5]; a->ar1[3] = effectData[6]; a->ar2[0] = effectData[2]; - a->ar2[1] = effectData[3]; + a->ar2[1] = effectData[4]; a->ar2[2] = 0; a->ar2[3] = effectData[7]; updateEffect(a); @@ -434,10 +434,10 @@ void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) { if (f & 1) { switch (b->type) { case 0: - _carrierTl = (a->effectState & 0xff) + b->inc; /*???*/ + _carrierTl = a->effectState + b->inc; /*???*/ break; case 13: - _modulatorTl = (a->effectState & 0xff) + b->inc; /*???*/ + _modulatorTl = a->effectState + b->inc; /*???*/ break; case 30: b->a->modWheelState = b->inc; @@ -504,7 +504,7 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { void TownsMidiOutputChannel::updateEffect(StateA *a) { uint8 c = a->numLoop - 1; uint16 v = a->ar1[c]; - int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]]; + int32 e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]]; if (v & 0x80) e = _driver->randomValue(e); @@ -545,7 +545,7 @@ int TownsMidiOutputChannel::lookupVolume(int a, int b) { if (b == 31) return a; - if (a > 63) + if (a > 63 || a < -63) return ((a + 1) * b) >> 5; if (b < 0) { @@ -760,6 +760,10 @@ void TownsMidiInputChannel::controlChange(byte control, byte value) { case 64: controlSustain(value); break; + case 123: + while (_outChan) + _outChan->disconnect(); + break; default: break; } @@ -793,7 +797,7 @@ void TownsMidiInputChannel::controlVolume(byte value) { uint16 v2 = value; if (_chanIndex != 16) { _ctrlVolume = value; - v2 = value; + v2 = _player->getEffectiveVolume(); } _tl = (v1 * v2) >> 7;*/ diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp index 289cc95863..e35da91cbb 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp @@ -1145,7 +1145,7 @@ void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) { reset(); - Common::StackLock lock(_mutex); + lock(); uint8 *src_a = _trackPtr = _musicBuffer = data; for (uint8 i = 0; i < 3; i++) { @@ -1176,6 +1176,7 @@ void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) { _finishedChannelsFlag = _finishedSSGFlag = _finishedRhythmFlag = 0; _musicPlaying = (loadPaused ? false : true); + unlock(); } void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) { @@ -1194,16 +1195,17 @@ void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) { return; } - Common::StackLock lock(_mutex); + lock(); _sfxData = _sfxBuffer = data; _sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]); _sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]); _sfxPlaying = true; _finishedSfxFlag = 0; + unlock(); } void TownsPC98_AudioDriver::reset() { - Common::StackLock lock(_mutex); + lock(); _musicPlaying = false; _sfxPlaying = false; @@ -1230,13 +1232,13 @@ void TownsPC98_AudioDriver::reset() { if (_rhythmChannel) _rhythmChannel->reset(); #endif + unlock(); } void TownsPC98_AudioDriver::fadeStep() { if (!_musicPlaying) return; - Common::StackLock lock(_mutex); for (int j = 0; j < _numChan; j++) { if (_updateChannelsFlag & _channels[j]->_idFlag) _channels[j]->fadeStep(); diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index 57ab8d9e1f..9412538685 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -837,8 +837,7 @@ TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) : _hasPercussion(type == kType86 ? true : false), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()), - _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), - _regProtectionFlag(false), _ready(false) { + _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _externLock(0), _ready(false) { memset(&_timers[0], 0, sizeof(ChipTimer)); memset(&_timers[1], 0, sizeof(ChipTimer)); @@ -931,9 +930,9 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) { if (_regProtectionFlag || !_ready) return; - static const uint8 oprOrdr[] = { 0, 2, 1, 3 }; + lock(); - Common::StackLock lock(_mutex); + static const uint8 oprOrdr[] = { 0, 2, 1, 3 }; uint8 h = regAddress & 0xf0; uint8 l = (regAddress & 0x0f); @@ -1081,6 +1080,7 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) { if (l == 0) { c->frqTemp = (c->frqTemp & 0xff00) | value; c->updateEnvelopeParameters = true; + c->fmIndex = (c->frqTemp >> 4 & 0x7f); for (int i = 0; i < 4; i++) co[i]->frequency(c->frqTemp); } else if (l == 4) { @@ -1112,18 +1112,17 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) { default: warning("TownsPC98_FmSynth: UNKNOWN ADDRESS %d", regAddress); } + unlock(); } int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { - Common::StackLock lock(_mutex); - memset(buffer, 0, sizeof(int16) * numSamples); int32 *tmp = new int32[numSamples]; int32 *tmpStart = tmp; memset(tmp, 0, sizeof(int32) * numSamples); int32 samplesLeft = numSamples >> 1; - while (_ready && samplesLeft) { + while (_ready && !_externLock && samplesLeft) { int32 render = samplesLeft; for (int i = 0; i < 2; i++) { @@ -1173,6 +1172,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { } delete[] tmpStart; + return numSamples; } @@ -1187,7 +1187,7 @@ uint8 TownsPC98_FmSynth::readSSGStatus() { } void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) { - Common::StackLock lock(_mutex); + lock(); _volumeA = CLIP(volA, 0, Audio::Mixer::kMaxMixerVolume); _volumeB = CLIP(volB, 0, Audio::Mixer::kMaxMixerVolume); if (_ssg) @@ -1196,10 +1196,11 @@ void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) { if (_prc) _prc->setVolumeIntern(_volumeA, _volumeB); #endif + unlock(); } void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB) { - Common::StackLock lock(_mutex); + lock(); _volMaskA = channelMaskA; _volMaskB = channelMaskB; if (_ssg) @@ -1208,6 +1209,17 @@ void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB if (_prc) _prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG)); #endif + unlock(); +} + +void TownsPC98_FmSynth::lock() { + _mutex.lock(); + _externLock++; +} + +void TownsPC98_FmSynth::unlock() { + _mutex.unlock(); + _externLock--; } void TownsPC98_FmSynth::generateTables() { diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index 5edd1a3ab8..f1494b6ba7 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -102,11 +102,13 @@ protected: void setVolumeIntern(int volA, int volB); void setVolumeChannelMasks(int channelMaskA, int channelMaskB); + void lock(); + void unlock(); + const int _numChan; const int _numSSG; const bool _hasPercussion; - Common::Mutex _mutex; private: void generateTables(); void nextTick(int32 *buffer, uint32 bufferSize); @@ -124,6 +126,7 @@ private: } uint16 frqTemp; + uint8 fmIndex; bool enableLeft; bool enableRight; bool updateEnvelopeParameters; @@ -179,6 +182,9 @@ private: Audio::Mixer *_mixer; Audio::SoundHandle _soundHandle; + int _externLock; + Common::Mutex _mutex; + #ifndef DISABLE_PC98_RHYTHM_CHANNEL static const uint8 _percussionData[]; #endif -- cgit v1.2.3 From 8fb5906117c67f4265e868b33aa343698bceac73 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sat, 7 May 2011 16:44:43 +0200 Subject: FM-TOWNS AUDIO: Some midi code fixes and some renaming --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 20 ++- audio/softsynth/fmtowns_pc98/towns_euphony.cpp | 22 +-- audio/softsynth/fmtowns_pc98/towns_euphony.h | 6 +- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 185 ++++++++++++--------- audio/softsynth/fmtowns_pc98/towns_midi.h | 15 +- .../softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 12 +- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 2 +- 7 files changed, 148 insertions(+), 114 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 51c2000514..6679e65cd2 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -163,8 +163,10 @@ private: int intf_fmReset(va_list &args); int intf_setOutputVolume(va_list &args); int intf_resetOutputVolume(va_list &args); - int intf_updateOutputVolume(va_list &args); + int intf_setOutputMute(va_list &args); int intf_cdaToggle(va_list &args); + int intf_getOutputVolume(va_list &args); + int intf_getOutputMute(va_list &args); int intf_pcmUpdateEnvelopeGenerator(va_list &args); int intf_notImpl(va_list &args); @@ -344,13 +346,13 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA // 68 INTCB(resetOutputVolume), INTCB(notImpl), - INTCB(updateOutputVolume), + INTCB(setOutputMute), INTCB(notImpl), // 72 INTCB(notImpl), INTCB(cdaToggle), - INTCB(notImpl), - INTCB(notImpl), + INTCB(getOutputVolume), + INTCB(getOutputMute), // 76 INTCB(notImpl), INTCB(notImpl), @@ -947,7 +949,7 @@ int TownsAudioInterfaceIntern::intf_resetOutputVolume(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_updateOutputVolume(va_list &args) { +int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) { int flags = va_arg(args, int); _outputMuteFlags = flags & 3; updateOutputVolume(); @@ -960,6 +962,14 @@ int TownsAudioInterfaceIntern::intf_cdaToggle(va_list &args) { return 0; } +int TownsAudioInterfaceIntern::intf_getOutputVolume (va_list &args) { + return 0; +} + +int TownsAudioInterfaceIntern::intf_getOutputMute (va_list &args) { + return 0; +} + int TownsAudioInterfaceIntern::intf_pcmUpdateEnvelopeGenerator(va_list &args) { for (int i = 0; i < 8; i++) pcmUpdateEnvelopeGenerator(i); diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp index cb6cfc53f3..f161228876 100644 --- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp @@ -27,7 +27,7 @@ TownsEuphonyDriver::TownsEuphonyDriver(Audio::Mixer *mixer) : _activeChannels(0), _sustainChannels(0), _assignedChannels(0), _paraCount(0), _command(0), _tEnable(0), _tMode(0), _tOrdr(0), _tLevel(0), - _tDetune(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0), + _tTranspose(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0), _tempoControlMode(0) { _para[0] = _para[1] = 0; _intf = new TownsAudioInterface(mixer, this); @@ -44,7 +44,7 @@ TownsEuphonyDriver::~TownsEuphonyDriver() { delete[] _tMode; delete[] _tOrdr; delete[] _tLevel; - delete[] _tDetune; + delete[] _tTranspose; } bool TownsEuphonyDriver::init() { @@ -59,7 +59,7 @@ bool TownsEuphonyDriver::init() { delete[] _tMode; delete[] _tOrdr; delete[] _tLevel; - delete[] _tDetune; + delete[] _tTranspose; _activeChannels = new int8[16]; _sustainChannels = new int8[16]; @@ -70,7 +70,7 @@ bool TownsEuphonyDriver::init() { _tMode = new uint8[32]; _tOrdr = new uint8[32]; _tLevel = new int8[32]; - _tDetune = new int8[32]; + _tTranspose = new int8[32]; reset(); @@ -250,11 +250,11 @@ int TownsEuphonyDriver::configChan_adjustVolume(int tableEntry, int val) { return 0; } -int TownsEuphonyDriver::configChan_setDetune(int tableEntry, int val) { +int TownsEuphonyDriver::configChan_setTranspose(int tableEntry, int val) { if (tableEntry > 31) return 3; if (val <= 40) - _tDetune[tableEntry] = (int8)(val & 0xff); + _tTranspose[tableEntry] = (int8)(val & 0xff); return 0; } @@ -325,7 +325,7 @@ void TownsEuphonyDriver::resetTables() { for (int i = 0; i < 32; i++) _tOrdr[i] = i & 0x0f; memset(_tLevel, 0, 32); - memset(_tDetune, 0, 32); + memset(_tTranspose, 0, 32); } void TownsEuphonyDriver::resetTempo() { @@ -672,7 +672,7 @@ bool TownsEuphonyDriver::evtSetupNote() { uint8 velo = _musicPos[5]; sendEvent(mode, evt); - sendEvent(mode, applyDetune(note)); + sendEvent(mode, applyTranspose(note)); sendEvent(mode, applyVolumeAdjust(velo)); jumpNextLoop(); @@ -712,7 +712,7 @@ bool TownsEuphonyDriver::evtPolyphonicAftertouch() { uint8 mode = _tMode[_musicPos[1]]; sendEvent(mode, evt); - sendEvent(mode, applyDetune(_musicPos[4])); + sendEvent(mode, applyTranspose(_musicPos[4])); sendEvent(mode, _musicPos[5]); return false; @@ -780,8 +780,8 @@ bool TownsEuphonyDriver::evtModeOrdrChange() { return false; } -uint8 TownsEuphonyDriver::applyDetune(uint8 in) { - int out = _tDetune[_musicPos[1]]; +uint8 TownsEuphonyDriver::applyTranspose(uint8 in) { + int out = _tTranspose[_musicPos[1]]; if (!out) return in; out += (in & 0x7f); diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.h b/audio/softsynth/fmtowns_pc98/towns_euphony.h index ae36d1232b..6b30bfb7f5 100644 --- a/audio/softsynth/fmtowns_pc98/towns_euphony.h +++ b/audio/softsynth/fmtowns_pc98/towns_euphony.h @@ -59,7 +59,7 @@ public: int configChan_setMode(int tableEntry, int val); int configChan_remap(int tableEntry, int val); int configChan_adjustVolume(int tableEntry, int val); - int configChan_setDetune(int tableEntry, int val); + int configChan_setTranspose(int tableEntry, int val); int assignChannel(int chan, int tableEntry); @@ -111,7 +111,7 @@ private: return false; } - uint8 applyDetune(uint8 in); + uint8 applyTranspose(uint8 in); uint8 applyVolumeAdjust(uint8 in); void sendNoteOff(); @@ -136,7 +136,7 @@ private: uint8 *_tMode; uint8 *_tOrdr; int8 *_tLevel; - int8 *_tDetune; + int8 *_tTranspose; struct DlEvent { uint8 evt; diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index ff14bb158a..ac6a89fbc0 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -24,6 +24,7 @@ #include "audio/softsynth/fmtowns_pc98/towns_midi.h" #include "common/textconsole.h" +#include "common/system.h" class TownsMidiOutputChannel { friend class TownsMidiInputChannel; @@ -33,8 +34,8 @@ public: void noteOn(uint8 msb, uint16 lsb); void noteOnPitchBend(uint8 msb, uint16 lsb); - void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2); - void setupEffects(int index, uint8 c, const uint8 *effectData); + void setupProgram(const uint8 *data, uint8 mLevelPara, uint8 tLevelPara); + void setupEffects(int index, uint8 flags, const uint8 *effectData); void setModWheel(uint8 value); void connect(TownsMidiInputChannel *chan); @@ -52,26 +53,26 @@ public: private: struct StateA { uint8 numLoop; - uint32 fld_1; + int32 fld_1; int32 duration; - int32 fld_9; - int16 effectState; + uint32 fld_9; + int32 effectState; uint8 fld_11; uint8 ar1[4]; uint8 ar2[4]; int8 modWheelSensitivity; int8 modWheelState; - uint8 fld_1c; - uint32 fld_1d; + uint8 modWheelLast; + uint16 fld_1d; uint32 fld_21; - uint32 fld_25; + int32 fld_25; int8 dir; uint32 fld_2a; uint32 fld_2e; } *_stateA; struct StateB { - int16 inc; + int32 inc; uint8 type; uint8 useModWheel; uint8 fld_6; @@ -99,7 +100,7 @@ private: uint8 _carrierTl; uint8 _modulatorTl; uint8 _sustainNoteOff; - int32 _duration; + int16 _duration; uint16 _freq; int16 _freqAdjust; @@ -237,7 +238,7 @@ void TownsMidiOutputChannel::noteOnPitchBend(uint8 msb, uint16 lsb) { keyOnSetFreq(_freq + _freqAdjust); } -void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) { +void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, uint8 tLevelPara) { // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7), // since it is just a modified AdLib driver. It also uses AdLib programs. // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS @@ -248,10 +249,10 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v uint8 chan = _chanMap[_chan]; uint8 mulAmsFms1 = _driver->_chanState[chan].mulAmsFms = data[0]; - uint8 tl1 = _driver->_chanState[chan].tl = (data[1] | 0x3f) - vol1; + uint8 tl1 = _driver->_chanState[chan].tl = (data[1] | 0x3f) - mLevelPara; uint8 attDec1 = _driver->_chanState[chan].attDec = ~data[2]; uint8 sus1 = _driver->_chanState[chan].sus = ~data[3]; - uint8 unk1 = _driver->_chanState[chan].unk2 = data[4]; + _driver->_chanState[chan].unk2 = data[4]; chan += 3; out(0x30, mul[mulAmsFms1 & 0x0f]); @@ -262,10 +263,10 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v out(0x80, sus1); uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = data[5]; - uint8 tl2 = _driver->_chanState[chan].tl = (data[6] | 0x3f) - vol2; + uint8 tl2 = _driver->_chanState[chan].tl = (data[6] | 0x3f) - tLevelPara; uint8 attDec2 = _driver->_chanState[chan].attDec = ~data[7]; uint8 sus2 = _driver->_chanState[chan].sus = ~data[8]; - uint8 unk2 = _driver->_chanState[chan].unk2 = data[9]; + _driver->_chanState[chan].unk2 = data[9]; uint8 mul2 = mul[mulAmsFms2 & 0x0f]; tl2 = (tl2 & 0x3f) + 15; @@ -290,7 +291,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5)); } -void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effectData) { +void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *effectData) { uint16 maxVal[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F }; uint8 effectType[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 }; @@ -298,11 +299,11 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec StateB *b = &_stateB[index]; b->inc = 0; - b->useModWheel = c & 0x40; - a->fld_11 = c & 0x20; - b->fld_6 = c & 0x10; - b->type = effectType[c & 0x0f]; - a->fld_9 = maxVal[c & 0x0f]; + b->useModWheel = flags & 0x40; + a->fld_11 = flags & 0x20; + b->fld_6 = flags & 0x10; + b->type = effectType[flags & 0x0f]; + a->fld_9 = maxVal[flags & 0x0f]; a->modWheelSensitivity = 31; a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 31; @@ -368,8 +369,9 @@ bool TownsMidiOutputChannel::update() { if (_duration) { _duration -= 17; - if (_duration <=0) { + if (_duration <= 0) { disconnect(); + //_duration = 0; return true; } } @@ -415,7 +417,7 @@ int16 TownsMidiOutputChannel::getEffectState(uint8 type) { void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) { a->numLoop = 1; a->fld_1 = 0; - a->fld_1c = 31; + a->modWheelLast = 31; a->duration = effectData[0] * 63; a->ar1[0] = effectData[1]; a->ar1[1] = effectData[3]; @@ -475,16 +477,17 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { int retFlags = 0; - if (t != a->fld_1 || a->modWheelState != a->fld_1c) { + if (t != a->fld_1 || a->modWheelState != a->modWheelLast) { a->fld_1 = t; - a->fld_1c = a->modWheelState; + a->modWheelLast = a->modWheelState; t = lookupVolume(t, a->modWheelState); if (t != b->inc) b->inc = t; retFlags |= 1; } - if (--a->fld_21 != 0) + --a->fld_21;/*???*/ + if (a->fld_21 != 0) return retFlags; if (++a->numLoop > 4) { @@ -504,7 +507,7 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { void TownsMidiOutputChannel::updateEffect(StateA *a) { uint8 c = a->numLoop - 1; uint16 v = a->ar1[c]; - int32 e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]]; + int32 e = _effectData[_driver->_chanEffectLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]]; if (v & 0x80) e = _driver->randomValue(e); @@ -515,7 +518,7 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) { a->fld_1d = a->fld_21 = e; int32 d = 0; - if (c + 1 != 3) { + if (c != 2) { v = a->ar2[c]; e = lookupVolume(a->fld_9, (v & 0x7f) - 31); @@ -533,7 +536,8 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) { } a->fld_25 = d / a->fld_1d; - a->dir = d < 0 ? -1 : 1; + a->dir = (d < 0) ? -1 : 1; + d *= a->dir; a->fld_2a = d % a->fld_1d; a->fld_2e = 0; } @@ -550,14 +554,14 @@ int TownsMidiOutputChannel::lookupVolume(int a, int b) { if (b < 0) { if (a < 0) - return _driver->_chanOutputLevel[(-a << 5) - b]; + return _driver->_chanEffectLevel[((-a) << 5) - b]; else - return -_driver->_chanOutputLevel[(a << 5) - b]; + return -_driver->_chanEffectLevel[(a << 5) - b]; } else { if (a < 0) - return -_driver->_chanOutputLevel[(-a << 5) + b]; + return -_driver->_chanEffectLevel[((-a) << 5) + b]; else - return _driver->_chanOutputLevel[(-a << 5) + b]; + return _driver->_chanEffectLevel[((-a) << 5) + b]; } } @@ -713,15 +717,15 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { oc->_sustainNoteOff = 0; oc->_duration = _instrument[29] * 63; - oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; + oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanEffectLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; if (oc->_modulatorTl > 63) oc->_modulatorTl = 63; - oc->_carrierTl = (_instrument[6] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)]; + oc->_carrierTl = (_instrument[6] & 0x3f) + _driver->_chanEffectLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)]; if (oc->_carrierTl > 63) oc->_carrierTl = 63; - oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]); + oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]); oc->noteOn(note + _transpose, _freqLSB); if (_instrument[11] & 0x80) @@ -838,6 +842,19 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter1(0), _tickCounter2(0), _curChan(0), _rand(1), _open(false) { _intf = new TownsAudioInterface(mixer, this); +} + +MidiDriver_TOWNS::~MidiDriver_TOWNS() { + close(); + delete _intf; +} + +int MidiDriver_TOWNS::open() { + if (_open) + return MERR_ALREADY_OPEN; + + if (!_intf->init()) + return MERR_CANNOT_CONNECT; _channels = new TownsMidiInputChannel*[32]; for (int i = 0; i < 32; i++) @@ -849,38 +866,13 @@ MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerP _chanState = new TownsMidiChanState[32]; - _chanOutputLevel = new uint8[2048]; + _chanEffectLevel = new uint8[2048]; for (int i = 0; i < 64; i++) { for (int ii = 0; ii < 32; ii++) - _chanOutputLevel[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff; + _chanEffectLevel[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff; } for (int i = 0; i < 64; i++) - _chanOutputLevel[i << 5] = 0; -} - -MidiDriver_TOWNS::~MidiDriver_TOWNS() { - close(); - delete _intf; - setTimerCallback(0, 0); - - for (int i = 0; i < 32; i++) - delete _channels[i]; - delete[] _channels; - - for (int i = 0; i < 6; i++) - delete _out[i]; - delete[] _out; - - delete[] _chanState; - delete[] _chanOutputLevel; -} - -int MidiDriver_TOWNS::open() { - if (_open) - return MERR_ALREADY_OPEN; - - if (!_intf->init()) - return MERR_CANNOT_CONNECT; + _chanEffectLevel[i << 5] = 0; _intf->callback(0); @@ -897,10 +889,38 @@ int MidiDriver_TOWNS::open() { } void MidiDriver_TOWNS::close() { + if (!_open) + return; + _open = false; + + setTimerCallback(0, 0); + g_system->delayMillis(20); + + if (_channels) { + for (int i = 0; i < 32; i++) + delete _channels[i]; + delete[] _channels; + } + _channels = 0; + + if (_out) { + for (int i = 0; i < 6; i++) + delete _out[i]; + delete[] _out; + } + _out = 0; + + delete[] _chanState; + _chanState = 0; + delete[] _chanEffectLevel; + _chanEffectLevel = 0; } void MidiDriver_TOWNS::send(uint32 b) { + if (!_open) + return; + byte param2 = (b >> 16) & 0xFF; byte param1 = (b >> 8) & 0xFF; byte cmd = b & 0xF0; @@ -945,6 +965,9 @@ uint32 MidiDriver_TOWNS::getBaseTempo() { } MidiChannel *MidiDriver_TOWNS::allocateChannel() { + if (!_open) + return 0; + for (int i = 0; i < 32; ++i) { TownsMidiInputChannel *chan = _channels[i]; if (chan->allocate()) @@ -978,6 +1001,23 @@ void MidiDriver_TOWNS::timerCallback(int timerId) { } } +void MidiDriver_TOWNS::updateParser() { + if (_timerProc) + _timerProc(_timerProcPara); +} + +void MidiDriver_TOWNS::updateOutputChannels() { + _tickCounter2 += 10000; + while (_tickCounter2 >= 16667) { + _tickCounter2 -= 16667; + for (int i = 0; i < 6; i++) { + TownsMidiOutputChannel *oc = _out[i]; + if (oc->update()) + return; + } + } +} + TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) { TownsMidiOutputChannel *res = 0; @@ -1001,23 +1041,6 @@ TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) { return res; } -void MidiDriver_TOWNS::updateParser() { - if (_timerProc) - _timerProc(_timerProcPara); -} - -void MidiDriver_TOWNS::updateOutputChannels() { - _tickCounter2 += 10000; - while (_tickCounter2 >= 16667) { - _tickCounter2 -= 16667; - for (int i = 0; i < 6; i++) { - TownsMidiOutputChannel *oc = _out[i]; - if (oc->update()) - return; - } - } -} - int MidiDriver_TOWNS::randomValue(int para) { _rand = (_rand & 1) ? (_rand >> 1) ^ 0xb8 : (_rand >> 1); return (_rand * para) >> 8; diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index a525226959..5164e04708 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -43,25 +43,22 @@ public: int open(); bool isOpen() const { return _open; } void close(); + void send(uint32 b); - //virtual uint32 property(int prop, uint32 param) { return 0; } - //virtual void sysEx(const byte *msg, uint16 length) { } - //virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { } - //virtual void metaEvent(byte type, byte *data, uint16 length) { } + void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc); + uint32 getBaseTempo(); MidiChannel *allocateChannel(); MidiChannel *getPercussionChannel(); void timerCallback(int timerId); - TownsAudioInterface *intf() { return _intf; } - private: - TownsMidiOutputChannel *allocateOutputChannel(int pri); - void updateParser(); void updateOutputChannels(); + + TownsMidiOutputChannel *allocateOutputChannel(int pri); int randomValue(int para); @@ -81,7 +78,7 @@ private: bool _open; - uint8 *_chanOutputLevel; + uint8 *_chanEffectLevel; }; #endif diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index 9412538685..263986ec0c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -837,7 +837,7 @@ TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) : _hasPercussion(type == kType86 ? true : false), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()), - _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _externLock(0), _ready(false) { + _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _lock(0), _ready(false) { memset(&_timers[0], 0, sizeof(ChipTimer)); memset(&_timers[1], 0, sizeof(ChipTimer)); @@ -1121,8 +1121,9 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { int32 *tmpStart = tmp; memset(tmp, 0, sizeof(int32) * numSamples); int32 samplesLeft = numSamples >> 1; + _lock |= 0x10000; - while (_ready && !_externLock && samplesLeft) { + while (_ready && !(_lock & 0xffff) && samplesLeft) { int32 render = samplesLeft; for (int i = 0; i < 2; i++) { @@ -1171,6 +1172,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { tmp += (render << 1); } + _lock &= ~0x10000; delete[] tmpStart; return numSamples; @@ -1178,6 +1180,8 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { void TownsPC98_FmSynth::deinit() { _ready = false; + while (_lock) + g_system->delayMillis(20); _mixer->stopHandle(_soundHandle); _timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback; } @@ -1214,12 +1218,12 @@ void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB void TownsPC98_FmSynth::lock() { _mutex.lock(); - _externLock++; + _lock++; } void TownsPC98_FmSynth::unlock() { _mutex.unlock(); - _externLock--; + _lock--; } void TownsPC98_FmSynth::generateTables() { diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index f1494b6ba7..cbf856c78c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -182,7 +182,7 @@ private: Audio::Mixer *_mixer; Audio::SoundHandle _soundHandle; - int _externLock; + int _lock; Common::Mutex _mutex; #ifndef DISABLE_PC98_RHYTHM_CHANNEL -- cgit v1.2.3 From c6f13d187e31d5642f4a789a2e1eb2b5f2708775 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 8 May 2011 18:20:39 +0200 Subject: FM-TOWNS AUDIO: Fix some midi driver bugs --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 109 +++++++++++++++------------- audio/softsynth/fmtowns_pc98/towns_midi.h | 4 +- 2 files changed, 60 insertions(+), 53 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index ac6a89fbc0..9fa6a8ceac 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -44,8 +44,8 @@ public: bool update(); enum CheckPriorityStatus { - kDisconnected = -3, - kHighPriority = -2 + kDisconnected = -2, + kHighPriority = -1 }; int checkPriority(int pri); @@ -55,14 +55,14 @@ private: uint8 numLoop; int32 fld_1; int32 duration; - uint32 fld_9; + uint16 fld_9; int32 effectState; uint8 fld_11; uint8 ar1[4]; uint8 ar2[4]; int8 modWheelSensitivity; int8 modWheelState; - uint8 modWheelLast; + int8 modWheelLast; uint16 fld_1d; uint32 fld_21; int32 fld_25; @@ -91,10 +91,10 @@ private: void keyOnSetFreq(uint16 frq); void out(uint8 reg, uint8 val); - TownsMidiInputChannel *_midi; + TownsMidiInputChannel *_in; TownsMidiOutputChannel *_prev; TownsMidiOutputChannel *_next; - uint8 _fld_c; + uint8 _adjustModTl; uint8 _chan; uint8 _note; uint8 _carrierTl; @@ -145,7 +145,7 @@ private: void releasePedal(); - TownsMidiOutputChannel *_outChan; + TownsMidiOutputChannel *_out; uint8 *_instrument; uint8 _prg; @@ -215,11 +215,13 @@ uint8 TownsMidiChanState::get(uint8 type) { } TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex), - _midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) { + _in(0), _prev(0), _next(0), _adjustModTl(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) { _stateA = new StateA[2]; memset(_stateA, 0, 2 * sizeof(StateA)); _stateB = new StateB[2]; memset(_stateB, 0, 2 * sizeof(StateB)); + _stateB[0].a = &_stateA[1]; + _stateB[1].a = &_stateA[0]; } TownsMidiOutputChannel::~TownsMidiOutputChannel() { @@ -259,7 +261,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u out(0x40, (tl1 & 0x3f) + 15); out(0x50, ((attDec1 >> 4) << 1) | ((attDec1 >> 4) & 1)); out(0x60, ((attDec1 << 1) | (attDec1 & 1)) & 0x1f); - out(0x70, (mulAmsFms1 & 0x20) ^ 0x20 ? ((sus1 & 0x0f) << 1) | 1: 0); + out(0x70, (mulAmsFms1 & 0x20) ^ 0x20 ? (((sus1 & 0x0f) << 1) | 1) : 0); out(0x80, sus1); uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = data[5]; @@ -272,7 +274,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u tl2 = (tl2 & 0x3f) + 15; uint8 ar2 = ((attDec2 >> 4) << 1) | ((attDec2 >> 4) & 1); uint8 dec2 = ((attDec2 << 1) | (attDec2 & 1)) & 0x1f; - uint8 sus2r = (mulAmsFms2 & 0x20) ^ 0x20 ? ((sus2 & 0x0f) << 1) | 1: 0; + uint8 sus2r = (mulAmsFms2 & 0x20) ^ 0x20 ? (((sus2 & 0x0f) << 1) | 1) : 0; for (int i = 4; i < 16; i += 4) { out(0x30 + i, mul2); @@ -284,11 +286,12 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u } _driver->_chanState[chan].fgAlg = data[10]; + uint8 alg = 5 + 2 * (data[10] & 1); uint8 fb = 4 * (data[10] & 0x0e); out(0xb0, fb | alg); uint8 t = mulAmsFms1 | mulAmsFms2; - out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5)); + out(0xb4, (0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5))); } void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *effectData) { @@ -305,7 +308,7 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *e b->type = effectType[flags & 0x0f]; a->fld_9 = maxVal[flags & 0x0f]; a->modWheelSensitivity = 31; - a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 31; + a->modWheelState = b->useModWheel ? _in->_modWheel >> 2 : 31; switch (b->type) { case 0: @@ -341,16 +344,18 @@ void TownsMidiOutputChannel::setModWheel(uint8 value) { void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) { if (!chan) return; - _midi = chan; - _next = chan->_outChan; + + _in = chan; + _next = chan->_out; _prev = 0; - chan->_outChan = this; + chan->_out = this; if (_next) _next->_prev = this; } void TownsMidiOutputChannel::disconnect() { keyOff(); + TownsMidiOutputChannel *p = _prev; TownsMidiOutputChannel *n = _next; @@ -359,19 +364,18 @@ void TownsMidiOutputChannel::disconnect() { if (p) p->_next = n; else - _midi->_outChan = n; - _midi = 0; + _in->_out = n; + _in = 0; } bool TownsMidiOutputChannel::update() { - if (!_midi) + if (!_in) return false; if (_duration) { _duration -= 17; if (_duration <= 0) { disconnect(); - //_duration = 0; return true; } } @@ -385,11 +389,11 @@ bool TownsMidiOutputChannel::update() { } int TownsMidiOutputChannel::checkPriority(int pri) { - if (!_midi) + if (!_in) return kDisconnected; - if (!_next && pri >= _midi->_priority) - return _midi->_priority; + if (!_next && pri >= _in->_priority) + return _in->_priority; return kHighPriority; } @@ -486,12 +490,11 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { retFlags |= 1; } - --a->fld_21;/*???*/ - if (a->fld_21 != 0) + if (--a->fld_21) return retFlags; if (++a->numLoop > 4) { - if (a->fld_11 == 0) { + if (!a->fld_11) { a->numLoop = 0; return retFlags; } @@ -506,7 +509,7 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { void TownsMidiOutputChannel::updateEffect(StateA *a) { uint8 c = a->numLoop - 1; - uint16 v = a->ar1[c]; + uint8 v = a->ar1[c]; int32 e = _effectData[_driver->_chanEffectLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]]; if (v & 0x80) @@ -665,7 +668,7 @@ const uint16 TownsMidiOutputChannel::_freqLSB[] = { 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B }; -TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _outChan(0), _prg(0), _chanIndex(chanIndex), +TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _out(0), _prg(0), _chanIndex(chanIndex), _effectLevel(0), _priority(0), _ctrlVolume(0), _tl(0), _pan(0), _panEff(0), _transpose(0), _percS(0), _pitchBendFactor(0), _pitchBend(0), _sustain(0), _freqLSB(0), _fld_1f(0), _detune(0), _modWheel(0), _allocated(false) { _instrument = new uint8[30]; @@ -692,16 +695,16 @@ void TownsMidiInputChannel::send(uint32 b) { } void TownsMidiInputChannel::noteOff(byte note) { - if (!_outChan) + if (!_out) return; - if (_outChan->_note != note) + if (_out->_note != note) return; if (_sustain) - _outChan->_sustainNoteOff = 1; + _out->_sustainNoteOff = 1; else - _outChan->disconnect(); + _out->disconnect(); } void TownsMidiInputChannel::noteOn(byte note, byte velocity) { @@ -712,7 +715,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { oc->connect(this); - oc->_fld_c = _instrument[10] & 1; + oc->_adjustModTl = _instrument[10] & 1; oc->_note = note; oc->_sustainNoteOff = 0; oc->_duration = _instrument[29] * 63; @@ -725,7 +728,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { if (oc->_carrierTl > 63) oc->_carrierTl = 63; - oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]); + oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]); oc->noteOn(note + _transpose, _freqLSB); if (_instrument[11] & 0x80) @@ -736,7 +739,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { if (_instrument[20] & 0x80) oc->setupEffects(1, _instrument[20], &_instrument[21]); else - oc->_stateA[1].numLoop = 0; + oc->_stateA[1].numLoop = 0; } void TownsMidiInputChannel::programChange(byte program) { @@ -746,8 +749,8 @@ void TownsMidiInputChannel::programChange(byte program) { void TownsMidiInputChannel::pitchBend(int16 bend) { _pitchBend = bend; _freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune; - for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) - oc->noteOnPitchBend(oc->_note + oc->_midi->_transpose, _freqLSB); + for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next) + oc->noteOnPitchBend(oc->_note + oc->_in->_transpose, _freqLSB); } void TownsMidiInputChannel::controlChange(byte control, byte value) { @@ -765,8 +768,8 @@ void TownsMidiInputChannel::controlChange(byte control, byte value) { controlSustain(value); break; case 123: - while (_outChan) - _outChan->disconnect(); + while (_out) + _out->disconnect(); break; default: break; @@ -776,8 +779,8 @@ void TownsMidiInputChannel::controlChange(byte control, byte value) { void TownsMidiInputChannel::pitchBendFactor(byte value) { _pitchBendFactor = value; _freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune; - for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) - oc->noteOnPitchBend(oc->_note + oc->_midi->_transpose, _freqLSB); + for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next) + oc->noteOnPitchBend(oc->_note + oc->_in->_transpose, _freqLSB); } void TownsMidiInputChannel::priority(byte value) { @@ -790,7 +793,7 @@ void TownsMidiInputChannel::sysEx_customInstrument(uint32 type, const byte *inst void TownsMidiInputChannel::controlModulationWheel(byte value) { _modWheel = value; - for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) + for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next) oc->setModWheel(value); } @@ -808,7 +811,7 @@ void TownsMidiInputChannel::controlVolume(byte value) { _tl = value; /* nullsub - _outChan->setVolume(_tl); + _out->setVolume(_tl); */ } @@ -823,7 +826,7 @@ void TownsMidiInputChannel::controlSustain(byte value) { } void TownsMidiInputChannel::releasePedal() { - for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) { + for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next) { if (oc->_sustainNoteOff) oc->disconnect(); } @@ -840,7 +843,7 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F }; -MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter1(0), _tickCounter2(0), _curChan(0), _rand(1), _open(false) { +MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _open(false) { _intf = new TownsAudioInterface(mixer, this); } @@ -883,6 +886,10 @@ int MidiDriver_TOWNS::open() { _intf->callback(33, 8); _intf->setSoundEffectChanMask(~0x3f); + _tickCounter1 = _tickCounter2 = 0; + _allocCurPos = 0; + _rand = 1; + _open = true; return 0; @@ -978,7 +985,7 @@ MidiChannel *MidiDriver_TOWNS::allocateChannel() { } MidiChannel *MidiDriver_TOWNS::getPercussionChannel() { - return 0;//_channels[16]; + return 0; } void MidiDriver_TOWNS::timerCallback(int timerId) { @@ -1018,20 +1025,20 @@ void MidiDriver_TOWNS::updateOutputChannels() { } } -TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) { +TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(uint8 pri) { TownsMidiOutputChannel *res = 0; for (int i = 0; i < 6; i++) { - if (++_curChan == 6) - _curChan = 0; + if (++_allocCurPos == 6) + _allocCurPos = 0; - int s = _out[i]->checkPriority(pri); + int s = _out[_allocCurPos]->checkPriority(pri); if (s == TownsMidiOutputChannel::kDisconnected) - return _out[i]; + return _out[_allocCurPos]; if (s != TownsMidiOutputChannel::kHighPriority) { pri = s; - res = _out[i]; + res = _out[_allocCurPos]; } } diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 5164e04708..8dc71f3528 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -58,7 +58,7 @@ private: void updateParser(); void updateOutputChannels(); - TownsMidiOutputChannel *allocateOutputChannel(int pri); + TownsMidiOutputChannel *allocateOutputChannel(uint8 pri); int randomValue(int para); @@ -73,7 +73,7 @@ private: uint32 _tickCounter1; uint32 _tickCounter2; - uint8 _curChan; + uint8 _allocCurPos; uint8 _rand; bool _open; -- cgit v1.2.3 From 95c059598d31ebdb871b97a528ad361472fcd217 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 8 May 2011 23:51:39 +0200 Subject: FM-TOWNS AUDIO: Fix note off event in midi driver --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 32 +++++++++++++---------------- 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 9fa6a8ceac..e22182632e 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -569,11 +569,7 @@ int TownsMidiOutputChannel::lookupVolume(int a, int b) { } void TownsMidiOutputChannel::keyOn() { - // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7), - // since it is just a modified AdLib driver. It also uses AdLib programs. - // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS - // music being so bad compared to AdLib (unsuitable data is just forced into the - // wrong audio device). + // This driver uses only 2 operators since it is just a modified AdLib driver. out(0x28, 0x30); } @@ -587,11 +583,7 @@ void TownsMidiOutputChannel::keyOnSetFreq(uint16 frq) { out(0xa4, frq >> 8); out(0xa0, frq & 0xff); out(0x28, 0); - // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7), - // since it is just a modified AdLib driver. It also uses AdLib programs. - // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS - // music being so bad compared to AdLib (unsuitable data is just forced into the - // wrong audio device). + // This driver uses only 2 operators since it is just a modified AdLib driver. out(0x28, 0x30); } @@ -698,13 +690,15 @@ void TownsMidiInputChannel::noteOff(byte note) { if (!_out) return; - if (_out->_note != note) - return; + for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next) { + if (oc->_note != note) + continue; - if (_sustain) - _out->_sustainNoteOff = 1; - else - _out->disconnect(); + if (_sustain) + oc->_sustainNoteOff = 1; + else + oc->disconnect(); + } } void TownsMidiInputChannel::noteOn(byte note, byte velocity) { @@ -743,7 +737,9 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { } void TownsMidiInputChannel::programChange(byte program) { - // Dysfunctional since this is all done inside the imuse code + // Not implemented (The loading and assignment of programs + // is handled externally by the SCUMM engine. The programs + // get sent via sysEx_customInstrument.) } void TownsMidiInputChannel::pitchBend(int16 bend) { @@ -816,7 +812,7 @@ void TownsMidiInputChannel::controlVolume(byte value) { } void TownsMidiInputChannel::controlPanPos(byte value) { - // not supported + // not implemented } void TownsMidiInputChannel::controlSustain(byte value) { -- cgit v1.2.3 From 15610b56db9f655ad0c8df0ffe730d123f048bac Mon Sep 17 00:00:00 2001 From: athrxx Date: Wed, 11 May 2011 00:41:32 +0200 Subject: FM-TOWNS AUDIO: Fix some bugs and rename some stuff in the midi driver code --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 343 ++++++++++----------- audio/softsynth/fmtowns_pc98/towns_midi.h | 2 +- .../softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 191 +++++++----- 3 files changed, 277 insertions(+), 259 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index e22182632e..6843a35ce3 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -51,40 +51,40 @@ public: int checkPriority(int pri); private: - struct StateA { - uint8 numLoop; - int32 fld_1; + struct EffectState { + uint8 envState; + int32 envStepLen; int32 duration; - uint16 fld_9; - int32 effectState; - uint8 fld_11; - uint8 ar1[4]; - uint8 ar2[4]; + int32 envTargetLevel; + int32 currentLevel; + uint8 loop; + uint8 envStepping[4]; + uint8 envMod[4]; int8 modWheelSensitivity; int8 modWheelState; int8 modWheelLast; - uint16 fld_1d; - uint32 fld_21; - int32 fld_25; + uint16 envStateNumSteps; + uint32 envStateStepCounter; + int32 envChangePerStep; int8 dir; - uint32 fld_2a; - uint32 fld_2e; - } *_stateA; + uint32 envChangePerStepRem; + uint32 envChangeCountRem; + } *_effectStates; - struct StateB { - int32 inc; + struct EffectDef { + int32 phase; uint8 type; uint8 useModWheel; - uint8 fld_6; - StateA *a; - } *_stateB; + uint8 loopRefresh; + EffectState *s; + } *_effectDefs; - int16 getEffectState(uint8 type); - void initEffect(StateA *a, const uint8 *effectData); - void updateEffectOuter3(StateA *a, StateB *b); - int updateEffectOuter(StateA *a, StateB *b); - void updateEffect(StateA *a); - int lookupVolume(int a, int b); + int16 getEffectLevel(uint8 type); + void initEffect(EffectState *s, const uint8 *effectData); + void updateEffectGenerator(EffectState *s, EffectDef *d); + int updateEffectEnvelope(EffectState *s, EffectDef *d); + void updateEffect(EffectState *s); + int calcModWheelLevel(int lvl, int mod); void keyOn(); void keyOff(); @@ -97,8 +97,8 @@ private: uint8 _adjustModTl; uint8 _chan; uint8 _note; - uint8 _carrierTl; - uint8 _modulatorTl; + uint8 _operator2Tl; + uint8 _operator1Tl; uint8 _sustainNoteOff; int16 _duration; @@ -109,8 +109,8 @@ private: static const uint8 _chanMap[]; static const uint8 _chanMap2[]; - static const uint8 _effectDefs[]; - static const uint16 _effectData[]; + static const uint8 _effectDefaults[]; + static const uint16 _effectEnvStepTable[]; static const uint8 _freqMSB[]; static const uint16 _freqLSB[]; }; @@ -215,18 +215,19 @@ uint8 TownsMidiChanState::get(uint8 type) { } TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex), - _in(0), _prev(0), _next(0), _adjustModTl(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) { - _stateA = new StateA[2]; - memset(_stateA, 0, 2 * sizeof(StateA)); - _stateB = new StateB[2]; - memset(_stateB, 0, 2 * sizeof(StateB)); - _stateB[0].a = &_stateA[1]; - _stateB[1].a = &_stateA[0]; + _in(0), _prev(0), _next(0), _adjustModTl(0), _operator2Tl(0), _note(0), _operator1Tl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) { + _effectStates = new EffectState[2]; + _effectDefs = new EffectDef[2]; + + memset(_effectStates, 0, 2 * sizeof(EffectState)); + memset(_effectDefs, 0, 2 * sizeof(EffectDef)); + _effectDefs[0].s = &_effectStates[1]; + _effectDefs[1].s = &_effectStates[0]; } TownsMidiOutputChannel::~TownsMidiOutputChannel() { - delete[] _stateA; - delete[] _stateB; + delete[] _effectStates; + delete[] _effectDefs; } void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) { @@ -243,9 +244,8 @@ void TownsMidiOutputChannel::noteOnPitchBend(uint8 msb, uint16 lsb) { void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, uint8 tLevelPara) { // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7), // since it is just a modified AdLib driver. It also uses AdLib programs. - // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS - // music being so bad compared to AdLib (unsuitable data is just forced into the - // wrong audio device). + // There are no FM-TOWNS specific programs. This is the reason for the low quality of the FM-TOWNS + // music (unsuitable data is just forced into the wrong audio device). static const uint8 mul[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 }; uint8 chan = _chanMap[_chan]; @@ -295,50 +295,50 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u } void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *effectData) { - uint16 maxVal[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F }; + uint16 effectTargetLevel[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F }; uint8 effectType[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 }; - StateA *a = &_stateA[index]; - StateB *b = &_stateB[index]; - - b->inc = 0; - b->useModWheel = flags & 0x40; - a->fld_11 = flags & 0x20; - b->fld_6 = flags & 0x10; - b->type = effectType[flags & 0x0f]; - a->fld_9 = maxVal[flags & 0x0f]; - a->modWheelSensitivity = 31; - a->modWheelState = b->useModWheel ? _in->_modWheel >> 2 : 31; - - switch (b->type) { + EffectState *s = &_effectStates[index]; + EffectDef *d = &_effectDefs[index]; + + d->phase = 0; + d->useModWheel = flags & 0x40; + s->loop = flags & 0x20; + d->loopRefresh = flags & 0x10; + d->type = effectType[flags & 0x0f]; + s->envTargetLevel = effectTargetLevel[flags & 0x0f]; + s->modWheelSensitivity = 31; + s->modWheelState = d->useModWheel ? _in->_modWheel >> 2 : 31; + + switch (d->type) { case 0: - a->effectState = _carrierTl; + s->currentLevel = _operator2Tl; break; case 13: - a->effectState = _modulatorTl; + s->currentLevel = _operator1Tl; break; case 30: - a->effectState = 31; - b->a->modWheelState = 0; + s->currentLevel = 31; + d->s->modWheelState = 0; break; case 31: - a->effectState = 0; - b->a->modWheelSensitivity = 0; + s->currentLevel = 0; + d->s->modWheelSensitivity = 0; break; default: - a->effectState = getEffectState(b->type); + s->currentLevel = getEffectLevel(d->type); break; } - initEffect(a, effectData); + initEffect(s, effectData); } void TownsMidiOutputChannel::setModWheel(uint8 value) { - if (_stateA[0].numLoop && _stateB[0].type) - _stateA[0].modWheelState = value >> 2; + if (_effectStates[0].envState && _effectDefs[0].type) + _effectStates[0].modWheelState = value >> 2; - if (_stateA[1].numLoop && _stateB[1].type) - _stateA[1].modWheelState = value >> 2; + if (_effectStates[1].envState && _effectDefs[1].type) + _effectStates[1].modWheelState = value >> 2; } void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) { @@ -381,8 +381,8 @@ bool TownsMidiOutputChannel::update() { } for (int i = 0; i < 2; i++) { - if (_stateA[i].numLoop) - updateEffectOuter3(&_stateA[i], &_stateB[i]); + if (_effectStates[i].envState) + updateEffectGenerator(&_effectStates[i], &_effectDefs[i]); } return false; @@ -398,7 +398,7 @@ int TownsMidiOutputChannel::checkPriority(int pri) { return kHighPriority; } -int16 TownsMidiOutputChannel::getEffectState(uint8 type) { +int16 TownsMidiOutputChannel::getEffectLevel(uint8 type) { uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan); if (type == 28) @@ -411,45 +411,45 @@ int16 TownsMidiOutputChannel::getEffectState(uint8 type) { type -= 13; int32 res = 0; - uint8 cs = (_driver->_chanState[chan].get(_effectDefs[type * 4] >> 5) & _effectDefs[type * 4 + 2]) >> _effectDefs[type * 4 + 1]; - if (_effectDefs[type * 4 + 3]) - res = _effectDefs[type * 4 + 3] - cs; + uint8 cs = (_driver->_chanState[chan].get(_effectDefaults[type * 4] >> 5) & _effectDefaults[type * 4 + 2]) >> _effectDefaults[type * 4 + 1]; + if (_effectDefaults[type * 4 + 3]) + res = _effectDefaults[type * 4 + 3] - cs; return res; } -void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) { - a->numLoop = 1; - a->fld_1 = 0; - a->modWheelLast = 31; - a->duration = effectData[0] * 63; - a->ar1[0] = effectData[1]; - a->ar1[1] = effectData[3]; - a->ar1[2] = effectData[5]; - a->ar1[3] = effectData[6]; - a->ar2[0] = effectData[2]; - a->ar2[1] = effectData[4]; - a->ar2[2] = 0; - a->ar2[3] = effectData[7]; - updateEffect(a); +void TownsMidiOutputChannel::initEffect(EffectState *s, const uint8 *effectData) { + s->envState = 1; + s->envStepLen = 0; + s->modWheelLast = 31; + s->duration = effectData[0] * 63; + s->envStepping[0] = effectData[1]; + s->envStepping[1] = effectData[3]; + s->envStepping[2] = effectData[5]; + s->envStepping[3] = effectData[6]; + s->envMod[0] = effectData[2]; + s->envMod[1] = effectData[4]; + s->envMod[2] = 0; + s->envMod[3] = effectData[7]; + updateEffect(s); } -void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) { - uint8 f = updateEffectOuter(a, b); +void TownsMidiOutputChannel::updateEffectGenerator(EffectState *s, EffectDef *d) { + uint8 f = updateEffectEnvelope(s, d); if (f & 1) { - switch (b->type) { + switch (d->type) { case 0: - _carrierTl = a->effectState + b->inc; /*???*/ + _operator2Tl = s->currentLevel + d->phase; break; case 13: - _modulatorTl = a->effectState + b->inc; /*???*/ + _operator1Tl = s->currentLevel + d->phase; break; case 30: - b->a->modWheelState = b->inc; + d->s->modWheelState = d->phase; break; case 31: - b->a->modWheelSensitivity = b->inc; + d->s->modWheelSensitivity = d->phase; break; default: break; @@ -457,60 +457,60 @@ void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) { } if (f & 2) { - if (b->fld_6) + if (d->loopRefresh) keyOn(); } } -int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) { - if (a->duration) { - a->duration -= 17; - if (a->duration <= 0) { - a->numLoop = 0; +int TownsMidiOutputChannel::updateEffectEnvelope(EffectState *s, EffectDef *d) { + if (s->duration) { + s->duration -= 17; + if (s->duration <= 0) { + s->envState = 0; return 0; } } - int32 t = a->fld_1 + a->fld_25; + int32 t = s->envStepLen + s->envChangePerStep; - a->fld_2e += a->fld_2a; - if (a->fld_2e >= a->fld_1d) { - a->fld_2e -= a->fld_1d; - t += a->dir; + s->envChangeCountRem += s->envChangePerStepRem; + if (s->envChangeCountRem >= s->envStateNumSteps) { + s->envChangeCountRem -= s->envStateNumSteps; + t += s->dir; } int retFlags = 0; - if (t != a->fld_1 || a->modWheelState != a->modWheelLast) { - a->fld_1 = t; - a->modWheelLast = a->modWheelState; - t = lookupVolume(t, a->modWheelState); - if (t != b->inc) - b->inc = t; + if (t != s->envStepLen || (s->modWheelState != s->modWheelLast)) { + s->envStepLen = t; + s->modWheelLast = s->modWheelState; + t = calcModWheelLevel(t, s->modWheelState); + if (t != d->phase) + d->phase = t; retFlags |= 1; } - if (--a->fld_21) + if (--s->envStateStepCounter) return retFlags; - if (++a->numLoop > 4) { - if (!a->fld_11) { - a->numLoop = 0; + if (++s->envState > 4) { + if (!s->loop) { + s->envState = 0; return retFlags; } - a->numLoop = 1; + s->envState = 1; retFlags |= 2; } - updateEffect(a); + updateEffect(s); return retFlags; } -void TownsMidiOutputChannel::updateEffect(StateA *a) { - uint8 c = a->numLoop - 1; - uint8 v = a->ar1[c]; - int32 e = _effectData[_driver->_chanEffectLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]]; +void TownsMidiOutputChannel::updateEffect(EffectState *s) { + uint8 st= s->envState - 1; + uint8 v = s->envStepping[st]; + int32 e = _effectEnvStepTable[_driver->_chanEffectLevelModifier[((v & 0x7f) << 5) + s->modWheelSensitivity]]; if (v & 0x80) e = _driver->randomValue(e); @@ -518,58 +518,59 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) { if (!e) e = 1; - a->fld_1d = a->fld_21 = e; + s->envStateNumSteps = s->envStateStepCounter = e; int32 d = 0; - if (c != 2) { - v = a->ar2[c]; - e = lookupVolume(a->fld_9, (v & 0x7f) - 31); + if (st != 2) { + v = s->envMod[st]; + e = calcModWheelLevel(s->envTargetLevel, (v & 0x7f) - 31); if (v & 0x80) e = _driver->randomValue(e); - if (e + a->effectState > a->fld_9) { - e = a->fld_9 - a->effectState; + if (e + s->currentLevel > s->envTargetLevel) { + e = s->envTargetLevel - s->currentLevel; } else { - if (e + a->effectState + 1 <= 0) - e = -a->effectState; + if (e + s->currentLevel + 1 <= 0) + e = -s->currentLevel; } - d = e - a->fld_1; + d = e - s->envStepLen; } - a->fld_25 = d / a->fld_1d; - a->dir = (d < 0) ? -1 : 1; - d *= a->dir; - a->fld_2a = d % a->fld_1d; - a->fld_2e = 0; + s->envChangePerStep = d / s->envStateNumSteps; + s->dir = (d < 0) ? -1 : 1; + d *= s->dir; + s->envChangePerStepRem = d % s->envStateNumSteps; + s->envChangeCountRem = 0; } -int TownsMidiOutputChannel::lookupVolume(int a, int b) { - if (b == 0) +int TownsMidiOutputChannel::calcModWheelLevel(int lvl, int mod) { + if (mod == 0) return 0; - if (b == 31) - return a; + if (mod == 31) + return lvl; - if (a > 63 || a < -63) - return ((a + 1) * b) >> 5; + if (lvl > 63 || lvl < -63) + return ((lvl + 1) * mod) >> 5; - if (b < 0) { - if (a < 0) - return _driver->_chanEffectLevel[((-a) << 5) - b]; + if (mod < 0) { + if (mod < 0) + return _driver->_chanEffectLevelModifier[((-lvl) << 5) - mod]; else - return -_driver->_chanEffectLevel[(a << 5) - b]; + return -_driver->_chanEffectLevelModifier[(lvl << 5) - mod]; } else { - if (a < 0) - return -_driver->_chanEffectLevel[((-a) << 5) + b]; + if (mod < 0) + return -_driver->_chanEffectLevelModifier[((-lvl) << 5) + mod]; else - return _driver->_chanEffectLevel[((-a) << 5) + b]; + return _driver->_chanEffectLevelModifier[((-lvl) << 5) + mod]; } + + return 0; } void TownsMidiOutputChannel::keyOn() { - // This driver uses only 2 operators since it is just a modified AdLib driver. out(0x28, 0x30); } @@ -578,12 +579,11 @@ void TownsMidiOutputChannel::keyOff() { } void TownsMidiOutputChannel::keyOnSetFreq(uint16 frq) { - uint8 t = (frq << 1) >> 8; - frq = (_freqMSB[t] << 11) | _freqLSB[t] ; + uint16 note = (frq << 1) >> 8; + frq = (_freqMSB[note] << 11) | _freqLSB[note] ; out(0xa4, frq >> 8); out(0xa0, frq & 0xff); - out(0x28, 0); - // This driver uses only 2 operators since it is just a modified AdLib driver. + //out(0x28, 0x00); out(0x28, 0x30); } @@ -607,7 +607,7 @@ const uint8 TownsMidiOutputChannel::_chanMap2[] = { 3, 4, 5, 11, 12, 13 }; -const uint8 TownsMidiOutputChannel::_effectDefs[] = { +const uint8 TownsMidiOutputChannel::_effectDefaults[] = { 0x40, 0x00, 0x3F, 0x3F, 0xE0, 0x02, 0x00, 0x00, 0x40, 0x06, 0xC0, 0x00, 0x20, 0x00, 0x0F, 0x00, 0x60, 0x04, 0xF0, 0x0F, 0x60, 0x00, 0x0F, 0x0F, 0x80, 0x04, 0xF0, 0x0F, 0x80, 0x00, 0x0F, 0x0F, 0xE0, 0x00, 0x03, 0x00, @@ -615,7 +615,7 @@ const uint8 TownsMidiOutputChannel::_effectDefs[] = { 0x20, 0x04, 0x10, 0x00, 0xC0, 0x00, 0x01, 0x00, 0xC0, 0x01, 0x0E, 0x00 }; -const uint16 TownsMidiOutputChannel::_effectData[] = { +const uint16 TownsMidiOutputChannel::_effectEnvStepTable[] = { 0x0001, 0x0002, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000C, 0x000E, 0x0010, 0x0012, 0x0015, 0x0018, 0x001E, 0x0024, 0x0032, 0x0040, 0x0052, 0x0064, 0x0088, 0x00A0, 0x00C0, @@ -714,26 +714,26 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { oc->_sustainNoteOff = 0; oc->_duration = _instrument[29] * 63; - oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanEffectLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; - if (oc->_modulatorTl > 63) - oc->_modulatorTl = 63; + oc->_operator1Tl = (_instrument[1] & 0x3f) + _driver->_chanEffectLevelModifier[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; + if (oc->_operator1Tl > 63) + oc->_operator1Tl = 63; - oc->_carrierTl = (_instrument[6] & 0x3f) + _driver->_chanEffectLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)]; - if (oc->_carrierTl > 63) - oc->_carrierTl = 63; + oc->_operator2Tl = (_instrument[6] & 0x3f) + _driver->_chanEffectLevelModifier[((velocity >> 1) << 5) + (_instrument[9] >> 2)]; + if (oc->_operator2Tl > 63) + oc->_operator2Tl = 63; - oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]); + oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_chanEffectLevelModifier[(_tl >> 2) + (oc->_operator1Tl << 5)]] : oc->_operator1Tl, _programAdjustLevel[_driver->_chanEffectLevelModifier[(_tl >> 2) + (oc->_operator2Tl << 5)]]); oc->noteOn(note + _transpose, _freqLSB); if (_instrument[11] & 0x80) oc->setupEffects(0, _instrument[11], &_instrument[12]); else - oc->_stateA[0].numLoop = 0; + oc->_effectStates[0].envState = 0; if (_instrument[20] & 0x80) oc->setupEffects(1, _instrument[20], &_instrument[21]); else - oc->_stateA[1].numLoop = 0; + oc->_effectStates[1].envState = 0; } void TownsMidiInputChannel::programChange(byte program) { @@ -795,7 +795,6 @@ void TownsMidiInputChannel::controlModulationWheel(byte value) { void TownsMidiInputChannel::controlVolume(byte value) { /* This is all done inside the imuse code - uint16 v1 = _ctrlVolume + 1; uint16 v2 = value; if (_chanIndex != 16) { @@ -805,10 +804,6 @@ void TownsMidiInputChannel::controlVolume(byte value) { _tl = (v1 * v2) >> 7;*/ _tl = value; - - /* nullsub - _out->setVolume(_tl); - */ } void TownsMidiInputChannel::controlPanPos(byte value) { @@ -865,13 +860,13 @@ int MidiDriver_TOWNS::open() { _chanState = new TownsMidiChanState[32]; - _chanEffectLevel = new uint8[2048]; + _chanEffectLevelModifier = new uint8[2048]; for (int i = 0; i < 64; i++) { for (int ii = 0; ii < 32; ii++) - _chanEffectLevel[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff; + _chanEffectLevelModifier[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff; } for (int i = 0; i < 64; i++) - _chanEffectLevel[i << 5] = 0; + _chanEffectLevelModifier[i << 5] = 0; _intf->callback(0); @@ -916,8 +911,8 @@ void MidiDriver_TOWNS::close() { delete[] _chanState; _chanState = 0; - delete[] _chanEffectLevel; - _chanEffectLevel = 0; + delete[] _chanEffectLevelModifier; + _chanEffectLevelModifier = 0; } void MidiDriver_TOWNS::send(uint32 b) { diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 8dc71f3528..52298d77ce 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -78,7 +78,7 @@ private: bool _open; - uint8 *_chanEffectLevel; + uint8 *_chanEffectLevelModifier; }; #endif diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index 263986ec0c..09d3ca3b8d 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -39,45 +39,22 @@ public: void recalculateRates(); void generateOutput(int32 phasebuf, int32 *feedbuf, int32 &out); - void feedbackLevel(int32 level) { - _feedbackLevel = level ? level + 6 : 0; - } - void detune(int value) { - _detn = &_detnTbl[value << 5]; - } - void multiple(uint32 value) { - _multiple = value ? (value << 1) : 1; - } - void attackRate(uint32 value) { - _specifiedAttackRate = value; - } + void feedbackLevel(int32 level); + void detune(int value); + void multiple(uint32 value); + void attackRate(uint32 value); bool scaleRate(uint8 value); - void decayRate(uint32 value) { - _specifiedDecayRate = value; - recalculateRates(); - } - void sustainRate(uint32 value) { - _specifiedSustainRate = value; - recalculateRates(); - } - void sustainLevel(uint32 value) { - _sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5; - } - void releaseRate(uint32 value) { - _specifiedReleaseRate = value; - recalculateRates(); - } - void totalLevel(uint32 value) { - _totalLevel = value << 3; - } - void ampModulation(bool enable) { - _ampMod = enable; - } + void decayRate(uint32 value); + void sustainRate(uint32 value); + void sustainLevel(uint32 value); + void releaseRate(uint32 value); + void totalLevel(uint32 value); + void ampModulation(bool enable); void reset(); protected: EnvelopeState _state; - bool _playing; + bool _holdKey; uint32 _feedbackLevel; uint32 _multiple; uint32 _totalLevel; @@ -122,7 +99,7 @@ TownsPC98_FmSynthOperator::TownsPC98_FmSynthOperator(const uint32 timerbase, con _rtt(rtt), _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable), _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(timerbase * 2), _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0), - _phase(0), _state(kEnvReady), _playing(false), _timer(0), _keyScale1(0), + _phase(0), _state(kEnvReady), _holdKey(false), _timer(0), _keyScale1(0), _keyScale2(0), _currentLevel(1023), _ampMod(false), _tickCount(0) { fs_a.rate = fs_a.shift = fs_d.rate = fs_d.shift = fs_s.rate = fs_s.shift = fs_r.rate = fs_r.shift = 0; @@ -131,19 +108,19 @@ TownsPC98_FmSynthOperator::TownsPC98_FmSynthOperator(const uint32 timerbase, con } void TownsPC98_FmSynthOperator::keyOn() { - if (_playing) + if (_holdKey) return; - _playing = true; + _holdKey = true; _state = kEnvAttacking; _phase = 0; } void TownsPC98_FmSynthOperator::keyOff() { - if (!_playing) + if (!_holdKey) return; - _playing = false; + _holdKey = false; if (_state != kEnvReady) _state = kEnvReleasing; } @@ -199,39 +176,42 @@ void TownsPC98_FmSynthOperator::generateOutput(int32 phasebuf, int32 *feed, int3 int32 targetLevel = 0; EnvelopeState nextState = kEnvReady; - switch (_state) { - case kEnvReady: - return; - case kEnvAttacking: - targetLevel = 0; - nextState = kEnvDecaying; - if ((_specifiedAttackRate << 1) + _keyScale2 < 64) { - targetTime = (1 << fs_a.shift) - 1; - levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4; + for (bool loop = true; loop;) { + switch (_state) { + case kEnvReady: + return; + case kEnvAttacking: + targetLevel = 0; + nextState = _sustainLevel ? kEnvDecaying : kEnvSustaining; + if ((_specifiedAttackRate << 1) + _keyScale2 < 62) { + targetTime = (1 << fs_a.shift) - 1; + levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4; + } else { + _currentLevel = targetLevel; + _state = nextState; + continue; + } + break; + case kEnvDecaying: + targetTime = (1 << fs_d.shift) - 1; + nextState = kEnvSustaining; + targetLevel = _sustainLevel; + levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)]; + break; + case kEnvSustaining: + targetTime = (1 << fs_s.shift) - 1; + nextState = kEnvSustaining; + targetLevel = 1023; + levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)]; + break; + case kEnvReleasing: + targetTime = (1 << fs_r.shift) - 1; + nextState = kEnvReady; + targetLevel = 1023; + levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)]; break; - } else { - _currentLevel = targetLevel; - _state = nextState; } - // Fall through - case kEnvDecaying: - targetTime = (1 << fs_d.shift) - 1; - nextState = kEnvSustaining; - targetLevel = _sustainLevel; - levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)]; - break; - case kEnvSustaining: - targetTime = (1 << fs_s.shift) - 1; - nextState = kEnvSustaining; - targetLevel = 1023; - levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)]; - break; - case kEnvReleasing: - targetTime = (1 << fs_r.shift) - 1; - nextState = kEnvReady; - targetLevel = 1023; - levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)]; - break; + loop = false; } if (!(_tickCount & targetTime)) { @@ -272,6 +252,63 @@ void TownsPC98_FmSynthOperator::generateOutput(int32 phasebuf, int32 *feed, int3 out += *o; } +void TownsPC98_FmSynthOperator::feedbackLevel(int32 level) { + _feedbackLevel = level ? level + 6 : 0; +} + +void TownsPC98_FmSynthOperator::detune(int value) { + _detn = &_detnTbl[value << 5]; +} + +void TownsPC98_FmSynthOperator::multiple(uint32 value) { + _multiple = value ? (value << 1) : 1; +} + +void TownsPC98_FmSynthOperator::attackRate(uint32 value) { + _specifiedAttackRate = value; +} + +bool TownsPC98_FmSynthOperator::scaleRate(uint8 value) { + value = 3 - value; + if (_keyScale1 != value) { + _keyScale1 = value; + return true; + } + + int k = _keyScale2; + int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0; + fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136; + fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0; + return false; +} + +void TownsPC98_FmSynthOperator::decayRate(uint32 value) { + _specifiedDecayRate = value; + recalculateRates(); +} + +void TownsPC98_FmSynthOperator::sustainRate(uint32 value) { + _specifiedSustainRate = value; + recalculateRates(); + } + +void TownsPC98_FmSynthOperator::sustainLevel(uint32 value) { + _sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5; +} + +void TownsPC98_FmSynthOperator::releaseRate(uint32 value) { + _specifiedReleaseRate = value; + recalculateRates(); +} + +void TownsPC98_FmSynthOperator::totalLevel(uint32 value) { + _totalLevel = value << 3; +} + +void TownsPC98_FmSynthOperator::ampModulation(bool enable) { + _ampMod = enable; +} + void TownsPC98_FmSynthOperator::reset() { keyOff(); _timer = 0; @@ -292,20 +329,6 @@ void TownsPC98_FmSynthOperator::reset() { ampModulation(false); } -bool TownsPC98_FmSynthOperator::scaleRate(uint8 value) { - value = 3 - value; - if (_keyScale1 != value) { - _keyScale1 = value; - return true; - } - - int k = _keyScale2; - int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0; - fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136; - fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0; - return false; -} - class TownsPC98_FmSynthSquareSineSource { public: TownsPC98_FmSynthSquareSineSource(const uint32 timerbase, const uint32 rtt); -- cgit v1.2.3 From b3476fc8016e3a62812eb9c7b5602e1f05f529cb Mon Sep 17 00:00:00 2001 From: athrxx Date: Sat, 14 May 2011 15:25:39 +0200 Subject: FM-TOWNS AUDIO: Some fixes and renaming - renamed some stuff in the new midi driver code - fixed minor bug in midi driver code - fixed minor bug in euphony driver code - add some functionality to towns audio interface --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 65 +++++- audio/softsynth/fmtowns_pc98/towns_euphony.cpp | 2 +- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 253 +++++++++++----------- audio/softsynth/fmtowns_pc98/towns_midi.h | 2 +- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 2 +- 5 files changed, 185 insertions(+), 139 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 6679e65cd2..f2d249b32a 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -163,9 +163,10 @@ private: int intf_fmReset(va_list &args); int intf_setOutputVolume(va_list &args); int intf_resetOutputVolume(va_list &args); + int intf_getOutputVolume(va_list &args); int intf_setOutputMute(va_list &args); int intf_cdaToggle(va_list &args); - int intf_getOutputVolume(va_list &args); + int intf_getOutputVolume2(va_list &args); int intf_getOutputMute(va_list &args); int intf_pcmUpdateEnvelopeGenerator(va_list &args); @@ -224,7 +225,7 @@ private: void updateOutputVolume(); uint8 _outputVolumeFlags; uint8 _outputLevel[16]; - uint8 _outputMuteFlags; + uint8 _outputMute[16]; const float _baserate; uint32 _timerBase; @@ -253,7 +254,7 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA _fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0), _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver), _pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume), - _outputVolumeFlags(0), _outputMuteFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0), + _outputVolumeFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0), _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _ready(false) { #define INTCB(x) &TownsAudioInterfaceIntern::intf_##x @@ -345,13 +346,13 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA INTCB(setOutputVolume), // 68 INTCB(resetOutputVolume), - INTCB(notImpl), + INTCB(getOutputVolume), INTCB(setOutputMute), INTCB(notImpl), // 72 INTCB(notImpl), INTCB(cdaToggle), - INTCB(getOutputVolume), + INTCB(getOutputVolume2), INTCB(getOutputMute), // 76 INTCB(notImpl), @@ -368,6 +369,7 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA memset(_fmSaveReg, 0, sizeof(_fmSaveReg)); memset(_outputLevel, 0, sizeof(_outputLevel)); + memset(_outputMute, 0, sizeof(_outputMute)); _timerBase = (uint32)(_baserate * 1000000.0f); _tickLength = 2 * _timerBase; @@ -929,11 +931,13 @@ int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) { if (chanType > 1) { _outputLevel[chan + chanType] = left; + _outputMute[chan + chanType] = 0; } else { if (chanType == 0) chan -= 8; _outputLevel[chan] = left; _outputLevel[chan + 1] = right; + _outputMute[chan] = _outputMute[chan + 1] = 0; } updateOutputVolume(); @@ -943,15 +947,56 @@ int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) { int TownsAudioInterfaceIntern::intf_resetOutputVolume(va_list &args) { memset(_outputLevel, 0, sizeof(_outputLevel)); - _outputMuteFlags = 0; _outputVolumeFlags = 0; updateOutputVolume(); return 0; } +int TownsAudioInterfaceIntern::intf_getOutputVolume(va_list &args) { + int chanType = va_arg(args, int); + int *left = va_arg(args, int*); + int *right = va_arg(args, int*); + + uint8 chan = (chanType & 0x40) ? 8 : 12; + chanType &= 3; + + if (chanType > 1) { + *left = _outputLevel[chan + chanType] & 0x3f; + } else { + if (chanType == 0) + chan -= 8; + *left = _outputLevel[chan] & 0x3f; + *right = _outputLevel[chan + 1] & 0x3f; + } + + return 0; +} + int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) { int flags = va_arg(args, int); - _outputMuteFlags = flags & 3; + _outputVolumeFlags = flags; + uint8 mute = flags & 3; + uint8 f = flags & 0xff; + + memset(_outputMute, 1, 8); + if (mute & 2) + memset(_outputMute + 12, 1, 4); + if (mute & 1) + memset(_outputMute + 8, 1, 4); + + _outputMute[(f < 0x80) ? 11 : 15] = 0; + f += f; + _outputMute[(f < 0x80) ? 10 : 14] = 0; + f += f; + _outputMute[(f < 0x80) ? 8 : 12] = 0; + f += f; + _outputMute[(f < 0x80) ? 9 : 13] = 0; + f += f; + _outputMute[(f < 0x80) ? 0 : 4] = 0; + f += f; + _outputMute[(f < 0x80) ? 1 : 5] = 0; + f += f; + updateOutputVolume(); return 0; } @@ -962,7 +1007,7 @@ int TownsAudioInterfaceIntern::intf_cdaToggle(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_getOutputVolume (va_list &args) { +int TownsAudioInterfaceIntern::intf_getOutputVolume2(va_list &args) { return 0; } @@ -1602,10 +1647,10 @@ void TownsAudioInterfaceIntern::updateOutputVolume() { // balance values for our -128 to 127 volume range // CD-AUDIO - uint32 maxVol = MAX(_outputLevel[12], _outputLevel[13]); + uint32 maxVol = MAX(_outputLevel[12] * (_outputMute[12] ^ 1), _outputLevel[13] * (_outputMute[13] ^ 1)); int volume = (int)(((float)(maxVol * 255) / 63.0f)); - int balance = maxVol ? (int)( ( ((int)_outputLevel[13] - _outputLevel[12]) * 127) / (float)maxVol) : 0; + int balance = maxVol ? (int)( ( ((int)_outputLevel[13] * (_outputMute[13] ^ 1) - _outputLevel[12] * (_outputMute[12] ^ 1)) * 127) / (float)maxVol) : 0; g_system->getAudioCDManager()->setVolume(volume); g_system->getAudioCDManager()->setBalance(balance); diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp index f161228876..f7aa33f44d 100644 --- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp @@ -81,7 +81,7 @@ void TownsEuphonyDriver::reset() { _intf->callback(0); _intf->callback(74); - _intf->callback(70); + _intf->callback(70, 0); _intf->callback(75, 3); setTimerA(true, 1); diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 6843a35ce3..6b31ea1aba 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -23,9 +23,12 @@ */ #include "audio/softsynth/fmtowns_pc98/towns_midi.h" +#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h" #include "common/textconsole.h" #include "common/system.h" +enum EnvelopeState; + class TownsMidiOutputChannel { friend class TownsMidiInputChannel; public: @@ -51,40 +54,40 @@ public: int checkPriority(int pri); private: - struct EffectState { - uint8 envState; - int32 envStepLen; - int32 duration; - int32 envTargetLevel; + struct EffectEnvelope { + uint8 state; int32 currentLevel; + int32 duration; + int32 maxLevel; + int32 startLevel; uint8 loop; - uint8 envStepping[4]; - uint8 envMod[4]; + uint8 stateTargetLevels[4]; + uint8 stateModWheelLevels[4]; int8 modWheelSensitivity; int8 modWheelState; int8 modWheelLast; - uint16 envStateNumSteps; - uint32 envStateStepCounter; - int32 envChangePerStep; + uint16 numSteps; + uint32 stepCounter; + int32 incrPerStep; int8 dir; - uint32 envChangePerStepRem; - uint32 envChangeCountRem; - } *_effectStates; + uint32 incrPerStepRem; + uint32 incrCountRem; + } *_effectEnvelopes; struct EffectDef { int32 phase; uint8 type; uint8 useModWheel; uint8 loopRefresh; - EffectState *s; + EffectEnvelope *s; } *_effectDefs; - int16 getEffectLevel(uint8 type); - void initEffect(EffectState *s, const uint8 *effectData); - void updateEffectGenerator(EffectState *s, EffectDef *d); - int updateEffectEnvelope(EffectState *s, EffectDef *d); - void updateEffect(EffectState *s); - int calcModWheelLevel(int lvl, int mod); + void startEffect(EffectEnvelope *s, const uint8 *effectData); + void updateEffectGenerator(EffectEnvelope *s, EffectDef *d); + int advanceEffectEnvelope(EffectEnvelope *s, EffectDef *d); + void initNextEnvelopeState(EffectEnvelope *s); + int16 getEffectStartLevel(uint8 type); + int getEffectModLevel(int lvl, int mod); void keyOn(); void keyOff(); @@ -216,17 +219,17 @@ uint8 TownsMidiChanState::get(uint8 type) { TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex), _in(0), _prev(0), _next(0), _adjustModTl(0), _operator2Tl(0), _note(0), _operator1Tl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) { - _effectStates = new EffectState[2]; + _effectEnvelopes = new EffectEnvelope[2]; _effectDefs = new EffectDef[2]; - memset(_effectStates, 0, 2 * sizeof(EffectState)); + memset(_effectEnvelopes, 0, 2 * sizeof(EffectEnvelope)); memset(_effectDefs, 0, 2 * sizeof(EffectDef)); - _effectDefs[0].s = &_effectStates[1]; - _effectDefs[1].s = &_effectStates[0]; + _effectDefs[0].s = &_effectEnvelopes[1]; + _effectDefs[1].s = &_effectEnvelopes[0]; } TownsMidiOutputChannel::~TownsMidiOutputChannel() { - delete[] _effectStates; + delete[] _effectEnvelopes; delete[] _effectDefs; } @@ -295,10 +298,10 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u } void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *effectData) { - uint16 effectTargetLevel[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F }; + uint16 effectMaxLevel[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F }; uint8 effectType[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 }; - EffectState *s = &_effectStates[index]; + EffectEnvelope *s = &_effectEnvelopes[index]; EffectDef *d = &_effectDefs[index]; d->phase = 0; @@ -306,39 +309,39 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *e s->loop = flags & 0x20; d->loopRefresh = flags & 0x10; d->type = effectType[flags & 0x0f]; - s->envTargetLevel = effectTargetLevel[flags & 0x0f]; + s->maxLevel = effectMaxLevel[flags & 0x0f]; s->modWheelSensitivity = 31; s->modWheelState = d->useModWheel ? _in->_modWheel >> 2 : 31; switch (d->type) { case 0: - s->currentLevel = _operator2Tl; + s->startLevel = _operator2Tl; break; case 13: - s->currentLevel = _operator1Tl; + s->startLevel = _operator1Tl; break; case 30: - s->currentLevel = 31; + s->startLevel = 31; d->s->modWheelState = 0; break; case 31: - s->currentLevel = 0; + s->startLevel = 0; d->s->modWheelSensitivity = 0; break; default: - s->currentLevel = getEffectLevel(d->type); + s->startLevel = getEffectStartLevel(d->type); break; } - initEffect(s, effectData); + startEffect(s, effectData); } void TownsMidiOutputChannel::setModWheel(uint8 value) { - if (_effectStates[0].envState && _effectDefs[0].type) - _effectStates[0].modWheelState = value >> 2; + if (_effectEnvelopes[0].state != kEnvReady && _effectDefs[0].type) + _effectEnvelopes[0].modWheelState = value >> 2; - if (_effectStates[1].envState && _effectDefs[1].type) - _effectStates[1].modWheelState = value >> 2; + if (_effectEnvelopes[1].state != kEnvReady && _effectDefs[1].type) + _effectEnvelopes[1].modWheelState = value >> 2; } void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) { @@ -381,8 +384,8 @@ bool TownsMidiOutputChannel::update() { } for (int i = 0; i < 2; i++) { - if (_effectStates[i].envState) - updateEffectGenerator(&_effectStates[i], &_effectDefs[i]); + if (_effectEnvelopes[i].state != kEnvReady) + updateEffectGenerator(&_effectEnvelopes[i], &_effectDefs[i]); } return false; @@ -398,52 +401,32 @@ int TownsMidiOutputChannel::checkPriority(int pri) { return kHighPriority; } -int16 TownsMidiOutputChannel::getEffectLevel(uint8 type) { - uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan); - - if (type == 28) - return 15; - else if (type == 29) - return 383; - else if (type > 29) - return 0; - else if (type > 12) - type -= 13; - - int32 res = 0; - uint8 cs = (_driver->_chanState[chan].get(_effectDefaults[type * 4] >> 5) & _effectDefaults[type * 4 + 2]) >> _effectDefaults[type * 4 + 1]; - if (_effectDefaults[type * 4 + 3]) - res = _effectDefaults[type * 4 + 3] - cs; - - return res; -} - -void TownsMidiOutputChannel::initEffect(EffectState *s, const uint8 *effectData) { - s->envState = 1; - s->envStepLen = 0; +void TownsMidiOutputChannel::startEffect(EffectEnvelope *s, const uint8 *effectData) { + s->state = kEnvAttacking; + s->currentLevel = 0; s->modWheelLast = 31; s->duration = effectData[0] * 63; - s->envStepping[0] = effectData[1]; - s->envStepping[1] = effectData[3]; - s->envStepping[2] = effectData[5]; - s->envStepping[3] = effectData[6]; - s->envMod[0] = effectData[2]; - s->envMod[1] = effectData[4]; - s->envMod[2] = 0; - s->envMod[3] = effectData[7]; - updateEffect(s); + s->stateTargetLevels[0] = effectData[1]; + s->stateTargetLevels[1] = effectData[3]; + s->stateTargetLevels[2] = effectData[5]; + s->stateTargetLevels[3] = effectData[6]; + s->stateModWheelLevels[0] = effectData[2]; + s->stateModWheelLevels[1] = effectData[4]; + s->stateModWheelLevels[2] = 0; + s->stateModWheelLevels[3] = effectData[7]; + initNextEnvelopeState(s); } -void TownsMidiOutputChannel::updateEffectGenerator(EffectState *s, EffectDef *d) { - uint8 f = updateEffectEnvelope(s, d); +void TownsMidiOutputChannel::updateEffectGenerator(EffectEnvelope *s, EffectDef *d) { + uint8 f = advanceEffectEnvelope(s, d); if (f & 1) { switch (d->type) { case 0: - _operator2Tl = s->currentLevel + d->phase; + _operator2Tl = s->startLevel + d->phase; break; case 13: - _operator1Tl = s->currentLevel + d->phase; + _operator1Tl = s->startLevel + d->phase; break; case 30: d->s->modWheelState = d->phase; @@ -462,55 +445,54 @@ void TownsMidiOutputChannel::updateEffectGenerator(EffectState *s, EffectDef *d) } } -int TownsMidiOutputChannel::updateEffectEnvelope(EffectState *s, EffectDef *d) { +int TownsMidiOutputChannel::advanceEffectEnvelope(EffectEnvelope *s, EffectDef *d) { if (s->duration) { s->duration -= 17; if (s->duration <= 0) { - s->envState = 0; + s->state = kEnvReady; return 0; } } - int32 t = s->envStepLen + s->envChangePerStep; + int32 t = s->currentLevel + s->incrPerStep; - s->envChangeCountRem += s->envChangePerStepRem; - if (s->envChangeCountRem >= s->envStateNumSteps) { - s->envChangeCountRem -= s->envStateNumSteps; + s->incrCountRem += s->incrPerStepRem; + if (s->incrCountRem >= s->numSteps) { + s->incrCountRem -= s->numSteps; t += s->dir; } int retFlags = 0; - if (t != s->envStepLen || (s->modWheelState != s->modWheelLast)) { - s->envStepLen = t; + if (t != s->currentLevel || (s->modWheelState != s->modWheelLast)) { + s->currentLevel = t; s->modWheelLast = s->modWheelState; - t = calcModWheelLevel(t, s->modWheelState); + t = getEffectModLevel(t, s->modWheelState); if (t != d->phase) d->phase = t; retFlags |= 1; } - if (--s->envStateStepCounter) + if (--s->stepCounter) return retFlags; - if (++s->envState > 4) { + if (++s->state > kEnvReleasing) { if (!s->loop) { - s->envState = 0; + s->state = kEnvReady; return retFlags; } - s->envState = 1; + s->state = kEnvAttacking; retFlags |= 2; } - updateEffect(s); + initNextEnvelopeState(s); return retFlags; } -void TownsMidiOutputChannel::updateEffect(EffectState *s) { - uint8 st= s->envState - 1; - uint8 v = s->envStepping[st]; - int32 e = _effectEnvStepTable[_driver->_chanEffectLevelModifier[((v & 0x7f) << 5) + s->modWheelSensitivity]]; +void TownsMidiOutputChannel::initNextEnvelopeState(EffectEnvelope *s) { + uint8 v = s->stateTargetLevels[s->state - 1]; + int32 e = _effectEnvStepTable[_driver->_operatorLevelTable[((v & 0x7f) << 5) + s->modWheelSensitivity]]; if (v & 0x80) e = _driver->randomValue(e); @@ -518,34 +500,54 @@ void TownsMidiOutputChannel::updateEffect(EffectState *s) { if (!e) e = 1; - s->envStateNumSteps = s->envStateStepCounter = e; + s->numSteps = s->stepCounter = e; int32 d = 0; - if (st != 2) { - v = s->envMod[st]; - e = calcModWheelLevel(s->envTargetLevel, (v & 0x7f) - 31); + if (s->state != kEnvSustaining) { + v = s->stateModWheelLevels[s->state - 1]; + e = getEffectModLevel(s->maxLevel, (v & 0x7f) - 31); if (v & 0x80) e = _driver->randomValue(e); - if (e + s->currentLevel > s->envTargetLevel) { - e = s->envTargetLevel - s->currentLevel; + if (e + s->startLevel > s->maxLevel) { + e = s->maxLevel - s->startLevel; } else { - if (e + s->currentLevel + 1 <= 0) - e = -s->currentLevel; + if (e + s->startLevel < 0) + e = -s->startLevel; } - d = e - s->envStepLen; + d = e - s->currentLevel; } - s->envChangePerStep = d / s->envStateNumSteps; + s->incrPerStep = d / s->numSteps; s->dir = (d < 0) ? -1 : 1; d *= s->dir; - s->envChangePerStepRem = d % s->envStateNumSteps; - s->envChangeCountRem = 0; + s->incrPerStepRem = d % s->numSteps; + s->incrCountRem = 0; +} + +int16 TownsMidiOutputChannel::getEffectStartLevel(uint8 type) { + uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan); + + if (type == 28) + return 15; + else if (type == 29) + return 383; + else if (type > 29) + return 0; + else if (type > 12) + type -= 13; + + const uint8 *def = &_effectDefaults[type << 2]; + uint8 res = (_driver->_chanState[chan].get(def[0] >> 5) & def[2]) >> def[1]; + if (def[3]) + res = def[3] - res; + + return res; } -int TownsMidiOutputChannel::calcModWheelLevel(int lvl, int mod) { +int TownsMidiOutputChannel::getEffectModLevel(int lvl, int mod) { if (mod == 0) return 0; @@ -556,15 +558,15 @@ int TownsMidiOutputChannel::calcModWheelLevel(int lvl, int mod) { return ((lvl + 1) * mod) >> 5; if (mod < 0) { - if (mod < 0) - return _driver->_chanEffectLevelModifier[((-lvl) << 5) - mod]; + if (lvl < 0) + return _driver->_operatorLevelTable[((-lvl) << 5) - mod]; else - return -_driver->_chanEffectLevelModifier[(lvl << 5) - mod]; + return -_driver->_operatorLevelTable[(lvl << 5) - mod]; } else { - if (mod < 0) - return -_driver->_chanEffectLevelModifier[((-lvl) << 5) + mod]; + if (lvl < 0) + return -_driver->_operatorLevelTable[((-lvl) << 5) + mod]; else - return _driver->_chanEffectLevelModifier[((-lvl) << 5) + mod]; + return _driver->_operatorLevelTable[((-lvl) << 5) + mod]; } return 0; @@ -714,26 +716,26 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) { oc->_sustainNoteOff = 0; oc->_duration = _instrument[29] * 63; - oc->_operator1Tl = (_instrument[1] & 0x3f) + _driver->_chanEffectLevelModifier[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; + oc->_operator1Tl = (_instrument[1] & 0x3f) + _driver->_operatorLevelTable[((velocity >> 1) << 5) + (_instrument[4] >> 2)]; if (oc->_operator1Tl > 63) oc->_operator1Tl = 63; - oc->_operator2Tl = (_instrument[6] & 0x3f) + _driver->_chanEffectLevelModifier[((velocity >> 1) << 5) + (_instrument[9] >> 2)]; + oc->_operator2Tl = (_instrument[6] & 0x3f) + _driver->_operatorLevelTable[((velocity >> 1) << 5) + (_instrument[9] >> 2)]; if (oc->_operator2Tl > 63) oc->_operator2Tl = 63; - oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_chanEffectLevelModifier[(_tl >> 2) + (oc->_operator1Tl << 5)]] : oc->_operator1Tl, _programAdjustLevel[_driver->_chanEffectLevelModifier[(_tl >> 2) + (oc->_operator2Tl << 5)]]); + oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_operatorLevelTable[(_tl >> 2) + (oc->_operator1Tl << 5)]] : oc->_operator1Tl, _programAdjustLevel[_driver->_operatorLevelTable[(_tl >> 2) + (oc->_operator2Tl << 5)]]); oc->noteOn(note + _transpose, _freqLSB); if (_instrument[11] & 0x80) oc->setupEffects(0, _instrument[11], &_instrument[12]); else - oc->_effectStates[0].envState = 0; + oc->_effectEnvelopes[0].state = kEnvReady; if (_instrument[20] & 0x80) oc->setupEffects(1, _instrument[20], &_instrument[21]); else - oc->_effectStates[1].envState = 0; + oc->_effectEnvelopes[1].state = kEnvReady; } void TownsMidiInputChannel::programChange(byte program) { @@ -852,7 +854,7 @@ int MidiDriver_TOWNS::open() { _channels = new TownsMidiInputChannel*[32]; for (int i = 0; i < 32; i++) - _channels[i] = new TownsMidiInputChannel(this, i); + _channels[i] = new TownsMidiInputChannel(this, i > 8 ? (i + 1) : i); _out = new TownsMidiOutputChannel*[6]; for (int i = 0; i < 6; i++) @@ -860,13 +862,13 @@ int MidiDriver_TOWNS::open() { _chanState = new TownsMidiChanState[32]; - _chanEffectLevelModifier = new uint8[2048]; + _operatorLevelTable = new uint8[2048]; for (int i = 0; i < 64; i++) { for (int ii = 0; ii < 32; ii++) - _chanEffectLevelModifier[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff; + _operatorLevelTable[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff; } for (int i = 0; i < 64; i++) - _chanEffectLevelModifier[i << 5] = 0; + _operatorLevelTable[i << 5] = 0; _intf->callback(0); @@ -911,8 +913,8 @@ void MidiDriver_TOWNS::close() { delete[] _chanState; _chanState = 0; - delete[] _chanEffectLevelModifier; - _chanEffectLevelModifier = 0; + delete[] _operatorLevelTable; + _operatorLevelTable = 0; } void MidiDriver_TOWNS::send(uint32 b) { @@ -1009,8 +1011,7 @@ void MidiDriver_TOWNS::updateOutputChannels() { while (_tickCounter2 >= 16667) { _tickCounter2 -= 16667; for (int i = 0; i < 6; i++) { - TownsMidiOutputChannel *oc = _out[i]; - if (oc->update()) + if (_out[i]->update()) return; } } diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 52298d77ce..2b6e1dff4e 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -78,7 +78,7 @@ private: bool _open; - uint8 *_chanEffectLevelModifier; + uint8 *_operatorLevelTable; }; #endif diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index cbf856c78c..f7bcc90585 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -44,7 +44,7 @@ class TownsPC98_FmSynthPercussionSource; #endif enum EnvelopeState { - kEnvReady, + kEnvReady = 0, kEnvAttacking, kEnvDecaying, kEnvSustaining, -- cgit v1.2.3 From d3e92f0b8105638b8fae45822006aa33bb8ed35a Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 15 May 2011 23:08:27 +0200 Subject: FM-TOWNS AUDIO: Fix several CppCheck warnings --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 12 +++++++++--- audio/softsynth/fmtowns_pc98/towns_euphony.cpp | 3 ++- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 5 +++-- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 11 ++++++----- 4 files changed, 20 insertions(+), 11 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index f2d249b32a..dd9bf61e48 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -255,7 +255,8 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver), _pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume), _outputVolumeFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0), - _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _ready(false) { + _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _fmChanPlaying(0), + _numReservedChannels(0), _numWaveTables(0), _ready(false) { #define INTCB(x) &TownsAudioInterfaceIntern::intf_##x static const TownsAudioIntfCallback intfCb[] = { @@ -368,6 +369,11 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA _intfOpcodes = intfCb; memset(_fmSaveReg, 0, sizeof(_fmSaveReg)); + memset(_fmChanNote, 0, sizeof(_fmChanNote)); + memset(_fmChanPitch, 0, sizeof(_fmChanPitch)); + memset(_pcmChanNote, 0, sizeof(_pcmChanNote)); + memset(_pcmChanVelo, 0, sizeof(_pcmChanVelo)); + memset(_pcmChanLevel, 0, sizeof(_pcmChanLevel)); memset(_outputLevel, 0, sizeof(_outputLevel)); memset(_outputMute, 0, sizeof(_outputMute)); @@ -980,9 +986,9 @@ int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) { memset(_outputMute, 1, 8); if (mute & 2) - memset(_outputMute + 12, 1, 4); + memset(&_outputMute[12], 1, 4); if (mute & 1) - memset(_outputMute + 8, 1, 4); + memset(&_outputMute[8], 1, 4); _outputMute[(f < 0x80) ? 11 : 15] = 0; f += f; diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp index f7aa33f44d..bc2c88b236 100644 --- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp @@ -28,7 +28,8 @@ TownsEuphonyDriver::TownsEuphonyDriver(Audio::Mixer *mixer) : _activeChannels(0), _sustainChannels(0), _assignedChannels(0), _paraCount(0), _command(0), _tEnable(0), _tMode(0), _tOrdr(0), _tLevel(0), _tTranspose(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0), - _tempoControlMode(0) { + _tempoControlMode(0), _timerSetting(0), _tempoDiff(0), _timeStampBase(0), _elapsedEvents(0), _loop(false), + _endOfTrack(false), _suspendParsing(false), _musicTrackSize(0) { _para[0] = _para[1] = 0; _intf = new TownsAudioInterface(mixer, this); resetTempo(); diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 6b31ea1aba..0743409af9 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -670,7 +670,7 @@ TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanI } TownsMidiInputChannel::~TownsMidiInputChannel() { - delete _instrument; + delete[] _instrument; } bool TownsMidiInputChannel::allocate() { @@ -836,7 +836,8 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F }; -MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _open(false) { +MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _channels(0), _out(0), + _chanState(0), _operatorLevelTable(0), _tickCounter1(0), _tickCounter2(0), _rand(1), _allocCurPos(0), _open(false) { _intf = new TownsAudioInterface(mixer, this); } diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index 09d3ca3b8d..46ac7e5c14 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -99,7 +99,7 @@ TownsPC98_FmSynthOperator::TownsPC98_FmSynthOperator(const uint32 timerbase, con _rtt(rtt), _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable), _sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(timerbase * 2), _specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0), - _phase(0), _state(kEnvReady), _holdKey(false), _timer(0), _keyScale1(0), + _sustainLevel(0), _phase(0), _state(kEnvReady), _holdKey(false), _timer(0), _keyScale1(0), _keyScale2(0), _currentLevel(1023), _ampMod(false), _tickCount(0) { fs_a.rate = fs_a.shift = fs_d.rate = fs_d.shift = fs_s.rate = fs_s.shift = fs_r.rate = fs_r.shift = 0; @@ -653,7 +653,8 @@ void TownsPC98_FmSynthSquareSineSource::updateRegs() { #ifndef DISABLE_PC98_RHYTHM_CHANNEL TownsPC98_FmSynthPercussionSource::TownsPC98_FmSynthPercussionSource(const uint32 timerbase, const uint32 rtt) : - _rtt(rtt), _tickLength(timerbase * 2), _timer(0), _ready(false), _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) { + _rtt(rtt), _tickLength(timerbase * 2), _timer(0), _totalLevel(0), _volMaskA(0), _volMaskB(0), + _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume), _ready(false) { memset(_rhChan, 0, sizeof(RhtChannel) * 6); _reg = new uint8 *[40]; @@ -1256,7 +1257,7 @@ void TownsPC98_FmSynth::generateTables() { WRITE_BE_UINT32(_oprRates + 32, _numChan == 6 ? 0x90900000 : 0x00081018); WRITE_BE_UINT32(_oprRates + 36, _numChan == 6 ? 0x00001010 : 0x00081018); memset(_oprRates, 0x90, 32); - memset(_oprRates + 96, 0x80, 32); + memset(&_oprRates[96], 0x80, 32); uint8 *dst = (uint8 *)_oprRates + 40; for (int i = 0; i < 40; i += 4) WRITE_BE_UINT32(dst + i, 0x00081018); @@ -1313,8 +1314,8 @@ void TownsPC98_FmSynth::generateTables() { uint8 *dtt = new uint8[128]; memset(dtt, 0, 36); - memset(dtt + 36, 1, 8); - memcpy(dtt + 44, _detSrc, 84); + memset(&dtt[36], 1, 8); + memcpy(&dtt[44], _detSrc, 84); delete[] _oprDetune; _oprDetune = new int32[256]; -- cgit v1.2.3 From 726a7f3b1aee4abd7c1fe198cbd317664685e21f Mon Sep 17 00:00:00 2001 From: athrxx Date: Mon, 16 May 2011 21:56:14 +0200 Subject: FM-TOWNS AUDIO: Fix GCC warnings --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 2 -- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 0743409af9..e66d6bed21 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -18,8 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL: $ - * $Id: $ */ #include "audio/softsynth/fmtowns_pc98/towns_midi.h" diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index 46ac7e5c14..bc5aa32823 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -928,7 +928,7 @@ bool TownsPC98_FmSynth::init() { } void TownsPC98_FmSynth::reset() { - Common::StackLock lock(_mutex); + lock(); for (int i = 0; i < _numChan; i++) { for (int ii = 0; ii < 4; ii++) _chanInternal[i].opr[ii]->reset(); @@ -948,6 +948,7 @@ void TownsPC98_FmSynth::reset() { if (_prc) _prc->reset(); #endif + unlock(); } void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) { -- cgit v1.2.3 From d2d002bcc2b830176d29459df7045d4ceb00a7bd Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 17 May 2011 21:24:00 +0200 Subject: AUDIO: Fix warning --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index dd9bf61e48..719bc981ee 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -1873,4 +1873,4 @@ void TownsAudioInterface::setSoundEffectVolume(int volume) { void TownsAudioInterface::setSoundEffectChanMask(int mask) { _intf->setSoundEffectChanMask(mask); -} \ No newline at end of file +} -- cgit v1.2.3 From 7804afd4cb2cbc6c5d291e781029005e304425bf Mon Sep 17 00:00:00 2001 From: athrxx Date: Tue, 17 May 2011 21:43:07 +0200 Subject: FM-TOWNS AUDIO: hopefully fix ps2 port compile --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 16 ++++++++-------- audio/softsynth/fmtowns_pc98/towns_midi.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index e66d6bed21..e67a78e9dc 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -835,7 +835,7 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { }; MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _channels(0), _out(0), - _chanState(0), _operatorLevelTable(0), _tickCounter1(0), _tickCounter2(0), _rand(1), _allocCurPos(0), _open(false) { + _chanState(0), _operatorLevelTable(0), _tickCounter1(0), _tickCounter2(0), _rand(1), _allocCurPos(0), _isOpen(false) { _intf = new TownsAudioInterface(mixer, this); } @@ -845,7 +845,7 @@ MidiDriver_TOWNS::~MidiDriver_TOWNS() { } int MidiDriver_TOWNS::open() { - if (_open) + if (_isOpen) return MERR_ALREADY_OPEN; if (!_intf->init()) @@ -882,16 +882,16 @@ int MidiDriver_TOWNS::open() { _allocCurPos = 0; _rand = 1; - _open = true; + _isOpen = true; return 0; } void MidiDriver_TOWNS::close() { - if (!_open) + if (!_isOpen) return; - _open = false; + _isOpen = false; setTimerCallback(0, 0); g_system->delayMillis(20); @@ -917,7 +917,7 @@ void MidiDriver_TOWNS::close() { } void MidiDriver_TOWNS::send(uint32 b) { - if (!_open) + if (!_isOpen) return; byte param2 = (b >> 16) & 0xFF; @@ -964,7 +964,7 @@ uint32 MidiDriver_TOWNS::getBaseTempo() { } MidiChannel *MidiDriver_TOWNS::allocateChannel() { - if (!_open) + if (!_isOpen) return 0; for (int i = 0; i < 32; ++i) { @@ -981,7 +981,7 @@ MidiChannel *MidiDriver_TOWNS::getPercussionChannel() { } void MidiDriver_TOWNS::timerCallback(int timerId) { - if (!_open) + if (!_isOpen) return; switch (timerId) { diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 2b6e1dff4e..20e986fd5c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -41,7 +41,7 @@ public: ~MidiDriver_TOWNS(); int open(); - bool isOpen() const { return _open; } + bool isOpen() const { return _isOpen; } void close(); void send(uint32 b); @@ -76,7 +76,7 @@ private: uint8 _allocCurPos; uint8 _rand; - bool _open; + bool _isOpen; uint8 *_operatorLevelTable; }; -- cgit v1.2.3 From 582827df40ed4a86a067c26dface4d51929d391a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 17 May 2011 23:23:44 +0200 Subject: AUDIO: Remove SVN Id/URL keywords from a few newly added files. --- audio/softsynth/fmtowns_pc98/towns_midi.h | 2 -- audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp | 2 -- 2 files changed, 4 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h index 20e986fd5c..a98bb1b59c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.h +++ b/audio/softsynth/fmtowns_pc98/towns_midi.h @@ -18,8 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL: $ - * $Id: $ */ #ifndef TOWNS_MIDI_H diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp index 3b46aca14d..194bfc41f9 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp @@ -18,8 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL: $ - * $Id: $ */ #include "audio/softsynth/fmtowns_pc98/towns_midi.h" -- cgit v1.2.3 From ffc2a93daa8d0dd4fed97427ae7f00e4194b26c4 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 20 May 2011 19:30:22 +0200 Subject: AUDIO: Remove leftover "forward" declaration after real declaration in the TOWNS midi code. --- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index e67a78e9dc..3c7ce7d0e4 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -25,8 +25,6 @@ #include "common/textconsole.h" #include "common/system.h" -enum EnvelopeState; - class TownsMidiOutputChannel { friend class TownsMidiInputChannel; public: -- cgit v1.2.3 From 2d1fa6c3f8bdc635d49978ad48f72619707d6893 Mon Sep 17 00:00:00 2001 From: athrxx Date: Fri, 20 May 2011 16:06:14 +0200 Subject: FM-TOWNS AUDIO: fix thread lockups and cleanup - fixed lockup situation in imuse destructor (only concerning the fm-towns driver) - fixed lockup situation when AudioCDManager functions get called (in both cases both the main thread and the mixer thread would get locked in different mutex belonging to the other thread) --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 228 +++++++++++---------- audio/softsynth/fmtowns_pc98/towns_audio.h | 11 +- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 68 +++--- audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp | 104 ++++++---- audio/softsynth/fmtowns_pc98/towns_pc98_driver.h | 34 +-- .../softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 60 +++--- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 23 +-- 7 files changed, 284 insertions(+), 244 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 719bc981ee..635f9354cc 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -30,7 +30,7 @@ class TownsAudio_PcmChannel { -friend class TownsAudioInterfaceIntern; +friend class TownsAudioInterfaceInternal; public: TownsAudio_PcmChannel(); ~TownsAudio_PcmChannel(); @@ -80,7 +80,7 @@ private: }; class TownsAudio_WaveTable { -friend class TownsAudioInterfaceIntern; +friend class TownsAudioInterfaceInternal; public: TownsAudio_WaveTable(); ~TownsAudio_WaveTable(); @@ -101,12 +101,12 @@ private: int8 *data; }; -class TownsAudioInterfaceIntern : public TownsPC98_FmSynth { +class TownsAudioInterfaceInternal : public TownsPC98_FmSynth { public: - TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); - ~TownsAudioInterfaceIntern(); + TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); + ~TownsAudioInterfaceInternal(); - static TownsAudioInterfaceIntern *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); + static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); static void releaseRef(); bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver); @@ -127,7 +127,7 @@ private: void timerCallbackA(); void timerCallbackB(); - typedef int (TownsAudioInterfaceIntern::*TownsAudioIntfCallback)(va_list &); + typedef int (TownsAudioInterfaceInternal::*TownsAudioIntfCallback)(va_list &); const TownsAudioIntfCallback *_intfOpcodes; int intf_reset(va_list &args); @@ -223,9 +223,11 @@ private: void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w); void updateOutputVolume(); + void updateOutputVolumeInternal(); uint8 _outputVolumeFlags; uint8 _outputLevel[16]; uint8 _outputMute[16]; + bool _updateOutputVol; const float _baserate; uint32 _timerBase; @@ -239,7 +241,7 @@ private: TownsAudioInterfacePluginDriver *_drv; bool _ready; - static TownsAudioInterfaceIntern *_refInstance; + static TownsAudioInterfaceInternal *_refInstance; static int _refCount; static const uint8 _chanFlags[]; @@ -250,15 +252,15 @@ private: static const uint16 _pcmPhase2[]; }; -TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns), +TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns), _fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0), _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver), _pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume), _outputVolumeFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0), _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _fmChanPlaying(0), - _numReservedChannels(0), _numWaveTables(0), _ready(false) { + _numReservedChannels(0), _numWaveTables(0), _updateOutputVol(false), _ready(false) { -#define INTCB(x) &TownsAudioInterfaceIntern::intf_##x +#define INTCB(x) &TownsAudioInterfaceInternal::intf_##x static const TownsAudioIntfCallback intfCb[] = { // 0 INTCB(reset), @@ -381,7 +383,7 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA _tickLength = 2 * _timerBase; } -TownsAudioInterfaceIntern::~TownsAudioInterfaceIntern() { +TownsAudioInterfaceInternal::~TownsAudioInterfaceInternal() { _ready = false; deinit(); @@ -393,19 +395,19 @@ TownsAudioInterfaceIntern::~TownsAudioInterfaceIntern() { delete[] _pcmChan; } -TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) { +TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) { _refCount++; if (_refCount == 1 && _refInstance == 0) - _refInstance = new TownsAudioInterfaceIntern(mixer, driver); + _refInstance = new TownsAudioInterfaceInternal(mixer, driver); else if (_refCount < 2 || _refInstance == 0) - error("TownsAudioInterfaceIntern::addNewRef(): Internal reference management failure"); + error("TownsAudioInterfaceInternal::addNewRef(): Internal reference management failure"); else if (!_refInstance->checkPluginDriver(driver)) - error("TownsAudioInterfaceIntern::addNewRef(): Plugin driver conflict"); + error("TownsAudioInterfaceInternal::addNewRef(): Plugin driver conflict"); return _refInstance; } -void TownsAudioInterfaceIntern::releaseRef() { +void TownsAudioInterfaceInternal::releaseRef() { if (!_refCount) return; @@ -417,7 +419,7 @@ void TownsAudioInterfaceIntern::releaseRef() { } } -bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDriver *driver) { +bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDriver *driver) { if (_refCount <= 1) return true; @@ -425,15 +427,13 @@ bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDrive if (driver && driver != _drv) return false; } else { - lock(); _drv = driver; - unlock(); } return true; } -bool TownsAudioInterfaceIntern::init() { +bool TownsAudioInterfaceInternal::init() { if (_ready) return true; @@ -457,7 +457,7 @@ bool TownsAudioInterfaceIntern::init() { return true; } -int TownsAudioInterfaceIntern::callback(int command, ...) { +int TownsAudioInterfaceInternal::callback(int command, ...) { if (!_ready) return 1; @@ -470,40 +470,42 @@ int TownsAudioInterfaceIntern::callback(int command, ...) { return res; } -int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) { +int TownsAudioInterfaceInternal::processCommand(int command, va_list &args) { if (!_ready) return 1; if (command < 0 || command > 81) return 4; - lock(); + Common::StackLock lock(_mutex); int res = (this->*_intfOpcodes[command])(args); - unlock(); return res; } -void TownsAudioInterfaceIntern::setMusicVolume(int volume) { +void TownsAudioInterfaceInternal::setMusicVolume(int volume) { _musicVolume = CLIP(volume, 0, Audio::Mixer::kMaxMixerVolume); setVolumeIntern(_musicVolume, _sfxVolume); } -void TownsAudioInterfaceIntern::setSoundEffectVolume(int volume) { +void TownsAudioInterfaceInternal::setSoundEffectVolume(int volume) { _sfxVolume = CLIP(volume, 0, Audio::Mixer::kMaxMixerVolume); setVolumeIntern(_musicVolume, _sfxVolume); } -void TownsAudioInterfaceIntern::setSoundEffectChanMask(int mask) { +void TownsAudioInterfaceInternal::setSoundEffectChanMask(int mask) { _pcmSfxChanMask = mask >> 6; mask &= 0x3f; setVolumeChannelMasks(~mask, mask); } -void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) { +void TownsAudioInterfaceInternal::nextTickEx(int32 *buffer, uint32 bufferSize) { if (!_ready) return; + if (_updateOutputVol) + updateOutputVolumeInternal(); + for (uint32 i = 0; i < bufferSize; i++) { _timer += _tickLength; while (_timer > 0x514767) { @@ -551,12 +553,12 @@ void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) { } } -void TownsAudioInterfaceIntern::timerCallbackA() { +void TownsAudioInterfaceInternal::timerCallbackA() { if (_drv && _ready) _drv->timerCallback(0); } -void TownsAudioInterfaceIntern::timerCallbackB() { +void TownsAudioInterfaceInternal::timerCallbackB() { if (_ready) { if (_drv) _drv->timerCallback(1); @@ -564,62 +566,62 @@ void TownsAudioInterfaceIntern::timerCallbackB() { } } -int TownsAudioInterfaceIntern::intf_reset(va_list &args) { +int TownsAudioInterfaceInternal::intf_reset(va_list &args) { fmReset(); pcmReset(); callback(68); return 0; } -int TownsAudioInterfaceIntern::intf_keyOn(va_list &args) { +int TownsAudioInterfaceInternal::intf_keyOn(va_list &args) { int chan = va_arg(args, int); int note = va_arg(args, int); int velo = va_arg(args, int); return (chan & 0x40) ? pcmKeyOn(chan, note, velo) : fmKeyOn(chan, note, velo); } -int TownsAudioInterfaceIntern::intf_keyOff(va_list &args) { +int TownsAudioInterfaceInternal::intf_keyOff(va_list &args) { int chan = va_arg(args, int); return (chan & 0x40) ? pcmKeyOff(chan) : fmKeyOff(chan); } -int TownsAudioInterfaceIntern::intf_setPanPos(va_list &args) { +int TownsAudioInterfaceInternal::intf_setPanPos(va_list &args) { int chan = va_arg(args, int); int mode = va_arg(args, int); return (chan & 0x40) ? pcmSetPanPos(chan, mode) : fmSetPanPos(chan, mode); } -int TownsAudioInterfaceIntern::intf_setInstrument(va_list &args) { +int TownsAudioInterfaceInternal::intf_setInstrument(va_list &args) { int chan = va_arg(args, int); int instrId = va_arg(args, int); return (chan & 0x40) ? pcmSetInstrument(chan, instrId) : fmSetInstrument(chan, instrId); } -int TownsAudioInterfaceIntern::intf_loadInstrument(va_list &args) { +int TownsAudioInterfaceInternal::intf_loadInstrument(va_list &args) { int chanType = va_arg(args, int); int instrId = va_arg(args, int); uint8 *instrData = va_arg(args, uint8 *); return (chanType & 0x40) ? pcmLoadInstrument(instrId, instrData) : fmLoadInstrument(instrId, instrData); } -int TownsAudioInterfaceIntern::intf_setPitch(va_list &args) { +int TownsAudioInterfaceInternal::intf_setPitch(va_list &args) { int chan = va_arg(args, int); int16 pitch = (int16)(va_arg(args, int) & 0xffff); return (chan & 0x40) ? pcmSetPitch(chan, pitch) : fmSetPitch(chan, pitch); } -int TownsAudioInterfaceIntern::intf_setLevel(va_list &args) { +int TownsAudioInterfaceInternal::intf_setLevel(va_list &args) { int chan = va_arg(args, int); int lvl = va_arg(args, int); return (chan & 0x40) ? pcmSetLevel(chan, lvl) : fmSetLevel(chan, lvl); } -int TownsAudioInterfaceIntern::intf_chanOff(va_list &args) { +int TownsAudioInterfaceInternal::intf_chanOff(va_list &args) { int chan = va_arg(args, int); return (chan & 0x40) ? pcmChanOff(chan) : fmChanOff(chan); } -int TownsAudioInterfaceIntern::intf_writeReg(va_list &args) { +int TownsAudioInterfaceInternal::intf_writeReg(va_list &args) { int part = va_arg(args, int) ? 1 : 0; int reg = va_arg(args, int); int val = va_arg(args, int); @@ -630,7 +632,7 @@ int TownsAudioInterfaceIntern::intf_writeReg(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_writeRegBuffer(va_list &args) { +int TownsAudioInterfaceInternal::intf_writeRegBuffer(va_list &args) { int part = va_arg(args, int) ? 1 : 0; int reg = va_arg(args, int); int val = va_arg(args, int); @@ -642,7 +644,7 @@ int TownsAudioInterfaceIntern::intf_writeRegBuffer(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_readRegBuffer(va_list &args) { +int TownsAudioInterfaceInternal::intf_readRegBuffer(va_list &args) { int part = va_arg(args, int) ? 1 : 0; int reg = va_arg(args, int); uint8 *dst = va_arg(args, uint8 *); @@ -655,7 +657,7 @@ int TownsAudioInterfaceIntern::intf_readRegBuffer(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_setTimerA(va_list &args) { +int TownsAudioInterfaceInternal::intf_setTimerA(va_list &args) { int enable = va_arg(args, int); int tempo = va_arg(args, int); @@ -670,7 +672,7 @@ int TownsAudioInterfaceIntern::intf_setTimerA(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_setTimerB(va_list &args) { +int TownsAudioInterfaceInternal::intf_setTimerB(va_list &args) { int enable = va_arg(args, int); int tempo = va_arg(args, int); @@ -684,17 +686,17 @@ int TownsAudioInterfaceIntern::intf_setTimerB(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_enableTimerA(va_list &args) { +int TownsAudioInterfaceInternal::intf_enableTimerA(va_list &args) { bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x15); return 0; } -int TownsAudioInterfaceIntern::intf_enableTimerB(va_list &args) { +int TownsAudioInterfaceInternal::intf_enableTimerB(va_list &args) { bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x2a); return 0; } -int TownsAudioInterfaceIntern::intf_loadSamples(va_list &args) { +int TownsAudioInterfaceInternal::intf_loadSamples(va_list &args) { uint32 dest = va_arg(args, uint32); int size = va_arg(args, int); uint8 *src = va_arg(args, uint8*); @@ -717,7 +719,7 @@ int TownsAudioInterfaceIntern::intf_loadSamples(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_reserveEffectChannels(va_list &args) { +int TownsAudioInterfaceInternal::intf_reserveEffectChannels(va_list &args) { int numChan = va_arg(args, int); if (numChan > 8) return 3; @@ -749,7 +751,7 @@ int TownsAudioInterfaceIntern::intf_reserveEffectChannels(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_loadWaveTable(va_list &args) { +int TownsAudioInterfaceInternal::intf_loadWaveTable(va_list &args) { uint8 *data = va_arg(args, uint8 *); if (_numWaveTables > 127) return 3; @@ -776,7 +778,7 @@ int TownsAudioInterfaceIntern::intf_loadWaveTable(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_unloadWaveTable(va_list &args) { +int TownsAudioInterfaceInternal::intf_unloadWaveTable(va_list &args) { int id = va_arg(args, int); if (id == -1) { @@ -803,7 +805,7 @@ int TownsAudioInterfaceIntern::intf_unloadWaveTable(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_pcmPlayEffect(va_list &args) { +int TownsAudioInterfaceInternal::intf_pcmPlayEffect(va_list &args) { int chan = va_arg(args, int); int note = va_arg(args, int); int velo = va_arg(args, int); @@ -853,13 +855,13 @@ int TownsAudioInterfaceIntern::intf_pcmPlayEffect(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_pcmChanOff(va_list &args) { +int TownsAudioInterfaceInternal::intf_pcmChanOff(va_list &args) { int chan = va_arg(args, int); pcmChanOff(chan); return 0; } -int TownsAudioInterfaceIntern::intf_pcmEffectPlaying(va_list &args) { +int TownsAudioInterfaceInternal::intf_pcmEffectPlaying(va_list &args) { int chan = va_arg(args, int); if (chan < 0x40 || chan > 0x47) return 1; @@ -867,54 +869,54 @@ int TownsAudioInterfaceIntern::intf_pcmEffectPlaying(va_list &args) { return (_pcmChanEffectPlaying & _chanFlags[chan]) ? 1 : 0; } -int TownsAudioInterfaceIntern::intf_fmKeyOn(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmKeyOn(va_list &args) { int chan = va_arg(args, int); int note = va_arg(args, int); int velo = va_arg(args, int); return fmKeyOn(chan, note, velo); } -int TownsAudioInterfaceIntern::intf_fmKeyOff(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmKeyOff(va_list &args) { int chan = va_arg(args, int); return fmKeyOff(chan); } -int TownsAudioInterfaceIntern::intf_fmSetPanPos(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmSetPanPos(va_list &args) { int chan = va_arg(args, int); int mode = va_arg(args, int); return fmSetPanPos(chan, mode); } -int TownsAudioInterfaceIntern::intf_fmSetInstrument(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmSetInstrument(va_list &args) { int chan = va_arg(args, int); int instrId = va_arg(args, int); return fmSetInstrument(chan, instrId); } -int TownsAudioInterfaceIntern::intf_fmLoadInstrument(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmLoadInstrument(va_list &args) { int instrId = va_arg(args, int); uint8 *instrData = va_arg(args, uint8 *); return fmLoadInstrument(instrId, instrData); } -int TownsAudioInterfaceIntern::intf_fmSetPitch(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmSetPitch(va_list &args) { int chan = va_arg(args, int); uint16 freq = va_arg(args, int) & 0xffff; return fmSetPitch(chan, freq); } -int TownsAudioInterfaceIntern::intf_fmSetLevel(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmSetLevel(va_list &args) { int chan = va_arg(args, int); int lvl = va_arg(args, int); return fmSetLevel(chan, lvl); } -int TownsAudioInterfaceIntern::intf_fmReset(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmReset(va_list &args) { fmReset(); return 0; } -int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) { +int TownsAudioInterfaceInternal::intf_setOutputVolume(va_list &args) { int chanType = va_arg(args, int); int left = va_arg(args, int); int right = va_arg(args, int); @@ -951,14 +953,14 @@ int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_resetOutputVolume(va_list &args) { +int TownsAudioInterfaceInternal::intf_resetOutputVolume(va_list &args) { memset(_outputLevel, 0, sizeof(_outputLevel)); _outputVolumeFlags = 0; updateOutputVolume(); return 0; } -int TownsAudioInterfaceIntern::intf_getOutputVolume(va_list &args) { +int TownsAudioInterfaceInternal::intf_getOutputVolume(va_list &args) { int chanType = va_arg(args, int); int *left = va_arg(args, int*); int *right = va_arg(args, int*); @@ -978,7 +980,7 @@ int TownsAudioInterfaceIntern::intf_getOutputVolume(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) { +int TownsAudioInterfaceInternal::intf_setOutputMute(va_list &args) { int flags = va_arg(args, int); _outputVolumeFlags = flags; uint8 mute = flags & 3; @@ -1007,31 +1009,31 @@ int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_cdaToggle(va_list &args) { +int TownsAudioInterfaceInternal::intf_cdaToggle(va_list &args) { //int mode = va_arg(args, int); //_unkMask = mode ? 0x7f : 0x3f; return 0; } -int TownsAudioInterfaceIntern::intf_getOutputVolume2(va_list &args) { +int TownsAudioInterfaceInternal::intf_getOutputVolume2(va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_getOutputMute (va_list &args) { +int TownsAudioInterfaceInternal::intf_getOutputMute (va_list &args) { return 0; } -int TownsAudioInterfaceIntern::intf_pcmUpdateEnvelopeGenerator(va_list &args) { +int TownsAudioInterfaceInternal::intf_pcmUpdateEnvelopeGenerator(va_list &args) { for (int i = 0; i < 8; i++) pcmUpdateEnvelopeGenerator(i); return 0; } -int TownsAudioInterfaceIntern::intf_notImpl(va_list &args) { +int TownsAudioInterfaceInternal::intf_notImpl(va_list &args) { return 4; } -void TownsAudioInterfaceIntern::fmReset() { +void TownsAudioInterfaceInternal::fmReset() { TownsPC98_FmSynth::reset(); _fmChanPlaying = 0; @@ -1059,7 +1061,7 @@ void TownsAudioInterfaceIntern::fmReset() { } } -int TownsAudioInterfaceIntern::fmKeyOn(int chan, int note, int velo) { +int TownsAudioInterfaceInternal::fmKeyOn(int chan, int note, int velo) { if (chan > 5) return 1; if (note < 12 || note > 107 || (velo & 0x80)) @@ -1139,7 +1141,7 @@ int TownsAudioInterfaceIntern::fmKeyOn(int chan, int note, int velo) { return 0; } -int TownsAudioInterfaceIntern::fmKeyOff(int chan) { +int TownsAudioInterfaceInternal::fmKeyOff(int chan) { if (chan > 5) return 1; _fmChanPlaying &= ~_chanFlags[chan]; @@ -1149,7 +1151,7 @@ int TownsAudioInterfaceIntern::fmKeyOff(int chan) { return 0; } -int TownsAudioInterfaceIntern::fmChanOff(int chan) { +int TownsAudioInterfaceInternal::fmChanOff(int chan) { if (chan > 5) return 1; _fmChanPlaying &= ~_chanFlags[chan]; @@ -1167,7 +1169,7 @@ int TownsAudioInterfaceIntern::fmChanOff(int chan) { return 0; } -int TownsAudioInterfaceIntern::fmSetPanPos(int chan, int value) { +int TownsAudioInterfaceInternal::fmSetPanPos(int chan, int value) { if (chan > 5) return 1; @@ -1186,7 +1188,7 @@ int TownsAudioInterfaceIntern::fmSetPanPos(int chan, int value) { return 0; } -int TownsAudioInterfaceIntern::fmSetInstrument(int chan, int instrId) { +int TownsAudioInterfaceInternal::fmSetInstrument(int chan, int instrId) { if (chan > 5) return 1; if (instrId > 127) @@ -1230,7 +1232,7 @@ int TownsAudioInterfaceIntern::fmSetInstrument(int chan, int instrId) { return 0; } -int TownsAudioInterfaceIntern::fmLoadInstrument(int instrId, const uint8 *data) { +int TownsAudioInterfaceInternal::fmLoadInstrument(int instrId, const uint8 *data) { if (instrId > 127) return 3; assert(data); @@ -1238,7 +1240,7 @@ int TownsAudioInterfaceIntern::fmLoadInstrument(int instrId, const uint8 *data) return 0; } -int TownsAudioInterfaceIntern::fmSetPitch(int chan, int pitch) { +int TownsAudioInterfaceInternal::fmSetPitch(int chan, int pitch) { if (chan > 5) return 1; @@ -1325,7 +1327,7 @@ int TownsAudioInterfaceIntern::fmSetPitch(int chan, int pitch) { return 0; } -int TownsAudioInterfaceIntern::fmSetLevel(int chan, int lvl) { +int TownsAudioInterfaceInternal::fmSetLevel(int chan, int lvl) { if (chan > 5) return 1; if (lvl > 127) @@ -1348,12 +1350,12 @@ int TownsAudioInterfaceIntern::fmSetLevel(int chan, int lvl) { return 0; } -void TownsAudioInterfaceIntern::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) { +void TownsAudioInterfaceInternal::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) { _fmSaveReg[part][regAddress] = value; writeReg(part, regAddress, value); } -void TownsAudioInterfaceIntern::pcmReset() { +void TownsAudioInterfaceInternal::pcmReset() { _pcmChanOut = 0; _pcmChanReserved = _pcmChanKeyPressed = _pcmChanEffectPlaying = _pcmChanKeyPlaying = 0; _numReservedChannels = 0; @@ -1381,7 +1383,7 @@ void TownsAudioInterfaceIntern::pcmReset() { } } -int TownsAudioInterfaceIntern::pcmKeyOn(int chan, int note, int velo) { +int TownsAudioInterfaceInternal::pcmKeyOn(int chan, int note, int velo) { if (chan < 0x40 || chan > 0x47) return 1; @@ -1452,7 +1454,7 @@ int TownsAudioInterfaceIntern::pcmKeyOn(int chan, int note, int velo) { return 0; } -int TownsAudioInterfaceIntern::pcmKeyOff(int chan) { +int TownsAudioInterfaceInternal::pcmKeyOff(int chan) { if (chan < 0x40 || chan > 0x47) return 1; @@ -1462,7 +1464,7 @@ int TownsAudioInterfaceIntern::pcmKeyOff(int chan) { return 0; } -int TownsAudioInterfaceIntern::pcmChanOff(int chan) { +int TownsAudioInterfaceInternal::pcmChanOff(int chan) { if (chan < 0x40 || chan > 0x47) return 1; @@ -1476,7 +1478,7 @@ int TownsAudioInterfaceIntern::pcmChanOff(int chan) { return 0; } -int TownsAudioInterfaceIntern::pcmSetPanPos(int chan, int mode) { +int TownsAudioInterfaceInternal::pcmSetPanPos(int chan, int mode) { if (chan > 0x47) return 1; if (mode & 0x80) @@ -1499,7 +1501,7 @@ int TownsAudioInterfaceIntern::pcmSetPanPos(int chan, int mode) { return 0; } -int TownsAudioInterfaceIntern::pcmSetInstrument(int chan, int instrId) { +int TownsAudioInterfaceInternal::pcmSetInstrument(int chan, int instrId) { if (chan > 0x47) return 1; if (instrId > 31) @@ -1509,7 +1511,7 @@ int TownsAudioInterfaceIntern::pcmSetInstrument(int chan, int instrId) { return 0; } -int TownsAudioInterfaceIntern::pcmLoadInstrument(int instrId, const uint8 *data) { +int TownsAudioInterfaceInternal::pcmLoadInstrument(int instrId, const uint8 *data) { if (instrId > 31) return 3; assert(data); @@ -1517,7 +1519,7 @@ int TownsAudioInterfaceIntern::pcmLoadInstrument(int instrId, const uint8 *data) return 0; } -int TownsAudioInterfaceIntern::pcmSetPitch(int chan, int pitch) { +int TownsAudioInterfaceInternal::pcmSetPitch(int chan, int pitch) { if (chan > 0x47) return 1; @@ -1547,7 +1549,7 @@ int TownsAudioInterfaceIntern::pcmSetPitch(int chan, int pitch) { return 0; } -int TownsAudioInterfaceIntern::pcmSetLevel(int chan, int lvl) { +int TownsAudioInterfaceInternal::pcmSetLevel(int chan, int lvl) { if (chan > 0x47) return 1; @@ -1576,7 +1578,7 @@ int TownsAudioInterfaceIntern::pcmSetLevel(int chan, int lvl) { return 0; } -void TownsAudioInterfaceIntern::pcmUpdateEnvelopeGenerator(int chan) { +void TownsAudioInterfaceInternal::pcmUpdateEnvelopeGenerator(int chan) { TownsAudio_PcmChannel *p = &_pcmChan[chan]; if (!p->envCurrentLevel) { _pcmChanKeyPlaying &= ~_chanFlags[chan]; @@ -1618,7 +1620,7 @@ void TownsAudioInterfaceIntern::pcmUpdateEnvelopeGenerator(int chan) { p->velo = (p->envCurrentLevel >> 8) << 1; } -void TownsAudioInterfaceIntern::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) { +void TownsAudioInterfaceInternal::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) { int8 diff = p->note - w->baseNote; uint16 r = w->rate + w->rateOffs; uint16 bl = 0; @@ -1647,7 +1649,16 @@ void TownsAudioInterfaceIntern::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, Towns p->step = (s * p->stepPitch) >> 14; } -void TownsAudioInterfaceIntern::updateOutputVolume() { +void TownsAudioInterfaceInternal::updateOutputVolume() { + // Avoid calls to g_system->getAudioCDManager() functions from the main thread + // since this can cause mutex lockups. + _updateOutputVol = true; +} + +void TownsAudioInterfaceInternal::updateOutputVolumeInternal() { + if (!_ready) + return; + // FM Towns seems to support volumes of 0 - 63 for each channel. // We recalculate sane values for our 0 to 255 volume range and // balance values for our -128 to 127 volume range @@ -1658,38 +1669,41 @@ void TownsAudioInterfaceIntern::updateOutputVolume() { int volume = (int)(((float)(maxVol * 255) / 63.0f)); int balance = maxVol ? (int)( ( ((int)_outputLevel[13] * (_outputMute[13] ^ 1) - _outputLevel[12] * (_outputMute[12] ^ 1)) * 127) / (float)maxVol) : 0; + Common::StackLock lock(_mutex); g_system->getAudioCDManager()->setVolume(volume); g_system->getAudioCDManager()->setBalance(balance); + + _updateOutputVol = false; } -TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::_refInstance = 0; +TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::_refInstance = 0; -int TownsAudioInterfaceIntern::_refCount = 0; +int TownsAudioInterfaceInternal::_refCount = 0; -const uint8 TownsAudioInterfaceIntern::_chanFlags[] = { +const uint8 TownsAudioInterfaceInternal::_chanFlags[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; -const uint16 TownsAudioInterfaceIntern::_frequency[] = { +const uint16 TownsAudioInterfaceInternal::_frequency[] = { 0x028C, 0x02B4, 0x02DC, 0x030A, 0x0338, 0x0368, 0x039C, 0x03D4, 0x040E, 0x044A, 0x048C, 0x04D0 }; -const uint8 TownsAudioInterfaceIntern::_carrier[] = { +const uint8 TownsAudioInterfaceInternal::_carrier[] = { 0x10, 0x10, 0x10, 0x10, 0x30, 0x70, 0x70, 0xF0 }; -const uint8 TownsAudioInterfaceIntern::_fmDefaultInstrument[] = { +const uint8 TownsAudioInterfaceInternal::_fmDefaultInstrument[] = { 0x45, 0x4C, 0x45, 0x50, 0x49, 0x41, 0x4E, 0x4F, 0x01, 0x0A, 0x02, 0x01, 0x1E, 0x32, 0x05, 0x00, 0x9C, 0xDC, 0x9C, 0xDC, 0x07, 0x03, 0x14, 0x08, 0x00, 0x03, 0x05, 0x05, 0x55, 0x45, 0x27, 0xA7, 0x04, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const uint16 TownsAudioInterfaceIntern::_pcmPhase1[] = { +const uint16 TownsAudioInterfaceInternal::_pcmPhase1[] = { 0x879B, 0x0F37, 0x1F58, 0x306E, 0x4288, 0x55B6, 0x6A08, 0x7F8F, 0x965E, 0xAE88, 0xC882, 0xE341 }; -const uint16 TownsAudioInterfaceIntern::_pcmPhase2[] = { +const uint16 TownsAudioInterfaceInternal::_pcmPhase2[] = { 0xFEFE, 0xF1A0, 0xE411, 0xD744, 0xCB2F, 0xBFC7, 0xB504, 0xAAE2, 0xA144, 0x9827, 0x8FAC }; @@ -1841,11 +1855,11 @@ void TownsAudio_WaveTable::clear() { } TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) { - _intf = TownsAudioInterfaceIntern::addNewRef(mixer, driver); + _intf = TownsAudioInterfaceInternal::addNewRef(mixer, driver); } TownsAudioInterface::~TownsAudioInterface() { - TownsAudioInterfaceIntern::releaseRef(); + TownsAudioInterfaceInternal::releaseRef(); _intf = 0; } @@ -1874,3 +1888,11 @@ void TownsAudioInterface::setSoundEffectVolume(int volume) { void TownsAudioInterface::setSoundEffectChanMask(int mask) { _intf->setSoundEffectChanMask(mask); } + +void TownsAudioInterface::lockInternal() { + _intf->lock(); +} + +void TownsAudioInterface::unlockInternal() { + _intf->unlock(); +} diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.h b/audio/softsynth/fmtowns_pc98/towns_audio.h index 2c58d46d06..b00243f610 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.h +++ b/audio/softsynth/fmtowns_pc98/towns_audio.h @@ -25,7 +25,7 @@ #include "audio/mixer.h" -class TownsAudioInterfaceIntern; +class TownsAudioInterfaceInternal; class TownsAudioInterfacePluginDriver { public: @@ -48,8 +48,15 @@ public: // The first 6 bits are the 6 fm channels. The next 8 bits are pcm channels. void setSoundEffectChanMask(int mask); + // These methods should not be needed in standard situations, since the mutex + // is handled internally. However, they may be required to avoid lockup situations + // if the code using this class has a mutex of its own (example for a lockup + // situation: imuse.cpp, line 78). + void lockInternal(); + void unlockInternal(); + private: - TownsAudioInterfaceIntern *_intf; + TownsAudioInterfaceInternal *_intf; }; #endif diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 3c7ce7d0e4..00f0d43b98 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -835,19 +835,6 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _channels(0), _out(0), _chanState(0), _operatorLevelTable(0), _tickCounter1(0), _tickCounter2(0), _rand(1), _allocCurPos(0), _isOpen(false) { _intf = new TownsAudioInterface(mixer, this); -} - -MidiDriver_TOWNS::~MidiDriver_TOWNS() { - close(); - delete _intf; -} - -int MidiDriver_TOWNS::open() { - if (_isOpen) - return MERR_ALREADY_OPEN; - - if (!_intf->init()) - return MERR_CANNOT_CONNECT; _channels = new TownsMidiInputChannel*[32]; for (int i = 0; i < 32; i++) @@ -866,6 +853,38 @@ int MidiDriver_TOWNS::open() { } for (int i = 0; i < 64; i++) _operatorLevelTable[i << 5] = 0; +} + +MidiDriver_TOWNS::~MidiDriver_TOWNS() { + close(); + delete _intf; + + if (_channels) { + for (int i = 0; i < 32; i++) + delete _channels[i]; + delete[] _channels; + } + _channels = 0; + + if (_out) { + for (int i = 0; i < 6; i++) + delete _out[i]; + delete[] _out; + } + _out = 0; + + delete[] _chanState; + _chanState = 0; + delete[] _operatorLevelTable; + _operatorLevelTable = 0; +} + +int MidiDriver_TOWNS::open() { + if (_isOpen) + return MERR_ALREADY_OPEN; + + if (!_intf->init()) + return MERR_CANNOT_CONNECT; _intf->callback(0); @@ -876,9 +895,7 @@ int MidiDriver_TOWNS::open() { _intf->callback(33, 8); _intf->setSoundEffectChanMask(~0x3f); - _tickCounter1 = _tickCounter2 = 0; - _allocCurPos = 0; - _rand = 1; + _allocCurPos = 0; _isOpen = true; @@ -893,25 +910,6 @@ void MidiDriver_TOWNS::close() { setTimerCallback(0, 0); g_system->delayMillis(20); - - if (_channels) { - for (int i = 0; i < 32; i++) - delete _channels[i]; - delete[] _channels; - } - _channels = 0; - - if (_out) { - for (int i = 0; i < 6; i++) - delete _out[i]; - delete[] _out; - } - _out = 0; - - delete[] _chanState; - _chanState = 0; - delete[] _operatorLevelTable; - _operatorLevelTable = 0; } void MidiDriver_TOWNS::send(uint32 b) { diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp index e35da91cbb..ee20068e74 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp @@ -1145,7 +1145,7 @@ void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) { reset(); - lock(); + Common::StackLock lock(_mutex); uint8 *src_a = _trackPtr = _musicBuffer = data; for (uint8 i = 0; i < 3; i++) { @@ -1176,7 +1176,6 @@ void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) { _finishedChannelsFlag = _finishedSSGFlag = _finishedRhythmFlag = 0; _musicPlaying = (loadPaused ? false : true); - unlock(); } void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) { @@ -1195,17 +1194,16 @@ void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) { return; } - lock(); + Common::StackLock lock(_mutex); _sfxData = _sfxBuffer = data; _sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]); _sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]); _sfxPlaying = true; _finishedSfxFlag = 0; - unlock(); } void TownsPC98_AudioDriver::reset() { - lock(); + Common::StackLock lock(_mutex); _musicPlaying = false; _sfxPlaying = false; @@ -1232,7 +1230,6 @@ void TownsPC98_AudioDriver::reset() { if (_rhythmChannel) _rhythmChannel->reset(); #endif - unlock(); } void TownsPC98_AudioDriver::fadeStep() { @@ -1263,37 +1260,30 @@ void TownsPC98_AudioDriver::fadeStep() { } } -void TownsPC98_AudioDriver::timerCallbackB() { - _sfxOffs = 0; - - if (_musicPlaying) { - _musicTickCounter++; - - for (int i = 0; i < _numChan; i++) { - if (_updateChannelsFlag & _channels[i]->_idFlag) { - _channels[i]->processEvents(); - _channels[i]->processFrequency(); - } - } +void TownsPC98_AudioDriver::pause() { + _musicPlaying = false; +} + +void TownsPC98_AudioDriver::cont() { + _musicPlaying = true; +} - for (int i = 0; i < _numSSG; i++) { - if (_updateSSGFlag & _ssgChannels[i]->_idFlag) { - _ssgChannels[i]->processEvents(); - _ssgChannels[i]->processFrequency(); - } - } +bool TownsPC98_AudioDriver::looping() { + return _looping == _updateChannelsFlag ? true : false; +} -#ifndef DISABLE_PC98_RHYTHM_CHANNEL - if (_hasPercussion) - if (_updateRhythmFlag & _rhythmChannel->_idFlag) - _rhythmChannel->processEvents(); -#endif - } +bool TownsPC98_AudioDriver::musicPlaying() { + return _musicPlaying; +} - toggleRegProtection(false); +void TownsPC98_AudioDriver::setMusicVolume(int volume) { + _musicVolume = volume; + setVolumeIntern(_musicVolume, _sfxVolume); +} - if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedRhythmFlag == _updateRhythmFlag) - _musicPlaying = false; +void TownsPC98_AudioDriver::setSoundEffectVolume(int volume) { + _sfxVolume = volume; + setVolumeIntern(_musicVolume, _sfxVolume); } void TownsPC98_AudioDriver::timerCallbackA() { @@ -1321,15 +1311,37 @@ void TownsPC98_AudioDriver::timerCallbackA() { } } -void TownsPC98_AudioDriver::setMusicTempo(uint8 tempo) { - writeReg(0, 0x26, tempo); - writeReg(0, 0x27, 0x33); -} +void TownsPC98_AudioDriver::timerCallbackB() { + _sfxOffs = 0; -void TownsPC98_AudioDriver::setSfxTempo(uint16 tempo) { - writeReg(0, 0x24, tempo & 0xff); - writeReg(0, 0x25, tempo >> 8); - writeReg(0, 0x27, 0x33); + if (_musicPlaying) { + _musicTickCounter++; + + for (int i = 0; i < _numChan; i++) { + if (_updateChannelsFlag & _channels[i]->_idFlag) { + _channels[i]->processEvents(); + _channels[i]->processFrequency(); + } + } + + for (int i = 0; i < _numSSG; i++) { + if (_updateSSGFlag & _ssgChannels[i]->_idFlag) { + _ssgChannels[i]->processEvents(); + _ssgChannels[i]->processFrequency(); + } + } + +#ifndef DISABLE_PC98_RHYTHM_CHANNEL + if (_hasPercussion) + if (_updateRhythmFlag & _rhythmChannel->_idFlag) + _rhythmChannel->processEvents(); +#endif + } + + toggleRegProtection(false); + + if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedRhythmFlag == _updateRhythmFlag) + _musicPlaying = false; } void TownsPC98_AudioDriver::startSoundEffect() { @@ -1352,6 +1364,16 @@ void TownsPC98_AudioDriver::startSoundEffect() { _sfxData = 0; } +void TownsPC98_AudioDriver::setMusicTempo(uint8 tempo) { + writeReg(0, 0x26, tempo); + writeReg(0, 0x27, 0x33); +} + +void TownsPC98_AudioDriver::setSfxTempo(uint16 tempo) { + writeReg(0, 0x24, tempo & 0xff); + writeReg(0, 0x25, tempo >> 8); + writeReg(0, 0x27, 0x33); +} const uint8 TownsPC98_AudioDriver::_drvTables[] = { // channel presets 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h index 46ee23895b..ff58482227 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h @@ -50,33 +50,19 @@ public: void fadeStep(); - void pause() { - _musicPlaying = false; - } - void cont() { - _musicPlaying = true; - } + void pause(); + void cont(); - void timerCallbackB(); + bool looping(); + bool musicPlaying(); + + void setMusicVolume(int volume); + void setSoundEffectVolume(int volume); + +private: void timerCallbackA(); + void timerCallbackB(); - bool looping() { - return _looping == _updateChannelsFlag ? true : false; - } - bool musicPlaying() { - return _musicPlaying; - } - - void setMusicVolume(int volume) { - _musicVolume = volume; - setVolumeIntern(_musicVolume, _sfxVolume); - } - void setSoundEffectVolume(int volume) { - _sfxVolume = volume; - setVolumeIntern(_musicVolume, _sfxVolume); - } - -protected: void startSoundEffect(); void setMusicTempo(uint8 tempo); diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index bc5aa32823..b09a9f65d1 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -861,7 +861,7 @@ TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) : _hasPercussion(type == kType86 ? true : false), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()), - _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _lock(0), _ready(false) { + _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _ready(false) { memset(&_timers[0], 0, sizeof(ChipTimer)); memset(&_timers[1], 0, sizeof(ChipTimer)); @@ -928,7 +928,7 @@ bool TownsPC98_FmSynth::init() { } void TownsPC98_FmSynth::reset() { - lock(); + Common::StackLock lock(_mutex); for (int i = 0; i < _numChan; i++) { for (int ii = 0; ii < 4; ii++) _chanInternal[i].opr[ii]->reset(); @@ -948,14 +948,13 @@ void TownsPC98_FmSynth::reset() { if (_prc) _prc->reset(); #endif - unlock(); } void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) { if (_regProtectionFlag || !_ready) return; - lock(); + Common::StackLock lock(_mutex); static const uint8 oprOrdr[] = { 0, 2, 1, 3 }; @@ -1137,7 +1136,6 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) { default: warning("TownsPC98_FmSynth: UNKNOWN ADDRESS %d", regAddress); } - unlock(); } int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { @@ -1146,9 +1144,14 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { int32 *tmpStart = tmp; memset(tmp, 0, sizeof(int32) * numSamples); int32 samplesLeft = numSamples >> 1; - _lock |= 0x10000; - while (_ready && !(_lock & 0xffff) && samplesLeft) { + bool locked = false; + if (_ready) { + lock(); + locked = true; + } + + while (_ready && samplesLeft) { int32 render = samplesLeft; for (int i = 0; i < 2; i++) { @@ -1197,17 +1200,38 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { tmp += (render << 1); } - _lock &= ~0x10000; + if (locked) + unlock(); + delete[] tmpStart; return numSamples; } +bool TownsPC98_FmSynth::isStereo() const { + return true; +} + +bool TownsPC98_FmSynth::endOfData() const { + return false; +} + +int TownsPC98_FmSynth::getRate() const { + return _mixer->getOutputRate(); +} + +void TownsPC98_FmSynth::lock() { + _mutex.lock(); +} + +void TownsPC98_FmSynth::unlock() { + _mutex.unlock(); +} + void TownsPC98_FmSynth::deinit() { _ready = false; - while (_lock) - g_system->delayMillis(20); _mixer->stopHandle(_soundHandle); + Common::StackLock lock(_mutex); _timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback; } @@ -1216,7 +1240,7 @@ uint8 TownsPC98_FmSynth::readSSGStatus() { } void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) { - lock(); + Common::StackLock lock(_mutex); _volumeA = CLIP(volA, 0, Audio::Mixer::kMaxMixerVolume); _volumeB = CLIP(volB, 0, Audio::Mixer::kMaxMixerVolume); if (_ssg) @@ -1225,11 +1249,10 @@ void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) { if (_prc) _prc->setVolumeIntern(_volumeA, _volumeB); #endif - unlock(); } void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB) { - lock(); + Common::StackLock lock(_mutex); _volMaskA = channelMaskA; _volMaskB = channelMaskB; if (_ssg) @@ -1238,17 +1261,6 @@ void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB if (_prc) _prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG)); #endif - unlock(); -} - -void TownsPC98_FmSynth::lock() { - _mutex.lock(); - _lock++; -} - -void TownsPC98_FmSynth::unlock() { - _mutex.unlock(); - _lock--; } void TownsPC98_FmSynth::generateTables() { diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index f7bcc90585..a1b09abd3a 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -69,15 +69,12 @@ public: // AudioStream interface int readBuffer(int16 *buffer, const int numSamples); - bool isStereo() const { - return true; - } - bool endOfData() const { - return false; - } - int getRate() const { - return _mixer->getOutputRate(); - } + bool isStereo() const; + bool endOfData() const; + int getRate() const; + + void lock(); + void unlock(); protected: void deinit(); @@ -102,13 +99,12 @@ protected: void setVolumeIntern(int volA, int volB); void setVolumeChannelMasks(int channelMaskA, int channelMaskB); - void lock(); - void unlock(); - const int _numChan; const int _numSSG; const bool _hasPercussion; + Common::Mutex _mutex; + private: void generateTables(); void nextTick(int32 *buffer, uint32 bufferSize); @@ -182,9 +178,6 @@ private: Audio::Mixer *_mixer; Audio::SoundHandle _soundHandle; - int _lock; - Common::Mutex _mutex; - #ifndef DISABLE_PC98_RHYTHM_CHANNEL static const uint8 _percussionData[]; #endif -- cgit v1.2.3 From 2ef8e9a2025fb522825cd8b39af331a2faae2f1f Mon Sep 17 00:00:00 2001 From: athrxx Date: Fri, 20 May 2011 16:21:39 +0200 Subject: FM-TOWNS AUDIO: fix gcc warnings --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 4 ++-- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 8 ++++---- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 635f9354cc..5161871601 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -1890,9 +1890,9 @@ void TownsAudioInterface::setSoundEffectChanMask(int mask) { } void TownsAudioInterface::lockInternal() { - _intf->lock(); + _intf->mutexLock(); } void TownsAudioInterface::unlockInternal() { - _intf->unlock(); + _intf->mutexUnlock(); } diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index b09a9f65d1..4336de9bdb 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -1147,7 +1147,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { bool locked = false; if (_ready) { - lock(); + mutexLock(); locked = true; } @@ -1201,7 +1201,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { } if (locked) - unlock(); + mutexUnlock(); delete[] tmpStart; @@ -1220,11 +1220,11 @@ int TownsPC98_FmSynth::getRate() const { return _mixer->getOutputRate(); } -void TownsPC98_FmSynth::lock() { +void TownsPC98_FmSynth::mutexLock() { _mutex.lock(); } -void TownsPC98_FmSynth::unlock() { +void TownsPC98_FmSynth::mutexUnlock() { _mutex.unlock(); } diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index a1b09abd3a..6ea9815a72 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -73,8 +73,8 @@ public: bool endOfData() const; int getRate() const; - void lock(); - void unlock(); + void mutexLock(); + void mutexUnlock(); protected: void deinit(); -- cgit v1.2.3 From e7c642b010c47d2520d21ea5b3c041d861bc1532 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 21 May 2011 19:03:22 +0200 Subject: AUDIO: Explicitly instantiate & name RandomSource used by MAME OPL --- audio/softsynth/opl/mame.cpp | 14 ++++++++++++-- audio/softsynth/opl/mame.h | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp index b380a15345..9cc35971eb 100644 --- a/audio/softsynth/opl/mame.cpp +++ b/audio/softsynth/opl/mame.cpp @@ -546,7 +546,7 @@ inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) { // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to // int(OPL->rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024, // or 128, so we can safely avoid any FP ops. - int whitenoise = OPL->rnd.getRandomBit() * (EG_ENT>>4); + int whitenoise = OPL->rnd->getRandomBit() * (EG_ENT>>4); int tone8; @@ -1126,6 +1126,15 @@ FM_OPL *OPLCreate(int type, int clock, int rate) { OPL->rate = rate; OPL->max_ch = max_ch; + // Init the random source. Note: We use a fixed name for it here. + // So if multiple FM_OPL objects exist in parallel, then their + // random sources will have an equal name. At least in the + // current EventRecorder implementation, this causes no problems; + // but this is probably not guaranteed. + // Alas, it does not seem worthwhile to bother much with this + // at the time, so I am leaving it as it is. + OPL->rnd = new Common::RandomSource("mame"); + /* init grobal tables */ OPL_initalize(OPL); @@ -1134,9 +1143,10 @@ FM_OPL *OPLCreate(int type, int clock, int rate) { return OPL; } -/* ---------- Destroy one of vietual YM3812 ---------- */ +/* ---------- Destroy one of virtual YM3812 ---------- */ void OPLDestroy(FM_OPL *OPL) { OPL_UnLockTable(); + delete OPL->rnd; free(OPL); } diff --git a/audio/softsynth/opl/mame.h b/audio/softsynth/opl/mame.h index 4c40949483..803ca897e7 100644 --- a/audio/softsynth/opl/mame.h +++ b/audio/softsynth/opl/mame.h @@ -147,7 +147,7 @@ typedef struct fm_opl_f { OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */ int UpdateParam; /* stream update parameter */ - Common::RandomSource rnd; + Common::RandomSource *rnd; } FM_OPL; /* ---------- Generic interface section ---------- */ -- cgit v1.2.3 From 9539017ee35ce280758f22e589aa52c3baf9aaf3 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Wed, 25 May 2011 11:17:11 -0400 Subject: ALL: initialise -> initialize --- audio/softsynth/mt32.cpp | 14 +++++++------- audio/softsynth/mt32/partial.cpp | 2 +- audio/softsynth/mt32/synth.cpp | 22 +++++++++++----------- audio/softsynth/mt32/synth.h | 2 +- audio/softsynth/mt32/tables.cpp | 20 ++++++++++---------- audio/softsynth/mt32/tables.h | 4 ++-- 6 files changed, 32 insertions(+), 32 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/mt32.cpp b/audio/softsynth/mt32.cpp index a9a612f410..27a5a629c4 100644 --- a/audio/softsynth/mt32.cpp +++ b/audio/softsynth/mt32.cpp @@ -63,7 +63,7 @@ protected: void generateSamples(int16 *buf, int len); public: - bool _initialising; + bool _initializing; MidiDriver_MT32(Audio::Mixer *mixer); virtual ~MidiDriver_MT32(); @@ -215,7 +215,7 @@ static MT32Emu::File *MT32_OpenFile(void *userData, const char *filename, MT32Em } static void MT32_PrintDebug(void *userData, const char *fmt, va_list list) { - if (((MidiDriver_MT32 *)userData)->_initialising) { + if (((MidiDriver_MT32 *)userData)->_initializing) { char buf[512]; vsnprintf(buf, 512, fmt, list); @@ -239,7 +239,7 @@ static int MT32_Report(void *userData, MT32Emu::ReportType type, const void *rep error("Failed to load MT32_PCM.ROM"); break; case MT32Emu::ReportType_progressInit: - if (((MidiDriver_MT32 *)userData)->_initialising) { + if (((MidiDriver_MT32 *)userData)->_initializing) { drawProgress(*((const float *)reportData)); return eatSystemEvents(); } @@ -283,7 +283,7 @@ MidiDriver_MT32::MidiDriver_MT32(Audio::Mixer *mixer) : MidiDriver_Emulated(mixe // at rates other than 32KHz, thus we produce data at 32KHz and // rely on Mixer to convert. _outputRate = 32000; //_mixer->getOutputRate(); - _initialising = false; + _initializing = false; } MidiDriver_MT32::~MidiDriver_MT32() { @@ -324,11 +324,11 @@ int MidiDriver_MT32::open() { g_system->getPaletteManager()->setPalette(dummy_palette, 0, 3); } - _initialising = true; - drawMessage(-1, _s("Initialising MT-32 Emulator")); + _initializing = true; + drawMessage(-1, _s("Initializing MT-32 Emulator")); if (!_synth->open(prop)) return MERR_DEVICE_NOT_AVAILABLE; - _initialising = false; + _initializing = false; if (screenFormat.bytesPerPixel > 1) g_system->fillScreen(screenFormat.RGBToColor(0, 0, 0)); diff --git a/audio/softsynth/mt32/partial.cpp b/audio/softsynth/mt32/partial.cpp index d06634dc91..c4f2e94ebe 100644 --- a/audio/softsynth/mt32/partial.cpp +++ b/audio/softsynth/mt32/partial.cpp @@ -164,7 +164,7 @@ void Partial::startPartial(dpoly *usePoly, const PatchCache *useCache, Partial * structurePosition = patchCache->structurePosition; play = true; - initKeyFollow(poly->freqnum); // Initialises noteVal, filtVal and realVal + initKeyFollow(poly->freqnum); // Initializes noteVal, filtVal and realVal #if MT32EMU_ACCURATENOTES == 0 noteLookup = &synth->tables.noteLookups[noteVal - LOWEST_NOTE]; #else diff --git a/audio/softsynth/mt32/synth.cpp b/audio/softsynth/mt32/synth.cpp index 5e74b262ae..322b864b6e 100644 --- a/audio/softsynth/mt32/synth.cpp +++ b/audio/softsynth/mt32/synth.cpp @@ -426,36 +426,36 @@ bool Synth::open(SynthProperties &useProp) { } } - printDebug("Initialising Timbre Bank A"); + printDebug("Initializing Timbre Bank A"); if (!initTimbres(controlROMMap->timbreAMap, controlROMMap->timbreAOffset, 0)) { return false; } - printDebug("Initialising Timbre Bank B"); + printDebug("Initializing Timbre Bank B"); if (!initTimbres(controlROMMap->timbreBMap, controlROMMap->timbreBOffset, 64)) { return false; } - printDebug("Initialising Timbre Bank R"); + printDebug("Initializing Timbre Bank R"); if (!initRhythmTimbres(controlROMMap->timbreRMap, controlROMMap->timbreRCount)) { return false; } - printDebug("Initialising Timbre Bank M"); - // CM-64 seems to initialise all bytes in this bank to 0. + printDebug("Initializing Timbre Bank M"); + // CM-64 seems to initialize all bytes in this bank to 0. memset(&mt32ram.timbres[128], 0, sizeof (mt32ram.timbres[128]) * 64); partialManager = new PartialManager(this); pcmWaves = new PCMWaveEntry[controlROMMap->pcmCount]; - printDebug("Initialising PCM List"); + printDebug("Initializing PCM List"); initPCMList(controlROMMap->pcmTable, controlROMMap->pcmCount); - printDebug("Initialising Rhythm Temp"); + printDebug("Initializing Rhythm Temp"); memcpy(mt32ram.rhythmSettings, &controlROMData[controlROMMap->rhythmSettings], controlROMMap->rhythmSettingsCount * 4); - printDebug("Initialising Patches"); + printDebug("Initializing Patches"); for (Bit8u i = 0; i < 128; i++) { PatchParam *patch = &mt32ram.patches[i]; patch->timbreGroup = i / 64; @@ -468,9 +468,9 @@ bool Synth::open(SynthProperties &useProp) { patch->dummy = 0; } - printDebug("Initialising System"); + printDebug("Initializing System"); // The MT-32 manual claims that "Standard pitch" is 442Hz. - mt32ram.system.masterTune = 0x40; // Confirmed on CM-64 as 0x4A, but SCUMM games use 0x40 and we don't want to initialise twice + mt32ram.system.masterTune = 0x40; // Confirmed on CM-64 as 0x4A, but SCUMM games use 0x40 and we don't want to initialize twice mt32ram.system.reverbMode = 0; // Confirmed mt32ram.system.reverbTime = 5; // Confirmed mt32ram.system.reverbLevel = 3; // Confirmed @@ -792,7 +792,7 @@ void Synth::writeSysex(unsigned char device, const Bit8u *sysex, Bit32u len) { for (;;) { // Find the appropriate memory region int regionNum; - const MemoryRegion *region = NULL; // Initialised to please compiler + const MemoryRegion *region = NULL; // Initialized to please compiler for (regionNum = 0; regionNum < NUM_REGIONS; regionNum++) { region = &memoryRegions[regionNum]; if (region->contains(addr)) { diff --git a/audio/softsynth/mt32/synth.h b/audio/softsynth/mt32/synth.h index edda446287..0ef2c9d135 100644 --- a/audio/softsynth/mt32/synth.h +++ b/audio/softsynth/mt32/synth.h @@ -263,7 +263,7 @@ public: Synth(); ~Synth(); - // Used to initialise the MT-32. Must be called before any other function. + // Used to initialize the MT-32. Must be called before any other function. // Returns true if initialization was sucessful, otherwise returns false. bool open(SynthProperties &useProp); diff --git a/audio/softsynth/mt32/tables.cpp b/audio/softsynth/mt32/tables.cpp index 25ee0436db..9fdb595467 100644 --- a/audio/softsynth/mt32/tables.cpp +++ b/audio/softsynth/mt32/tables.cpp @@ -203,7 +203,7 @@ void Tables::initEnvelopes(float samplerate) { void Tables::initMT32ConstantTables(Synth *synth) { int lf; - synth->printDebug("Initialising Pitch Tables"); + synth->printDebug("Initializing Pitch Tables"); for (lf = -108; lf <= 108; lf++) { tvfKeyfollowMult[lf + 108] = (int)(256 * powf(2.0f, (float)(lf / 24.0f))); //synth->printDebug("KT %d = %d", f, keytable[f+108]); @@ -668,7 +668,7 @@ bool Tables::initNotes(Synth *synth, PCMWaveEntry *pcmWaves, float rate, float m bool abort = false; synth->report(ReportType_progressInit, &progress); for (int f = LOWEST_NOTE; f <= HIGHEST_NOTE; f++) { - synth->printDebug("Initialising note %s%d", NoteNames[f % 12], (f / 12) - 2); + synth->printDebug("Initializing note %s%d", NoteNames[f % 12], (f / 12) - 2); NoteLookup *noteLookup = ¬eLookups[f - LOWEST_NOTE]; file = initNote(synth, noteLookup, (float)f, rate, masterTune, pcmWaves, file); progress = (f - LOWEST_NOTE + 1) / (float)NUM_NOTES; @@ -723,12 +723,12 @@ void Tables::freeNotes() { } } } - initialisedMasterTune = 0.0f; + initializedMasterTune = 0.0f; } Tables::Tables() { - initialisedSampleRate = 0.0f; - initialisedMasterTune = 0.0f; + initializedSampleRate = 0.0f; + initializedMasterTune = 0.0f; memset(¬eLookups, 0, sizeof(noteLookups)); } @@ -737,23 +737,23 @@ bool Tables::init(Synth *synth, PCMWaveEntry *pcmWaves, float sampleRate, float synth->printDebug("Bad sampleRate (%f <= 0.0f)", (double)sampleRate); return false; } - if (initialisedSampleRate == 0.0f) { + if (initializedSampleRate == 0.0f) { initMT32ConstantTables(synth); } - if (initialisedSampleRate != sampleRate) { + if (initializedSampleRate != sampleRate) { initFiltCoeff(sampleRate); initEnvelopes(sampleRate); for (int key = 12; key <= 108; key++) { initDep(&keyLookups[key - 12], (float)key); } } - if (initialisedSampleRate != sampleRate || initialisedMasterTune != masterTune) { + if (initializedSampleRate != sampleRate || initializedMasterTune != masterTune) { freeNotes(); if (!initNotes(synth, pcmWaves, sampleRate, masterTune)) { return false; } - initialisedSampleRate = sampleRate; - initialisedMasterTune = masterTune; + initializedSampleRate = sampleRate; + initializedMasterTune = masterTune; } return true; } diff --git a/audio/softsynth/mt32/tables.h b/audio/softsynth/mt32/tables.h index d9af5114b2..9950323e7b 100644 --- a/audio/softsynth/mt32/tables.h +++ b/audio/softsynth/mt32/tables.h @@ -69,8 +69,8 @@ struct KeyLookup { }; class Tables { - float initialisedSampleRate; - float initialisedMasterTune; + float initializedSampleRate; + float initializedMasterTune; void initMT32ConstantTables(Synth *synth); static Bit16s clampWF(Synth *synth, const char *n, float ampVal, double input); static File *initWave(Synth *synth, NoteLookup *noteLookup, float ampsize, float div2, File *file); -- cgit v1.2.3 From c60807cbb9dec063c0b00f8d6ffdb19e83db48f3 Mon Sep 17 00:00:00 2001 From: athrxx Date: Mon, 23 May 2011 16:37:58 +0200 Subject: FM-TOWNS AUDIO: Unlock internal mutex before calling imuse timer proc. --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 33 +++++++++------------- audio/softsynth/fmtowns_pc98/towns_audio.h | 9 +----- audio/softsynth/fmtowns_pc98/towns_midi.cpp | 4 ++- .../softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 29 +++++++++++-------- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 6 ++-- 5 files changed, 36 insertions(+), 45 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 5161871601..42a8252d53 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -103,12 +103,12 @@ private: class TownsAudioInterfaceInternal : public TownsPC98_FmSynth { public: - TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); + TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); ~TownsAudioInterfaceInternal(); - static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); + static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); static void releaseRef(); - bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver); + bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); bool init(); @@ -252,7 +252,8 @@ private: static const uint16 _pcmPhase2[]; }; -TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns), +TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) : + TownsPC98_FmSynth(mixer, kTypeTowns, externalMutexHandling), _fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0), _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver), _pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume), @@ -395,13 +396,13 @@ TownsAudioInterfaceInternal::~TownsAudioInterfaceInternal() { delete[] _pcmChan; } -TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) { +TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { _refCount++; if (_refCount == 1 && _refInstance == 0) - _refInstance = new TownsAudioInterfaceInternal(mixer, driver); + _refInstance = new TownsAudioInterfaceInternal(mixer, driver, externalMutexHandling); else if (_refCount < 2 || _refInstance == 0) error("TownsAudioInterfaceInternal::addNewRef(): Internal reference management failure"); - else if (!_refInstance->checkPluginDriver(driver)) + else if (!_refInstance->checkPluginDriver(driver, externalMutexHandling)) error("TownsAudioInterfaceInternal::addNewRef(): Plugin driver conflict"); return _refInstance; @@ -419,7 +420,7 @@ void TownsAudioInterfaceInternal::releaseRef() { } } -bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDriver *driver) { +bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { if (_refCount <= 1) return true; @@ -428,6 +429,7 @@ bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDri return false; } else { _drv = driver; + _externalMutex = externalMutexHandling; } return true; @@ -1669,7 +1671,6 @@ void TownsAudioInterfaceInternal::updateOutputVolumeInternal() { int volume = (int)(((float)(maxVol * 255) / 63.0f)); int balance = maxVol ? (int)( ( ((int)_outputLevel[13] * (_outputMute[13] ^ 1) - _outputLevel[12] * (_outputMute[12] ^ 1)) * 127) / (float)maxVol) : 0; - Common::StackLock lock(_mutex); g_system->getAudioCDManager()->setVolume(volume); g_system->getAudioCDManager()->setBalance(balance); @@ -1854,8 +1855,8 @@ void TownsAudio_WaveTable::clear() { data = 0; } -TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) { - _intf = TownsAudioInterfaceInternal::addNewRef(mixer, driver); +TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { + _intf = TownsAudioInterfaceInternal::addNewRef(mixer, driver, externalMutexHandling); } TownsAudioInterface::~TownsAudioInterface() { @@ -1887,12 +1888,4 @@ void TownsAudioInterface::setSoundEffectVolume(int volume) { void TownsAudioInterface::setSoundEffectChanMask(int mask) { _intf->setSoundEffectChanMask(mask); -} - -void TownsAudioInterface::lockInternal() { - _intf->mutexLock(); -} - -void TownsAudioInterface::unlockInternal() { - _intf->mutexUnlock(); -} +} \ No newline at end of file diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.h b/audio/softsynth/fmtowns_pc98/towns_audio.h index b00243f610..4af888f009 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.h +++ b/audio/softsynth/fmtowns_pc98/towns_audio.h @@ -35,7 +35,7 @@ public: class TownsAudioInterface { public: - TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); + TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); ~TownsAudioInterface(); bool init(); @@ -48,13 +48,6 @@ public: // The first 6 bits are the 6 fm channels. The next 8 bits are pcm channels. void setSoundEffectChanMask(int mask); - // These methods should not be needed in standard situations, since the mutex - // is handled internally. However, they may be required to avoid lockup situations - // if the code using this class has a mutex of its own (example for a lockup - // situation: imuse.cpp, line 78). - void lockInternal(); - void unlockInternal(); - private: TownsAudioInterfaceInternal *_intf; }; diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 00f0d43b98..4617b0555c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -834,7 +834,9 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = { MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _channels(0), _out(0), _chanState(0), _operatorLevelTable(0), _tickCounter1(0), _tickCounter2(0), _rand(1), _allocCurPos(0), _isOpen(false) { - _intf = new TownsAudioInterface(mixer, this); + // We set exteral mutex handling to true, since this driver is only suitable for use with the SCUMM engine + // which has its own mutex. This causes lockups which cannot always be avoided. + _intf = new TownsAudioInterface(mixer, this, true); _channels = new TownsMidiInputChannel*[32]; for (int i = 0; i < 32; i++) diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index 4336de9bdb..f4dd3cf6cc 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -851,7 +851,7 @@ void TownsPC98_FmSynthPercussionSource::advanceInput(RhtChannel *ins) { } #endif // DISABLE_PC98_RHYTHM_CHANNEL -TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) : +TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type, bool externalMutexHandling) : _mixer(mixer), _chanInternal(0), _ssg(0), #ifndef DISABLE_PC98_RHYTHM_CHANNEL @@ -861,7 +861,8 @@ TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) : _hasPercussion(type == kType86 ? true : false), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()), - _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _ready(false) { + _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), + _regProtectionFlag(false), _externalMutex(externalMutexHandling), _ready(false) { memset(&_timers[0], 0, sizeof(ChipTimer)); memset(&_timers[1], 0, sizeof(ChipTimer)); @@ -1147,7 +1148,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { bool locked = false; if (_ready) { - mutexLock(); + _mutex.lock(); locked = true; } @@ -1157,7 +1158,19 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { for (int i = 0; i < 2; i++) { if (_timers[i].enabled && _timers[i].cb) { if (!_timers[i].smpTillCb) { + + if (locked && _externalMutex) { + _mutex.unlock(); + locked = false; + } + (this->*_timers[i].cb)(); + + if (_ready && !locked && _externalMutex) { + _mutex.lock(); + locked = true; + } + _timers[i].smpTillCb = _timers[i].smpPerCb; _timers[i].smpTillCbRem += _timers[i].smpPerCbRem; @@ -1201,7 +1214,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { } if (locked) - mutexUnlock(); + _mutex.unlock(); delete[] tmpStart; @@ -1220,14 +1233,6 @@ int TownsPC98_FmSynth::getRate() const { return _mixer->getOutputRate(); } -void TownsPC98_FmSynth::mutexLock() { - _mutex.lock(); -} - -void TownsPC98_FmSynth::mutexUnlock() { - _mutex.unlock(); -} - void TownsPC98_FmSynth::deinit() { _ready = false; _mixer->stopHandle(_soundHandle); diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index 6ea9815a72..50a05f92a9 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -59,7 +59,7 @@ public: kType86 }; - TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type); + TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type, bool externalMutexHandling = false); virtual ~TownsPC98_FmSynth(); virtual bool init(); @@ -73,9 +73,6 @@ public: bool endOfData() const; int getRate() const; - void mutexLock(); - void mutexUnlock(); - protected: void deinit(); @@ -104,6 +101,7 @@ protected: const bool _hasPercussion; Common::Mutex _mutex; + bool _externalMutex; private: void generateTables(); -- cgit v1.2.3 From 7f8a69d6fc44ca5515a91f29ce5451c12f85daa5 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 29 May 2011 21:43:38 +0200 Subject: FM-TOWNS AUDIO: fix destructors (thread safety) --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 73 +++++++++++++--------- audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp | 2 + .../softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 8 ++- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 8 +-- 4 files changed, 57 insertions(+), 34 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 42a8252d53..efc9f9fb62 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -103,12 +103,11 @@ private: class TownsAudioInterfaceInternal : public TownsPC98_FmSynth { public: - TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); + TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); ~TownsAudioInterfaceInternal(); - static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); - static void releaseRef(); - bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); + static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); + static void releaseRef(TownsAudioInterface *owner); bool init(); @@ -122,6 +121,9 @@ public: void setSoundEffectChanMask(int mask); private: + bool assignPluginDriver(TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); + void removePluginDriver(TownsAudioInterface *owner); + void nextTickEx(int32 *buffer, uint32 bufferSize); void timerCallbackA(); @@ -239,6 +241,7 @@ private: int _pcmSfxChanMask; TownsAudioInterfacePluginDriver *_drv; + void *_drvOwner; bool _ready; static TownsAudioInterfaceInternal *_refInstance; @@ -252,10 +255,10 @@ private: static const uint16 _pcmPhase2[]; }; -TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) : +TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) : TownsPC98_FmSynth(mixer, kTypeTowns, externalMutexHandling), _fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0), - _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver), + _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver), _drvOwner(owner), _pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume), _outputVolumeFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0), _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _fmChanPlaying(0), @@ -388,6 +391,8 @@ TownsAudioInterfaceInternal::~TownsAudioInterfaceInternal() { _ready = false; deinit(); + Common::StackLock lock(_mutex); + delete[] _fmSaveReg[0]; delete[] _fmSaveReg[1]; delete[] _fmInstruments; @@ -396,45 +401,33 @@ TownsAudioInterfaceInternal::~TownsAudioInterfaceInternal() { delete[] _pcmChan; } -TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { +TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { _refCount++; if (_refCount == 1 && _refInstance == 0) - _refInstance = new TownsAudioInterfaceInternal(mixer, driver, externalMutexHandling); + _refInstance = new TownsAudioInterfaceInternal(mixer, owner, driver, externalMutexHandling); else if (_refCount < 2 || _refInstance == 0) error("TownsAudioInterfaceInternal::addNewRef(): Internal reference management failure"); - else if (!_refInstance->checkPluginDriver(driver, externalMutexHandling)) + else if (!_refInstance->assignPluginDriver(owner, driver, externalMutexHandling)) error("TownsAudioInterfaceInternal::addNewRef(): Plugin driver conflict"); return _refInstance; } -void TownsAudioInterfaceInternal::releaseRef() { +void TownsAudioInterfaceInternal::releaseRef(TownsAudioInterface *owner) { if (!_refCount) return; _refCount--; - if (!_refCount) { + if (_refCount) { + if (_refInstance) + _refInstance->removePluginDriver(owner); + } else { delete _refInstance; _refInstance = 0; } } -bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { - if (_refCount <= 1) - return true; - - if (_drv) { - if (driver && driver != _drv) - return false; - } else { - _drv = driver; - _externalMutex = externalMutexHandling; - } - - return true; -} - bool TownsAudioInterfaceInternal::init() { if (_ready) return true; @@ -501,6 +494,30 @@ void TownsAudioInterfaceInternal::setSoundEffectChanMask(int mask) { setVolumeChannelMasks(~mask, mask); } +bool TownsAudioInterfaceInternal::assignPluginDriver(TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { + if (_refCount <= 1) + return true; + + if (_drv) { + if (driver && driver != _drv) + return false; + } else { + Common::StackLock lock(_mutex); + _drv = driver; + _drvOwner = owner; + _externalMutex = externalMutexHandling; + } + + return true; +} + +void TownsAudioInterfaceInternal::removePluginDriver(TownsAudioInterface *owner) { + if (_drvOwner == owner) { + Common::StackLock lock(_mutex); + _drv = 0; + } +} + void TownsAudioInterfaceInternal::nextTickEx(int32 *buffer, uint32 bufferSize) { if (!_ready) return; @@ -1856,11 +1873,11 @@ void TownsAudio_WaveTable::clear() { } TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { - _intf = TownsAudioInterfaceInternal::addNewRef(mixer, driver, externalMutexHandling); + _intf = TownsAudioInterfaceInternal::addNewRef(mixer, this, driver, externalMutexHandling); } TownsAudioInterface::~TownsAudioInterface() { - TownsAudioInterfaceInternal::releaseRef(); + TownsAudioInterfaceInternal::releaseRef(this); _intf = 0; } diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp index ee20068e74..49fe97caf1 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp @@ -1054,6 +1054,8 @@ TownsPC98_AudioDriver::~TownsPC98_AudioDriver() { _ready = false; deinit(); + Common::StackLock lock(_mutex); + if (_channels) { for (int i = 0; i < _numChan; i++) delete _channels[i]; diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index f4dd3cf6cc..63007ba93c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -875,6 +875,8 @@ TownsPC98_FmSynth::~TownsPC98_FmSynth() { if (_ready) deinit(); + Common::StackLock lock(_mutex); + delete _ssg; #ifndef DISABLE_PC98_RHYTHM_CHANNEL delete _prc; @@ -1166,7 +1168,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { (this->*_timers[i].cb)(); - if (_ready && !locked && _externalMutex) { + if (!locked && _externalMutex) { _mutex.lock(); locked = true; } @@ -1240,6 +1242,10 @@ void TownsPC98_FmSynth::deinit() { _timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback; } +void TownsPC98_FmSynth::toggleRegProtection(bool prot) { + _regProtectionFlag = prot; +} + uint8 TownsPC98_FmSynth::readSSGStatus() { return _ssg->chanEnable(); } diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index 50a05f92a9..4f81fa9a5c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -80,17 +80,15 @@ protected: // additional output that has to be inserted into the buffer. virtual void nextTickEx(int32 *buffer, uint32 bufferSize) {} - void toggleRegProtection(bool prot) { - _regProtectionFlag = prot; - } + void toggleRegProtection(bool prot); uint8 readSSGStatus(); virtual void timerCallbackA() = 0; virtual void timerCallbackB() = 0; - // The audio driver can store and apply two different audio settings + // The audio driver can store and apply two different volume settings // (usually for music and sound effects). The channel mask will determine - // which channels get effected by the setting. The first bits will be + // which channels get effected by which setting. The first bits will be // the normal fm channels, the next bits the ssg channels and the final // bit the rhythm channel. void setVolumeIntern(int volA, int volB); -- cgit v1.2.3 From bea6858953dbcde1c6dc88345631f14d9b550ef8 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Tue, 31 May 2011 12:06:14 +0100 Subject: AUDIO: Fix GCC Compilation Warning in FM-Towns Softsynth. --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index efc9f9fb62..786e3ee1d2 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -1905,4 +1905,4 @@ void TownsAudioInterface::setSoundEffectVolume(int volume) { void TownsAudioInterface::setSoundEffectChanMask(int mask) { _intf->setSoundEffectChanMask(mask); -} \ No newline at end of file +} -- cgit v1.2.3