aboutsummaryrefslogtreecommitdiff
path: root/backends/midi
diff options
context:
space:
mode:
authorMax Horn2004-10-17 17:49:45 +0000
committerMax Horn2004-10-17 17:49:45 +0000
commit267144e69c09862c230506ec1550b6b1ac8437f3 (patch)
tree0115f95a43c141541c2f05bf209a9d9cfe1db910 /backends/midi
parent649eb19a3ed45dbea8b2796a57190ff18534fffe (diff)
downloadscummvm-rg350-267144e69c09862c230506ec1550b6b1ac8437f3.tar.gz
scummvm-rg350-267144e69c09862c230506ec1550b6b1ac8437f3.tar.bz2
scummvm-rg350-267144e69c09862c230506ec1550b6b1ac8437f3.zip
added MidiDriver_Emulated base class used by the adlib & ym2612 midi 'drivers'
svn-id: r15589
Diffstat (limited to 'backends/midi')
-rw-r--r--backends/midi/adlib.cpp83
-rw-r--r--backends/midi/emumidi.h96
-rw-r--r--backends/midi/ym2612.cpp68
3 files changed, 119 insertions, 128 deletions
diff --git a/backends/midi/adlib.cpp b/backends/midi/adlib.cpp
index f702ee6532..48c62e1f5d 100644
--- a/backends/midi/adlib.cpp
+++ b/backends/midi/adlib.cpp
@@ -18,15 +18,9 @@
* $Header$
*/
-#include "stdafx.h"
-#include "sound/audiostream.h"
-#include "sound/mididrv.h"
-#include "sound/fmopl.h"
-#include "sound/mixer.h"
+#include "emumidi.h"
#include "common/util.h"
-
-#define BASE_FREQ 250
-#define FIXP_SHIFT 16
+#include "sound/fmopl.h"
#ifdef DEBUG_ADLIB
static int tick;
@@ -544,7 +538,7 @@ static void create_lookup_table() {
//
////////////////////////////////////////
-class MidiDriver_ADLIB : public AudioStream, public MidiDriver {
+class MidiDriver_ADLIB : public MidiDriver_Emulated {
friend class AdlibPart;
friend class AdlibPercussionChannel;
@@ -554,51 +548,30 @@ public:
int open();
void close();
void send(uint32 b);
- void send (byte channel, uint32 b); // Supports higher than channel 15
+ void send(byte channel, uint32 b); // Supports higher than channel 15
uint32 property(int prop, uint32 param);
void setPitchBendRange(byte channel, uint range);
void sysEx_customInstrument(byte channel, uint32 type, byte *instr);
- void setTimerCallback(void *timer_param, Timer::TimerProc timer_proc);
- uint32 getBaseTempo() {
- return 1000000 / BASE_FREQ;
- }
-
MidiChannel *allocateChannel();
MidiChannel *getPercussionChannel() { return &_percussion; } // Percussion partially supported
+
// AudioStream API
- int readBuffer(int16 *buffer, const int numSamples) {
- memset(buffer, 0, 2 * numSamples); // FIXME
- generate_samples(buffer, numSamples);
- return numSamples;
- }
- int16 read() {
- error("ProcInputStream::read not supported");
- }
bool isStereo() const { return false; }
- bool endOfData() const { return false; }
-
int getRate() const { return _mixer->getOutputRate(); }
private:
- bool _isOpen;
bool _game_SmallHeader;
FM_OPL *_opl;
byte *_adlib_reg_cache;
- SoundMixer *_mixer;
-
- Timer::TimerProc _timer_proc;
- void *_timer_param;
int _adlib_timer_counter;
uint16 channel_table_2[9];
int _voice_index;
- int _next_tick;
- int _samples_per_tick;
int _timer_p;
int _timer_q;
uint16 curnote_table[9];
@@ -820,20 +793,15 @@ void AdlibPercussionChannel::noteOn(byte note, byte velocity) {
// MidiDriver method implementations
MidiDriver_ADLIB::MidiDriver_ADLIB(SoundMixer *mixer)
- : _mixer(mixer) {
+ : MidiDriver_Emulated(mixer) {
uint i;
- _isOpen = false;
_game_SmallHeader = false;
_adlib_reg_cache = 0;
- _timer_proc = 0;
- _timer_param = 0;
-
_adlib_timer_counter = 0;
_voice_index = 0;
- _next_tick = 0;
for (i = 0; i < ARRAYSIZE(curnote_table); ++i) {
curnote_table[i] = 0;
}
@@ -849,7 +817,8 @@ MidiDriver_ADLIB::MidiDriver_ADLIB(SoundMixer *mixer)
int MidiDriver_ADLIB::open() {
if (_isOpen)
return MERR_ALREADY_OPEN;
- _isOpen = true;
+
+ MidiDriver_Emulated::open();
int i;
AdlibVoice *voice;
@@ -869,8 +838,6 @@ int MidiDriver_ADLIB::open() {
adlib_write(0xBD, 0x00);
create_lookup_table();
- _samples_per_tick = (getRate() << FIXP_SHIFT) / BASE_FREQ;
-
_mixer->setupPremix(this);
return 0;
@@ -879,6 +846,10 @@ int MidiDriver_ADLIB::open() {
void MidiDriver_ADLIB::close() {
if (!_isOpen)
return;
+ _isOpen = false;
+
+ // Detach the premix callback handler
+ _mixer->setupPremix(0);
uint i;
for (i = 0; i < ARRAYSIZE(_voices); ++i) {
@@ -886,15 +857,10 @@ void MidiDriver_ADLIB::close() {
mc_off(&_voices [i]);
}
- // Detach the premix callback handler
- _mixer->setupPremix(0);
-
// Turn off the OPL emulation
// YM3812Shutdown();
free(_adlib_reg_cache);
-
- _isOpen = false;
}
void MidiDriver_ADLIB::send (uint32 b) {
@@ -976,11 +942,6 @@ void MidiDriver_ADLIB::sysEx_customInstrument(byte channel, uint32 type, byte *i
_parts[channel].sysEx_customInstrument(type, instr);
}
-void MidiDriver_ADLIB::setTimerCallback(void *timer_param, Timer::TimerProc timer_proc) {
- _timer_proc = timer_proc;
- _timer_param = timer_param;
-}
-
MidiChannel *MidiDriver_ADLIB::allocateChannel() {
AdlibPart *part;
uint i;
@@ -1013,24 +974,8 @@ void MidiDriver_ADLIB::adlib_write(byte port, byte value) {
}
void MidiDriver_ADLIB::generate_samples(int16 *data, int len) {
- int step;
-
- do {
- step = len;
- if (step > (_next_tick >> FIXP_SHIFT))
- step = (_next_tick >> FIXP_SHIFT);
- YM3812UpdateOne(_opl, data, step);
-
- _next_tick -= step << FIXP_SHIFT;
- if (!(_next_tick >> FIXP_SHIFT)) {
- if (_timer_proc)
- (*_timer_proc)(_timer_param);
- on_timer();
- _next_tick += _samples_per_tick;
- }
- data += step;
- len -= step;
- } while (len);
+ memset(data, 0, sizeof(int16) * len);
+ YM3812UpdateOne(_opl, data, len);
}
void MidiDriver_ADLIB::on_timer() {
diff --git a/backends/midi/emumidi.h b/backends/midi/emumidi.h
new file mode 100644
index 0000000000..e5daa40647
--- /dev/null
+++ b/backends/midi/emumidi.h
@@ -0,0 +1,96 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "sound/audiostream.h"
+#include "sound/mididrv.h"
+#include "sound/mixer.h"
+
+#define BASE_FREQ 250
+#define FIXP_SHIFT 16
+
+class MidiDriver_Emulated : public AudioStream, public MidiDriver {
+protected:
+ bool _isOpen;
+ SoundMixer *_mixer;
+
+private:
+ Timer::TimerProc _timer_proc;
+ void *_timer_param;
+
+ int _next_tick;
+ int _samples_per_tick;
+
+protected:
+ virtual void generate_samples(int16 *buf, int len) = 0;
+
+public:
+ MidiDriver_Emulated(SoundMixer *mixer) : _mixer(mixer) {
+ _isOpen = false;
+
+ _timer_proc = 0;
+ _timer_param = 0;
+
+ _next_tick = 0;
+ _samples_per_tick = 0;
+ }
+
+ int open() {
+ _isOpen = true;
+ _samples_per_tick = (getRate() << FIXP_SHIFT) / BASE_FREQ;
+ }
+
+ void setTimerCallback(void *timer_param, Timer::TimerProc timer_proc) {
+ _timer_proc = timer_proc;
+ _timer_param = timer_param;
+ }
+
+ uint32 getBaseTempo() { return 1000000 / BASE_FREQ; }
+
+
+ // AudioStream API
+ int readBuffer(int16 *data, const int numSamples) {
+ const int stereoFactor = isStereo() ? 2 : 1;
+ int len = numSamples / stereoFactor;
+ int step;
+
+ do {
+ step = len;
+ if (step > (_next_tick >> FIXP_SHIFT))
+ step = (_next_tick >> FIXP_SHIFT);
+ generate_samples(data, step);
+
+ _next_tick -= step << FIXP_SHIFT;
+ if (!(_next_tick >> FIXP_SHIFT)) {
+ if (_timer_proc)
+ (*_timer_proc)(_timer_param);
+ _next_tick += _samples_per_tick;
+ }
+ data += step * stereoFactor;
+ len -= step;
+ } while (len);
+
+ return numSamples;
+ }
+ int16 read() {
+ error("ProcInputStream::read not supported");
+ }
+ bool endOfData() const { return false; }
+};
diff --git a/backends/midi/ym2612.cpp b/backends/midi/ym2612.cpp
index 50f786b011..6f0e6aeece 100644
--- a/backends/midi/ym2612.cpp
+++ b/backends/midi/ym2612.cpp
@@ -22,11 +22,7 @@
* $Header$
*/
-#include "stdafx.h"
-#include "common/util.h"
-#include "sound/audiostream.h"
-#include "sound/mididrv.h"
-#include "sound/mixer.h"
+#include "emumidi.h"
#include <math.h>
@@ -37,9 +33,6 @@
//
////////////////////////////////////////
-#define BASE_FREQ 250
-#define FIXP_SHIFT 16
-
static int *sintbl = 0;
static int *powtbl = 0;
static int *frequencyTable = 0;
@@ -158,20 +151,13 @@ public:
void sysEx_customInstrument(uint32 type, byte *instr);
};
-class MidiDriver_YM2612 : public AudioStream, public MidiDriver {
+class MidiDriver_YM2612 : public MidiDriver_Emulated {
protected:
MidiChannel_YM2612 *_channel[16];
int _next_voice;
int _volume;
- bool _isOpen;
- SoundMixer *_mixer;
- Timer::TimerProc _timer_proc;
- void *_timer_param;
- int _next_tick;
- int _samples_per_tick;
-
protected:
static void createLookupTables();
void nextTick(int16 *buf1, int buflen);
@@ -193,25 +179,12 @@ public:
void setPitchBendRange(byte channel, uint range) { }
void sysEx(byte *msg, uint16 length);
- void setTimerCallback(void *timer_param, Timer::TimerProc timer_proc);
- uint32 getBaseTempo() { return 1000000 / BASE_FREQ; }
-
MidiChannel *allocateChannel() { return 0; }
MidiChannel *getPercussionChannel() { return 0; }
// AudioStream API
- int readBuffer(int16 *buffer, const int numSamples) {
- memset(buffer, 0, 2 * numSamples); // FIXME
- generate_samples(buffer, numSamples / 2);
- return numSamples;
- }
- int16 read() {
- error("ProcInputStream::read not supported");
- }
bool isStereo() const { return true; }
- bool endOfData() const { return false; }
-
int getRate() const { return _mixer->getOutputRate(); }
};
@@ -736,13 +709,8 @@ void MidiChannel_YM2612::rate(uint16 r) {
//
////////////////////////////////////////
-MidiDriver_YM2612::MidiDriver_YM2612(SoundMixer *mixer) :
-_mixer(mixer) {
- _isOpen = false;
- _timer_proc = 0;
- _timer_param = 0;
- _next_tick = 0;
- _samples_per_tick = (getRate() << FIXP_SHIFT) / BASE_FREQ;
+MidiDriver_YM2612::MidiDriver_YM2612(SoundMixer *mixer)
+ : MidiDriver_Emulated(mixer) {
_next_voice = 0;
createLookupTables();
@@ -769,8 +737,10 @@ MidiDriver_YM2612::~MidiDriver_YM2612() {
int MidiDriver_YM2612::open() {
if (_isOpen)
return MERR_ALREADY_OPEN;
+
+ MidiDriver_Emulated::open();
+
_mixer->setupPremix(this);
- _isOpen = true;
return 0;
}
@@ -783,11 +753,6 @@ void MidiDriver_YM2612::close() {
_mixer->setupPremix(0);
}
-void MidiDriver_YM2612::setTimerCallback(void *timer_param, Timer::TimerProc timer_proc) {
- _timer_proc = timer_proc;
- _timer_param = timer_param;
-}
-
void MidiDriver_YM2612::send(uint32 b) {
send(b & 0xF, b & 0xFFFFFFF0);
}
@@ -838,23 +803,8 @@ void MidiDriver_YM2612::sysEx(byte *msg, uint16 length) {
}
void MidiDriver_YM2612::generate_samples(int16 *data, int len) {
- int step;
-
- do {
- step = len;
- if (step > (_next_tick >> FIXP_SHIFT))
- step = (_next_tick >> FIXP_SHIFT);
- nextTick(data, step);
-
- _next_tick -= step << FIXP_SHIFT;
- if (!(_next_tick >> FIXP_SHIFT)) {
- if (_timer_proc)
- (*_timer_proc)(_timer_param);
- _next_tick += _samples_per_tick;
- }
- data += step * 2; // Stereo means * 2
- len -= step;
- } while (len);
+ memset(data, 0, 2 * sizeof(int16) * len);
+ nextTick(data, len);
}
void MidiDriver_YM2612::nextTick(int16 *buf1, int buflen) {