Preliminary preparation for new YM2612 FM emulator.

All the hooks are in, but actual implementation
needs to be checked for portability.

svn-id: r10615
This commit is contained in:
Jamieson Christian 2003-10-05 15:36:52 +00:00
parent 7174a32c8e
commit a722d0601e
16 changed files with 154 additions and 60 deletions

1
README
View file

@ -570,6 +570,7 @@ choices of output, depending on your operating system and configuration.
adlib - Uses internal Adlib Emulation (default) adlib - Uses internal Adlib Emulation (default)
pcjr - Uses internal PCjr Emulation pcjr - Uses internal PCjr Emulation
pcspk - Uses internal PC Speaker Emulation pcspk - Uses internal PC Speaker Emulation
towns - Uses FM-Towns YM2612 Emulation
windows - Windows MIDI. Uses built-in sequencer, for Windows users windows - Windows MIDI. Uses built-in sequencer, for Windows users
seq - Uses /dev/sequencer for MIDI, *nix users. See below. seq - Uses /dev/sequencer for MIDI, *nix users. See below.
qt - Quicktime sound, for Macintosh users. qt - Quicktime sound, for Macintosh users.

31
backends/midi/ym2612.cpp Normal file
View file

@ -0,0 +1,31 @@
/* ScummVM - Scumm Interpreter
* Copyright (C) 2001-2003 The ScummVM project
*
* YM2612 tone generation code written by Tomoaki Hayasaka.
* Used under the terms of the GNU General Public License.
* Adpated to ScummVM by Jamieson Christian.
*
* 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$
*/
// Real implementation coming soon! :)
#include "sound/mididrv.h"
MidiDriver *MidiDriver_YM2612_create(SoundMixer *mixer) {
return 0;
}

View file

@ -11,7 +11,8 @@ MODULE_OBJS := \
backends/midi/quicktime.o \ backends/midi/quicktime.o \
backends/midi/seq.o \ backends/midi/seq.o \
backends/midi/alsa.o \ backends/midi/alsa.o \
backends/midi/windows.o backends/midi/windows.o \
backends/midi/ym2612.o
MODULE_DIRS += \ MODULE_DIRS += \
backends \ backends \

View file

