diff options
author | Max Horn | 2004-10-17 17:49:45 +0000 |
---|---|---|
committer | Max Horn | 2004-10-17 17:49:45 +0000 |
commit | 267144e69c09862c230506ec1550b6b1ac8437f3 (patch) | |
tree | 0115f95a43c141541c2f05bf209a9d9cfe1db910 /backends/midi | |
parent | 649eb19a3ed45dbea8b2796a57190ff18534fffe (diff) | |
download | scummvm-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.cpp | 83 | ||||
-rw-r--r-- | backends/midi/emumidi.h | 96 | ||||
-rw-r--r-- | backends/midi/ym2612.cpp | 68 |
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) { |