@ -676,12 +676,15 @@ bool GameDetector::detectMain() {
if (_game.midi & MDT_PREFER_NATIVE) if (_game.midi & MDT_PREFER_NATIVE)
_midi_driver = getMidiDriverType(); _midi_driver = getMidiDriverType();
else else
_midi_driver = MD_ADLIB; _midi_driver = MD_TOWNS;
} }
bool nativeMidiDriver = bool nativeMidiDriver =
(_midi_driver != MD_NULL && _midi_driver != MD_ADLIB && (_midi_driver != MD_NULL && _midi_driver != MD_ADLIB &&
_midi_driver != MD_PCSPK && _midi_driver != MD_PCJR); _midi_driver != MD_PCSPK && _midi_driver != MD_PCJR &&
_midi_driver != MD_TOWNS);
if (nativeMidiDriver && !(_game.midi & MDT_NATIVE)) if (nativeMidiDriver && !(_game.midi & MDT_NATIVE))
_midi_driver = MD_TOWNS;
if (_midi_driver == MD_TOWNS && !(_game.midi & MDT_TOWNS))
_midi_driver = MD_ADLIB; _midi_driver = MD_ADLIB;
if (_midi_driver == MD_ADLIB && !(_game.midi & MDT_ADLIB)) if (_midi_driver == MD_ADLIB && !(_game.midi & MDT_ADLIB))
_midi_driver = MD_PCJR; _midi_driver = MD_PCJR;
@ -770,12 +773,15 @@ MidiDriver *GameDetector::createMidi() {
switch(drv) { switch(drv) {
case MD_NULL: return MidiDriver_NULL_create(); case MD_NULL: return MidiDriver_NULL_create();
// In the case of Adlib, we won't specify anything. // In the case of Adlib, we won't specify anything.
// IMuse is designed to set up its own Adlib driver // IMuse is designed to set up its own Adlib driver
// if need be, and we only have to specify a native // if need be, and we only have to specify a native
// driver. // driver.
case MD_ADLIB: return NULL; case MD_ADLIB: return NULL;
case MD_TOWNS: return MidiDriver_YM2612_create(g_engine->_mixer);
// Right now PC Speaker and PCjr are handled // Right now PC Speaker and PCjr are handled
// outside the MidiDriver architecture, so // outside the MidiDriver architecture, so
// don't create anything for now. // don't create anything for now.

View file

@ -70,8 +70,9 @@ enum MidiDriverType {
MDT_NONE = 0, MDT_NONE = 0,
MDT_PCSPK = 1, // MD_PCSPK and MD_PCJR MDT_PCSPK = 1, // MD_PCSPK and MD_PCJR
MDT_ADLIB = 2, // MD_ADLIB MDT_ADLIB = 2, // MD_ADLIB
MDT_NATIVE = 4, // Everything else MDT_TOWNS = 4, // MD_TOWNS
MDT_PREFER_NATIVE = 8 MDT_NATIVE = 8, // Everything else
MDT_PREFER_NATIVE = 16
}; };
struct TargetSettings { struct TargetSettings {

View file

@ -540,6 +540,10 @@ SOURCE=..\..\backends\midi\null.cpp
SOURCE=..\..\backends\midi\windows.cpp SOURCE=..\..\backends\midi\windows.cpp
# End Source File # End Source File
# Begin Source File
SOURCE=..\..\backends\midi\ym2612.cpp
# End Source File
# End Group # End Group
# End Group # End Group
# End Group # End Group

View file

@ -355,6 +355,9 @@
<File <File
RelativePath="..\..\backends\midi\windows.cpp"> RelativePath="..\..\backends\midi\windows.cpp">
</File> </File>
<File
RelativePath="..\..\backends\midi\ym2612.cpp">
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter

View file

@ -54,6 +54,7 @@ _initialized(false),
_tempoFactor(0), _tempoFactor(0),
_player_limit(ARRAYSIZE(_players)), _player_limit(ARRAYSIZE(_players)),
_recycle_players(false), _recycle_players(false),
_direct_passthrough(false),
_queue_end(0), _queue_end(0),
_queue_pos(0), _queue_pos(0),
_queue_sound(0), _queue_sound(0),
@ -250,7 +251,7 @@ bool IMuseInternal::startSound(int sound) {
return false; return false;
player->clear(); player->clear();
return player->startSound(sound, driver); return player->startSound(sound, driver, _direct_passthrough);
} }
@ -1117,10 +1118,14 @@ uint32 IMuseInternal::property(int prop, uint32 value) {
break; break;
case IMuse::PROP_RECYCLE_PLAYERS: case IMuse::PROP_RECYCLE_PLAYERS:
if (value > 0 && value <= ARRAYSIZE(_players))
_recycle_players = (value != 0); _recycle_players = (value != 0);
break; break;
case IMuse::PROP_DIRECT_PASSTHROUGH:
_direct_passthrough = (value != 0);
break;
} }
return 0; return 0;
} }

View file

@ -51,12 +51,13 @@ public:
~IMuse(); ~IMuse();
enum { enum {
PROP_TEMPO_BASE = 1, PROP_TEMPO_BASE,
PROP_NATIVE_MT32 = 2, PROP_NATIVE_MT32,
PROP_MULTI_MIDI = 3, PROP_MULTI_MIDI,
PROP_OLD_ADLIB_INSTRUMENTS = 4, PROP_OLD_ADLIB_INSTRUMENTS,
PROP_LIMIT_PLAYERS = 5, PROP_LIMIT_PLAYERS,
PROP_RECYCLE_PLAYERS = 6 PROP_RECYCLE_PLAYERS,
PROP_DIRECT_PASSTHROUGH
}; };
void on_timer(MidiDriver *midi); void on_timer(MidiDriver *midi);

View file

@ -60,10 +60,6 @@ class ScummEngine;
#define TICKS_PER_BEAT 480 #define TICKS_PER_BEAT 480
#define IMUSE_SYSEX_ID 0x7D
#define ROLAND_SYSEX_ID 0x41
#define PERCUSSION_CHANNEL 9
#define TRIGGER_ID 0 #define TRIGGER_ID 0
#define COMMAND_ID 1 #define COMMAND_ID 1
@ -158,6 +154,7 @@ protected:
protected: protected:
MidiDriver *_midi; MidiDriver *_midi;
MidiParser *_parser; MidiParser *_parser;
bool _passThrough; // Only respond to EOT, all else direct to MidiDriver
Part *_parts; Part *_parts;
bool _active; bool _active;
@ -259,7 +256,7 @@ public:
void setSpeed(byte speed); void setSpeed(byte speed);
int setTranspose(byte relative, int b); int setTranspose(byte relative, int b);
int setVolume(byte vol); int setVolume(byte vol);
bool startSound(int sound, MidiDriver *midi); bool startSound(int sound, MidiDriver *midi, bool passThrough);
int getMusicTimer() const; int getMusicTimer() const;
public: public:
@ -368,6 +365,7 @@ protected:
int _player_limit; // Limits how many simultaneous music tracks are played int _player_limit; // Limits how many simultaneous music tracks are played
bool _recycle_players; // Can we stop a player in order to start another one? bool _recycle_players; // Can we stop a player in order to start another one?
bool _direct_passthrough; // Pass data direct to MidiDriver (no interactivity)
uint _queue_end, _queue_pos, _queue_sound; uint _queue_end, _queue_pos, _queue_sound;
byte _queue_adding; byte _queue_adding;

View file

@ -39,6 +39,11 @@ namespace Scumm {
// //
//////////////////////////////////////// ////////////////////////////////////////
#define IMUSE_SYSEX_ID 0x7D
#define YM2612_SYSEX_ID 0x7C
#define ROLAND_SYSEX_ID 0x41
#define PERCUSSION_CHANNEL 9
extern MidiParser *MidiParser_createRO(); extern MidiParser *MidiParser_createRO();
extern MidiParser *MidiParser_createEUP(); extern MidiParser *MidiParser_createEUP();
@ -85,7 +90,7 @@ Player::~Player() {
} }
} }
bool Player::startSound(int sound, MidiDriver *midi) { bool Player::startSound(int sound, MidiDriver *midi, bool passThrough) {
void *ptr; void *ptr;
int i; int i;
@ -111,6 +116,7 @@ bool Player::startSound(int sound, MidiDriver *midi) {
_pan = 0; _pan = 0;
_transpose = 0; _transpose = 0;
_detune = 0; _detune = 0;
_passThrough = passThrough;
for (i = 0; i < ARRAYSIZE(_parameterFaders); ++i) for (i = 0; i < ARRAYSIZE(_parameterFaders); ++i)
_parameterFaders[i].init(); _parameterFaders[i].init();
@ -152,8 +158,11 @@ void Player::clear() {
debug (0, "Stopping music %d", _id); debug (0, "Stopping music %d", _id);
#endif #endif
if (_parser) if (_parser) {
_parser->unloadMusic(); _parser->unloadMusic();
delete _parser;
_parser = 0;
}
uninit_parts(); uninit_parts();
_se->ImFireAllTriggers(_id); _se->ImFireAllTriggers(_id);
_active = false; _active = false;
@ -224,6 +233,11 @@ void Player::setSpeed(byte speed) {
} }
void Player::send(uint32 b) { void Player::send(uint32 b) {
if (_passThrough) {
_midi->send (b);
return;
}
byte cmd = (byte)(b & 0xF0); byte cmd = (byte)(b & 0xF0);
byte chan = (byte)(b & 0x0F); byte chan = (byte)(b & 0x0F);
byte param1 = (byte)((b >> 8) & 0xFF); byte param1 = (byte)((b >> 8) & 0xFF);
@ -333,8 +347,12 @@ void Player::sysEx(byte *p, uint16 len) {
byte buf[128]; byte buf[128];
Part *part; Part *part;
if (_passThrough) {
_midi->sysEx (p, len);
return;
}
// Check SysEx manufacturer. // Check SysEx manufacturer.
// Roland is 0x41
a = *p++; a = *p++;
--len; --len;
if (a != IMUSE_SYSEX_ID) { if (a != IMUSE_SYSEX_ID) {
@ -346,6 +364,9 @@ void Player::sysEx(byte *p, uint16 len) {
if (part->clearToTransmit()) if (part->clearToTransmit())
part->_instrument.send(part->_mc); part->_instrument.send(part->_mc);
} }
} else if (a == YM2612_SYSEX_ID) {
// FM-Towns custom instrument definition
_midi->sysEx_customInstrument (p[0], 'EUP ', p + 1);
} else { } else {
warning("Unknown SysEx manufacturer 0x%02X", (int) a); warning("Unknown SysEx manufacturer 0x%02X", (int) a);
} }
@ -1124,10 +1145,8 @@ uint32 Player::getBaseTempo() {
} }
void Player::metaEvent(byte type, byte *msg, uint16 len) { void Player::metaEvent(byte type, byte *msg, uint16 len) {
if (type == 0x2F) { if (type == 0x2F)
_parser->unloadMusic();
clear(); clear();
}
} }

View file

@ -32,6 +32,8 @@ namespace Scumm {
*/ */
class MidiParser_EUP : public MidiParser { class MidiParser_EUP : public MidiParser {
protected: protected:
byte _instruments[6][50]; // Two extra bytes for SysEx ID and channel #
byte _channel_instr[16];
struct { struct {
byte *enable; byte *enable;
int8 *channel; int8 *channel;
@ -69,14 +71,22 @@ void MidiParser_EUP::parseNextEvent (EventInfo &info) {
// program changes to get a reasonable "one-size- // program changes to get a reasonable "one-size-
// fits-all" sound until we actually support the // fits-all" sound until we actually support the
// FM synthesis capabilities of FM Towns. // FM synthesis capabilities of FM Towns.
if (_presend) { for (; _presend < 32; ++_presend) {
--_presend; if (_channel_instr[_presend >> 1] == 0xFF) continue;
info.start = pos; info.start = pos;
info.delta = 0; info.delta = 0;
info.event = ((_presend & 1) ? 0xB0 : 0xC0) | (_presend >> 1); if (_presend & 1) {
info.basic.param1 = ((_presend & 1) ? 7 : 0x38); info.event = 0xB0;
info.basic.param2 = ((_presend & 1) ? 127 : 0); info.basic.param1 = 7;
_presend = (_presend + 2) % 32; info.basic.param2 = 127;
} else {
byte *data = &_instruments[_channel_instr[_presend >> 1]][0];
data[1] = _presend >> 1;
info.event = 0xF0;
info.ext.data = data;
info.length = 48;
}
++_presend;
return; return;
} }
@ -89,7 +99,17 @@ void MidiParser_EUP::parseNextEvent (EventInfo &info) {
channel = cmd & 0x0F; channel = cmd & 0x0F;
uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _base_tick; uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _base_tick;
int note = (int) pos[4] + _presets.transpose[preset]; int note = (int) pos[4] + _presets.transpose[preset];
int volume = (int) pos[5] + _presets.volume[preset]; int volume = (int) pos[5];
// HACK: Loom-Towns distaff tracks seem to
// contain zero-volume note events, so change
// those to full volume.
if (!volume)
volume = 127;
volume += _presets.volume[preset];
if (volume > 127)
volume = 127;
else if (volume < 0)
volume = 0;
pos += 6; pos += 6;
if (_presets.enable[preset]) { if (_presets.enable[preset]) {
uint16 duration = pos[1] | (pos[2] << 4); uint16 duration = pos[1] | (pos[2] << 4);
@ -148,7 +168,12 @@ bool MidiParser_EUP::loadMusic (byte *data, uint32 size) {
} }
byte numInstruments = pos[16]; byte numInstruments = pos[16];
pos += (16 + 2 + numInstruments * 48); pos += 16 + 2;
for (int i = 0; i < numInstruments; ++i) {
_instruments[i][0] = 0x7C;
memcpy (&_instruments[i][2], pos, 48);
pos += 48;
}
// Load the prest pointers // Load the prest pointers
_presets.enable = pos; _presets.enable = pos;
@ -161,6 +186,10 @@ bool MidiParser_EUP::loadMusic (byte *data, uint32 size) {
pos += 32; pos += 32;
pos += 8; // Unknown bytes pos += 8; // Unknown bytes
for (i = 0; i < 16; ++i)
_channel_instr[i] = 0xFF;
for (i = 0; i < 6; ++i)
_channel_instr[pos[i]] = i;
pos += 6; // Instrument-to-channel mapping (not supported yet) pos += 6; // Instrument-to-channel mapping (not supported yet)
pos += 4; // Skip the music size for now. pos += 4; // Skip the music size for now.
pos++; // Unknown byte pos++; // Unknown byte
@ -183,7 +212,7 @@ bool MidiParser_EUP::loadMusic (byte *data, uint32 size) {
void MidiParser_EUP::resetTracking() { void MidiParser_EUP::resetTracking() {
MidiParser::resetTracking(); MidiParser::resetTracking();
_presend = 1; _presend = 0;
_base_tick = 0; _base_tick = 0;
} }

View file

@ -92,15 +92,15 @@ static const TargetSettings scumm_settings[] = {
/* Scumm Version 3 */ /* Scumm Version 3 */
{"indy3EGA", "Indiana Jones and the Last Crusade", GID_INDY3, 3, MDT_PCSPK | MDT_ADLIB, {"indy3EGA", "Indiana Jones and the Last Crusade", GID_INDY3, 3, MDT_PCSPK | MDT_ADLIB,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_USE_KEY | GF_16COLOR | GF_OLD_BUNDLE, "00.LFL"}, GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_USE_KEY | GF_16COLOR | GF_OLD_BUNDLE, "00.LFL"},
{"indy3Towns", "Indiana Jones and the Last Crusade (FM Towns)", GID_INDY3, 3, MDT_ADLIB, {"indy3Towns", "Indiana Jones and the Last Crusade (FM Towns)", GID_INDY3, 3, MDT_TOWNS,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FEW_LOCALS | GF_FMTOWNS | GF_AUDIOTRACKS, "00.LFL"}, GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FEW_LOCALS | GF_FMTOWNS | GF_AUDIOTRACKS, "00.LFL"},
{"indy3", "Indiana Jones and the Last Crusade (256)", GID_INDY3, 3, MDT_PCSPK | MDT_ADLIB, {"indy3", "Indiana Jones and the Last Crusade (256)", GID_INDY3, 3, MDT_PCSPK | MDT_ADLIB,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FEW_LOCALS, "00.LFL"}, GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FEW_LOCALS, "00.LFL"},
{"zak256", "Zak McKracken and the Alien Mindbenders (256)", GID_ZAK256, 3, MDT_ADLIB, {"zak256", "Zak McKracken and the Alien Mindbenders (256)", GID_ZAK256, 3, MDT_TOWNS,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FMTOWNS | GF_AUDIOTRACKS, "00.LFL"}, GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FMTOWNS | GF_AUDIOTRACKS, "00.LFL"},
{"loom", "Loom", GID_LOOM, 3, MDT_PCSPK | MDT_ADLIB | MDT_NATIVE, {"loom", "Loom", GID_LOOM, 3, MDT_PCSPK | MDT_ADLIB | MDT_NATIVE,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_USE_KEY | GF_16COLOR | GF_OLD_BUNDLE, "00.LFL"}, GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_USE_KEY | GF_16COLOR | GF_OLD_BUNDLE, "00.LFL"},
{"loomTowns", "Loom (FM Towns)", GID_LOOM, 3, MDT_ADLIB, {"loomTowns", "Loom (FM Towns)", GID_LOOM, 3, MDT_TOWNS,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FMTOWNS | GF_AUDIOTRACKS, "00.LFL"}, GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FMTOWNS | GF_AUDIOTRACKS, "00.LFL"},
/* Scumm Version 4 */ /* Scumm Version 4 */
@ -696,6 +696,8 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst)
_imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1); _imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1);
_imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1); _imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1);
} }
if (_features & GF_FMTOWNS)
_imuse->property(IMuse::PROP_DIRECT_PASSTHROUGH, 1);
_imuse->set_music_volume(_sound->_sound_volume_music); _imuse->set_music_volume(_sound->_sound_volume_music);
} }
} }

View file

@ -54,6 +54,7 @@ static const struct MidiDriverDescription midiDrivers[] = {
{"adlib", "Adlib", MD_ADLIB}, {"adlib", "Adlib", MD_ADLIB},
{"pcspk", "PC Speaker", MD_PCSPK}, {"pcspk", "PC Speaker", MD_PCSPK},
{"pcjr", "IBM PCjr", MD_PCJR}, {"pcjr", "IBM PCjr", MD_PCJR},
{"towns", "FM Towns", MD_TOWNS},
#endif #endif
#if defined(__PALM_OS__) #if defined(__PALM_OS__)

View file

@ -44,8 +44,8 @@ enum {
MD_ADLIB = 10, MD_ADLIB = 10,
MD_PCSPK = 11, MD_PCSPK = 11,
MD_PCJR = 12, MD_PCJR = 12,
MD_TOWNS = 13,
MD_YPA1 = 100 // palmos MD_YPA1 = 14 // PalmOS
}; };
/** /**
@ -144,16 +144,16 @@ public:
// Control Change messages // Control Change messages
virtual void controlChange (byte control, byte value) = 0; virtual void controlChange (byte control, byte value) = 0;
virtual void modulationWheel (byte value) = 0; virtual void modulationWheel (byte value) { controlChange (1, value); }
virtual void volume (byte value) = 0; virtual void volume (byte value) { controlChange (7, value); }
virtual void panPosition (byte value) = 0; virtual void panPosition (byte value) { controlChange (10, value); }
virtual void pitchBendFactor (byte value) = 0; virtual void pitchBendFactor (byte value) = 0;
virtual void detune (byte value) = 0; virtual void detune (byte value) { controlChange (17, value); }
virtual void priority (byte value) = 0; virtual void priority (byte value) { controlChange (18, value); }
virtual void sustain (bool value) = 0; virtual void sustain (bool value) { controlChange (64, value ? 1 : 0); }
virtual void effectLevel (byte value) = 0; virtual void effectLevel (byte value) { controlChange (91, value); }
virtual void chorusLevel (byte value) = 0; virtual void chorusLevel (byte value) { controlChange (93, value); }
virtual void allNotesOff() = 0; virtual void allNotesOff() { controlChange (123, 0); }
// SysEx messages // SysEx messages
virtual void sysEx_customInstrument (uint32 type, byte *instr) = 0; virtual void sysEx_customInstrument (uint32 type, byte *instr) = 0;
@ -169,6 +169,7 @@ extern MidiDriver *MidiDriver_QT_create();
extern MidiDriver *MidiDriver_CORE_create(); extern MidiDriver *MidiDriver_CORE_create();
extern MidiDriver *MidiDriver_ETUDE_create(); extern MidiDriver *MidiDriver_ETUDE_create();
extern MidiDriver *MidiDriver_ALSA_create(); extern MidiDriver *MidiDriver_ALSA_create();
extern MidiDriver *MidiDriver_YM2612_create(SoundMixer *mixer);
extern MidiDriver *MidiDriver_YamahaPa1_create(); extern MidiDriver *MidiDriver_YamahaPa1_create();
#endif #endif

View file

@ -59,16 +59,7 @@ public:
// Control Change messages // Control Change messages
void controlChange (byte control, byte value); void controlChange (byte control, byte value);
void modulationWheel (byte value) { controlChange (1, value); }
void volume (byte value) { controlChange (7, value); }
void panPosition (byte value) { controlChange (10, value); }
void pitchBendFactor (byte value); void pitchBendFactor (byte value);
void detune (byte value) { controlChange (17, value); }
void priority (byte value) { controlChange (18, value); }
void sustain (bool value) { controlChange (64, value ? 1 : 0); }
void effectLevel (byte value) { controlChange (91, value); }
void chorusLevel (byte value) { controlChange (93, value); }
void allNotesOff() { controlChange (123, 0); }
// SysEx messages // SysEx messages
void sysEx_customInstrument (uint32 type, byte *instr); void sysEx_customInstrument (uint32 type, byte *instr);