Some work on the sound module handling and the SB16 midi file output.

- Added the capability to load up to 4 sound drivers and added methods to
  get pointers to the waveout, wavein and midiout services of a driver.
- Rewrite of the SB16 midi file output code. In midimode 2 and 3 the midiout
  service of the 'file' driver is used. Removed obsolete midi file handling.
- Re-implemented the closemidioutput() method to make runtime changes of the
  midi setup work with the new code.
This commit is contained in:
Volker Ruppert 2015-02-17 18:28:25 +00:00
parent c8207c7a10
commit b1e8a6369c
21 changed files with 286 additions and 293 deletions

View File

@ -77,13 +77,17 @@ class BOCHSAPI bx_devmodel_c : public logfunctions {
#endif
};
//////////////////////////////////////////////////////////////////////
// declare stubs for PCI devices
//////////////////////////////////////////////////////////////////////
// forward declarations
class bx_list_c;
class device_image_t;
class cdrom_base_c;
class bx_soundlow_waveout_c;
class bx_soundlow_wavein_c;
class bx_soundlow_midiout_c;
//////////////////////////////////////////////////////////////////////
// declare stubs for PCI devices
//////////////////////////////////////////////////////////////////////
// the best should be deriving of bx_pci_device_stub_c from bx_devmodel_c
// but it make serious problems for cirrus_svga device
@ -350,14 +354,14 @@ public:
#if BX_SUPPORT_SOUNDLOW
class BOCHSAPI bx_soundmod_ctl_stub_c : public bx_devmodel_c {
public:
virtual void* get_module() {
STUBFUNC(soundmod_ctl, get_module); return NULL;
virtual bx_soundlow_waveout_c* get_waveout(const char *driver) {
STUBFUNC(soundmod_ctl, get_waveout); return NULL;
}
virtual bx_bool beep_on(float frequency) {
return 0;
virtual bx_soundlow_wavein_c* get_wavein(const char *driver) {
STUBFUNC(soundmod_ctl, get_wavein); return NULL;
}
virtual bx_bool beep_off() {
return 0;
virtual bx_soundlow_midiout_c* get_midiout(const char *driver) {
STUBFUNC(soundmod_ctl, get_midiout); return NULL;
}
virtual void VOC_init_file(FILE *stream) {}
virtual void VOC_write_block(FILE *stream, int block, Bit32u headerlen,

View File

@ -186,7 +186,6 @@ bx_es1370_c::bx_es1370_c()
memset(&s, 0, sizeof(bx_es1370_t));
s.dac1_timer_index = BX_NULL_TIMER_HANDLE;
s.dac2_timer_index = BX_NULL_TIMER_HANDLE;
soundmod = NULL;
waveout = NULL;
wavein = NULL;
wavefile = NULL;
@ -223,9 +222,8 @@ void bx_es1370_c::init(void)
BX_ES1370_THIS pci_base_address[0] = 0;
BX_ES1370_THIS soundmod = DEV_sound_get_module();
BX_ES1370_THIS waveout = soundmod->get_waveout();
BX_ES1370_THIS wavein = soundmod->get_wavein();
BX_ES1370_THIS waveout = DEV_sound_get_waveout("default");
BX_ES1370_THIS wavein = DEV_sound_get_wavein("default");
BX_ES1370_THIS s.dac_outputinit = 1;
BX_ES1370_THIS s.adc_inputinit = 0;
BX_ES1370_THIS s.dac_nr_active = -1;

View File

@ -71,7 +71,6 @@ typedef struct {
// forward definitions
class bx_sound_lowlevel_c;
class bx_soundlow_waveout_c;
class bx_soundlow_wavein_c;
@ -118,7 +117,6 @@ private:
void write(Bit32u address, Bit32u value, unsigned io_len);
#endif
bx_sound_lowlevel_c *soundmod;
bx_soundlow_waveout_c *waveout;
bx_soundlow_wavein_c *wavein;
int wavemode;

View File

@ -175,7 +175,6 @@ void CDECL libsb16_LTX_plugin_fini(void)
// some shortcuts to save typing
#define LOGFILE BX_SB16_THIS logfile
#define MIDIDATA BX_SB16_THIS midifile
#define WAVEDATA BX_SB16_THIS wavefile
#define MPU BX_SB16_THIS mpu401
#define DSP BX_SB16_THIS dsp
@ -183,7 +182,6 @@ void CDECL libsb16_LTX_plugin_fini(void)
#define EMUL BX_SB16_THIS emuldata
#define OPL BX_SB16_THIS opl
#define BX_SB16_OUTPUT BX_SB16_THIS soundmod
#define BX_SB16_WAVEOUT BX_SB16_THIS waveout
#define BX_SB16_WAVEIN BX_SB16_THIS wavein
#define BX_SB16_MIDIOUT BX_SB16_THIS midiout
@ -191,6 +189,13 @@ void CDECL libsb16_LTX_plugin_fini(void)
// here's a safe way to print out null pointeres
#define MIGHT_BE_NULL(x) ((x==NULL)? "(null)" : x)
const char *sb16_midi_drv[4] = {
"dummy",
"default",
"file",
"file",
};
// the device object
bx_sb16_c::bx_sb16_c(void)
@ -204,11 +209,10 @@ bx_sb16_c::bx_sb16_c(void)
mpu401.timer_handle = BX_NULL_TIMER_HANDLE;
dsp.timer_handle = BX_NULL_TIMER_HANDLE;
opl.timer_handle = BX_NULL_TIMER_HANDLE;
soundmod = NULL;
waveout = NULL;
wavein = NULL;
midiout = NULL;
midimode = 0;
midifile = NULL;
wavemode = 0;
wavefile = NULL;
loglevel = 0;
@ -255,21 +259,19 @@ void bx_sb16_c::init(void)
BX_SB16_THIS loglevel = SIM->get_param_num("loglevel", base)->get();
// always initialize lowlevel driver
BX_SB16_OUTPUT = DEV_sound_get_module();
if (BX_SB16_OUTPUT == NULL) {
BX_PANIC(("Couldn't initialize lowlevel driver"));
}
BX_SB16_WAVEOUT = soundmod->get_waveout();
BX_SB16_WAVEOUT = DEV_sound_get_waveout("default");
if (BX_SB16_WAVEOUT == NULL) {
BX_PANIC(("Couldn't initialize lowlevel driver (waveout)"));
BX_PANIC(("Couldn't initialize waveout driver"));
}
BX_SB16_WAVEIN = soundmod->get_wavein();
BX_SB16_WAVEIN = DEV_sound_get_wavein("default");
if (BX_SB16_WAVEIN == NULL) {
BX_PANIC(("Couldn't initialize lowlevel driver (wavein)"));
BX_PANIC(("Couldn't initialize wavein driver"));
}
BX_SB16_MIDIOUT = soundmod->get_midiout();
if (BX_SB16_MIDIOUT == NULL) {
BX_PANIC(("Couldn't initialize lowlevel driver (midiout)"));
if ((BX_SB16_THIS midimode >= 0) && (BX_SB16_THIS midimode <= 3)) {
BX_SB16_MIDIOUT = DEV_sound_get_midiout(sb16_midi_drv[BX_SB16_THIS midimode]);
if (BX_SB16_MIDIOUT == NULL) {
BX_PANIC(("Couldn't initialize midiout driver"));
}
}
DSP.dma.chunk = new Bit8u[BX_SOUNDLOW_WAVEPACKETSIZE];
@ -438,7 +440,6 @@ void bx_sb16_c::register_state(void)
new bx_shadow_bool_c(mpu, "irqpending", &MPU.irqpending);
new bx_shadow_bool_c(mpu, "forceuartmode", &MPU.forceuartmode);
new bx_shadow_bool_c(mpu, "singlecommand", &MPU.singlecommand);
new bx_shadow_bool_c(mpu, "outputinit", &MPU.outputinit);
new bx_shadow_num_c(mpu, "current_timer", &MPU.current_timer);
new bx_shadow_num_c(mpu, "last_delta_time", &MPU.last_delta_time);
bx_list_c *patchtbl = new bx_list_c(mpu, "patchtable");
@ -530,9 +531,17 @@ void bx_sb16_c::runtime_config_handler(void *this_ptr)
void bx_sb16_c::runtime_config(void)
{
bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_SOUND_SB16);
if (BX_SB16_THIS midi_changed) {
if (BX_SB16_THIS midi_changed != 0) {
BX_SB16_THIS closemidioutput();
BX_SB16_THIS midimode = SIM->get_param_num("midimode", base)->get();
if (BX_SB16_THIS midi_changed & 1) {
BX_SB16_THIS midimode = SIM->get_param_num("midimode", base)->get();
if ((BX_SB16_THIS midimode >= 0) && (BX_SB16_THIS midimode <= 3)) {
BX_SB16_MIDIOUT = DEV_sound_get_midiout(sb16_midi_drv[BX_SB16_THIS midimode]);
if (BX_SB16_MIDIOUT == NULL) {
BX_PANIC(("Couldn't initialize midiout driver"));
}
}
}
// writemidicommand() re-opens the output device / file on demand
BX_SB16_THIS midi_changed = 0;
}
@ -2378,55 +2387,26 @@ Bit32u fmopl_callback(void *dev, Bit16u rate, Bit8u *buffer, Bit32u len)
/* Handlers for the midi commands/midi file output */
// Write the header of the midi file. Track length is 0x7fffffff
// until we know how long it's really going to be
void bx_sb16_c::initmidifile()
{
struct {
Bit8u chunk[4];
Bit32u chunklen; // all values in BIG Endian!
Bit16u smftype;
Bit16u tracknum;
Bit16u timecode; // 0x80 + deltatimesperquarter << 8
} midiheader =
#ifdef BX_LITTLE_ENDIAN
{ "MTh", 0x06000000, 0, 0x0100, 0x8001 };
#else
{ "MTh", 6, 0, 1, 0x180 };
#endif
midiheader.chunk[3] = 'd';
struct {
Bit8u chunk[4];
Bit32u chunklen;
Bit8u data[15];
} trackheader =
#ifdef BX_LITTLE_ENDIAN
{ "MTr", 0xffffff7f,
#else
{ "MTr", 0x7fffffff,
#endif
{ 0x00,0xff,0x51,3,0x07,0xa1,0x20, // set tempo 120 (0x7a120 us per quarter)
0x00,0xff,0x58,4,4,2,0x18,0x08 }}; // time sig 4/4
trackheader.chunk[3] = 'k';
fwrite(&midiheader, 1, 14, MIDIDATA);
fwrite(&trackheader, 1, 23, MIDIDATA);
}
// write the midi command to the midi file
void bx_sb16_c::writemidicommand(int command, int length, Bit8u data[])
{
bx_param_string_c *midiparam;
/* We need to determine the time elapsed since the last MIDI command */
int deltatime = currentdeltatime();
/* Initialize output device if necessary and not done yet */
if (BX_SB16_THIS midimode == 1) {
/* Initialize output device/file if necessary and not done yet */
if (BX_SB16_THIS midimode > 0) {
if (MPU.outputinit != 1) {
writelog(MIDILOG(4), "Initializing Midi output.");
if (BX_SB16_MIDIOUT->openmidioutput(SIM->get_param_string(BXPN_SOUND_MIDIOUT)->getptr()) == BX_SOUNDLOW_OK)
if (BX_SB16_THIS midimode == 1) {
midiparam = SIM->get_param_string(BXPN_SOUND_MIDIOUT);
} else {
bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_SOUND_SB16);
midiparam = SIM->get_param_string("midi", base);
}
if (BX_SB16_MIDIOUT->openmidioutput(midiparam->getptr()) == BX_SOUNDLOW_OK)
MPU.outputinit = 1;
else
MPU.outputinit = 0;
@ -2437,35 +2417,7 @@ void bx_sb16_c::writemidicommand(int command, int length, Bit8u data[])
}
}
BX_SB16_MIDIOUT->sendmidicommand(deltatime, command, length, data);
return;
} else if ((BX_SB16_THIS midimode == 2) ||
(BX_SB16_THIS midimode == 3)) {
bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_SOUND_SB16);
bx_param_string_c *midiparam = SIM->get_param_string("midi", base);
if ((MIDIDATA == NULL) && (!midiparam->isempty())) {
MIDIDATA = fopen(midiparam->getptr(),"wb");
if (MIDIDATA == NULL) {
writelog (MIDILOG(2), "Error opening file %s. Midimode disabled.",
midiparam->getptr());
BX_SB16_THIS midimode = 0;
} else if (BX_SB16_THIS midimode == 2) {
initmidifile();
}
}
}
if (BX_SB16_THIS midimode < 2)
return;
if (BX_SB16_THIS midimode == 2)
writedeltatime(deltatime);
fputc(command, MIDIDATA);
if ((command == 0xf0) ||
(command == 0xf7)) // write event length for sysex/meta events
writedeltatime(length);
fwrite(data, 1, length, MIDIDATA);
}
// determine how many delta times have passed since
@ -2594,86 +2546,13 @@ void bx_sb16_c::midiremapprogram(int channel)
}
}
// convert a number into a delta time coded value
int bx_sb16_c::converttodeltatime(Bit32u deltatime, Bit8u value[4])
{
int i, count;
Bit8u outbytes[4];
count = 0;
if (deltatime <= 0)
{
count = 1;
value[0] = 0;
}
else
{
while ((deltatime > 0) && (count < 4)) // split into parts
{ // of seven bits
outbytes[count++] = deltatime & 0x7f;
deltatime >>= 7;
}
for (i=0; i<count; i++) // reverse order and
value[i] = outbytes[count - i - 1] | 0x80; // set eighth bit on
value[count - 1] &= 0x7f; // all but last byte
}
return count;
}
// write a delta time coded value to the midi file
void bx_sb16_c::writedeltatime(Bit32u deltatime)
{
Bit8u outbytes[4];
int count = converttodeltatime(deltatime, outbytes);
for (int i=0; i<count; i++)
fputc(outbytes[i], MIDIDATA);
}
// close the midi file, and set the track length accordingly
void bx_sb16_c::finishmidifile()
{
struct {
Bit8u delta, statusbyte, metaevent, length;
} metatrackend = { 0, 0xff, 0x2f, 0 };
// Meta event track end (0xff 0x2f 0x00) plus leading delta time
fwrite(&metatrackend, 1, sizeof(metatrackend), MIDIDATA);
Bit32u tracklen = ftell(MIDIDATA);
if (tracklen < 0)
BX_PANIC (("ftell failed in finishmidifile"));
if (tracklen < 22)
BX_PANIC (("finishmidifile with track length too short"));
tracklen -= 22; // subtract the midi file and track header
fseek(MIDIDATA, 22 - 4, SEEK_SET);
// value has to be in big endian
#ifdef BX_LITTLE_ENDIAN
tracklen = bx_bswap32(tracklen);
#endif
fwrite(&tracklen, 4, 1, MIDIDATA);
}
void bx_sb16_c::closemidioutput()
{
switch (BX_SB16_THIS midimode) {
case 1:
if (MPU.outputinit != 0) {
MPU.outputinit = 0;
}
break;
case 2:
if (MIDIDATA != NULL)
finishmidifile();
case 3:
if (MIDIDATA != NULL)
fclose(MIDIDATA);
MIDIDATA = NULL;
break;
if (BX_SB16_THIS midimode > 0) {
if (MPU.outputinit != 0) {
BX_SB16_MIDIOUT->closemidioutput();
MPU.outputinit = 0;
}
}
}
@ -3238,7 +3117,7 @@ Bit64s bx_sb16_c::sb16_param_handler(bx_param_c *param, int set, Bit64s val)
BX_SB16_THIS loglevel = (int)val;
} else if (!strcmp(pname, "midimode")) {
if (val != BX_SB16_THIS midimode) {
BX_SB16_THIS midi_changed = 1;
BX_SB16_THIS midi_changed |= 1;
}
} else if (!strcmp(pname, "wavemode")) {
if (val != BX_SB16_THIS wavemode) {
@ -3260,7 +3139,7 @@ const char* bx_sb16_c::sb16_param_string_handler(bx_param_string_c *param, int s
if (!strcmp(pname, "wave")) {
BX_SB16_THIS wave_changed = 1;
} else if (!strcmp(pname, "midi")) {
BX_SB16_THIS midi_changed = 1;
BX_SB16_THIS midi_changed |= 2;
} else if (!strcmp(pname, "log")) {
if (LOGFILE != NULL) {
fclose(LOGFILE);

View File

@ -152,10 +152,10 @@ public:
private:
int midimode, wavemode, loglevel;
bx_bool midi_changed, wave_changed;
bx_bool wave_changed;
Bit8u midi_changed;
Bit32u dmatimer;
FILE *logfile, *midifile, *wavefile; // the output files or devices
bx_sound_lowlevel_c *soundmod; // the lowlevel class
FILE *logfile, *wavefile; // the output files or devices
bx_soundlow_waveout_c *waveout; // waveout support
bx_soundlow_wavein_c *wavein; // wavein support
bx_soundlow_midiout_c *midiout; // midiout support
@ -293,14 +293,10 @@ private:
BX_SB16_SMF int currentdeltatime();
BX_SB16_SMF void processmidicommand(bx_bool force);
BX_SB16_SMF void midiremapprogram(int channel); // remap program change
BX_SB16_SMF int converttodeltatime(Bit32u deltatime, Bit8u value[4]);
BX_SB16_SMF void writemidicommand(int command, int length, Bit8u data[]);
BX_SB16_SMF void writedeltatime(Bit32u deltatime); // write in delta time coding
BX_SB16_SMF void initmidifile(); // write midi file header
BX_SB16_SMF void closemidioutput(); // close midi file / device
BX_SB16_SMF void closewaveoutput(); // close wave file
BX_SB16_SMF void finishmidifile(); // write track length etc.
BX_SB16_SMF void finishvocfile(); // close voc file
BX_SB16_SMF void create_logfile();

View File

@ -273,9 +273,7 @@ bx_soundlow_midiout_alsa_c::bx_soundlow_midiout_alsa_c()
bx_soundlow_midiout_alsa_c::~bx_soundlow_midiout_alsa_c()
{
if (alsa_seq.handle != NULL) {
snd_seq_close(alsa_seq.handle);
}
closemidioutput();
}
int bx_soundlow_midiout_alsa_c::alsa_seq_open(const char *alsadev)
@ -415,6 +413,15 @@ int bx_soundlow_midiout_alsa_c::sendmidicommand(int delta, int command, int leng
return BX_SOUNDLOW_ERR;
}
int bx_soundlow_midiout_alsa_c::closemidioutput()
{
if (alsa_seq.handle != NULL) {
snd_seq_close(alsa_seq.handle);
alsa_seq.handle = NULL;
}
return BX_SOUNDLOW_OK;
}
// bx_sound_alsa_c class implemenzation
bx_sound_alsa_c::bx_sound_alsa_c()

View File

@ -73,6 +73,7 @@ public:
virtual int openmidioutput(const char *mididev);
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
virtual int closemidioutput();
private:
int alsa_seq_open(const char *alsadev);

View File

@ -167,30 +167,7 @@ bx_soundlow_midiout_file_c::bx_soundlow_midiout_file_c()
bx_soundlow_midiout_file_c::~bx_soundlow_midiout_file_c()
{
struct {
Bit8u delta, statusbyte, metaevent, length;
} metatrackend = { 0, 0xff, 0x2f, 0 };
if (midifile != NULL) {
if (type == BX_SOUNDFILE_MID) {
// Meta event track end (0xff 0x2f 0x00) plus leading delta time
fwrite(&metatrackend, 1, sizeof(metatrackend), midifile);
Bit32u tracklen = ftell(midifile);
if (tracklen < 0)
BX_PANIC (("ftell failed in finishmidifile"));
if (tracklen < 22)
BX_PANIC (("MIDI track length too short"));
tracklen -= 22; // subtract the midi file and track header
fseek(midifile, 22 - 4, SEEK_SET);
// value has to be in big endian
#ifdef BX_LITTLE_ENDIAN
tracklen = bx_bswap32(tracklen);
#endif
fwrite(&tracklen, 4, 1, midifile);
}
fclose(midifile);
}
closemidioutput();
}
int bx_soundlow_midiout_file_c::openmidioutput(const char *mididev)
@ -263,6 +240,36 @@ int bx_soundlow_midiout_file_c::sendmidicommand(int delta, int command, int leng
return BX_SOUNDLOW_OK;
}
int bx_soundlow_midiout_file_c::closemidioutput()
{
struct {
Bit8u delta, statusbyte, metaevent, length;
} metatrackend = { 0, 0xff, 0x2f, 0 };
if (midifile != NULL) {
if (type == BX_SOUNDFILE_MID) {
// Meta event track end (0xff 0x2f 0x00) plus leading delta time
fwrite(&metatrackend, 1, sizeof(metatrackend), midifile);
Bit32u tracklen = ftell(midifile);
if (tracklen < 0)
BX_PANIC (("ftell failed in finishmidifile"));
if (tracklen < 22)
BX_PANIC (("MIDI track length too short"));
tracklen -= 22; // subtract the midi file and track header
fseek(midifile, 22 - 4, SEEK_SET);
// value has to be in big endian
#ifdef BX_LITTLE_ENDIAN
tracklen = bx_bswap32(tracklen);
#endif
fwrite(&tracklen, 4, 1, midifile);
}
fclose(midifile);
midifile = NULL;
}
return BX_SOUNDLOW_OK;
}
void bx_soundlow_midiout_file_c::writedeltatime(Bit32u deltatime)
{
int i, count = 0;

View File

@ -31,6 +31,7 @@ public:
virtual int openwaveoutput(const char *wavedev);
virtual int set_pcm_params(bx_pcm_param_t *param);
virtual int output(int length, Bit8u data[]);
private:
void initvocfile();
void initwavfile();
@ -47,6 +48,7 @@ public:
virtual int openmidioutput(const char *mididev);
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
virtual int closemidioutput();
private:
void writedeltatime(Bit32u deltatime);

View File

@ -303,7 +303,7 @@ bx_soundlow_midiout_oss_c::bx_soundlow_midiout_oss_c()
bx_soundlow_midiout_oss_c::~bx_soundlow_midiout_oss_c()
{
fclose(midi);
closemidioutput();
}
int bx_soundlow_midiout_oss_c::openmidioutput(const char *mididev)
@ -323,11 +323,6 @@ int bx_soundlow_midiout_oss_c::openmidioutput(const char *mididev)
}
int bx_soundlow_midiout_oss_c::midiready()
{
return BX_SOUNDLOW_OK;
}
int bx_soundlow_midiout_oss_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
{
UNUSED(delta);
@ -339,6 +334,15 @@ int bx_soundlow_midiout_oss_c::sendmidicommand(int delta, int command, int lengt
return BX_SOUNDLOW_OK;
}
int bx_soundlow_midiout_oss_c::closemidioutput()
{
if (midi != NULL) {
fclose(midi);
midi = NULL;
}
return BX_SOUNDLOW_OK;
}
// bx_sound_oss_c class implemenzation
bx_sound_oss_c::bx_sound_oss_c()

View File

@ -60,8 +60,8 @@ public:
virtual ~bx_soundlow_midiout_oss_c();
virtual int openmidioutput(const char *mididev);
virtual int midiready();
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
virtual int closemidioutput();
private:
FILE *midi;

View File

@ -426,6 +426,11 @@ int bx_soundlow_midiout_c::sendmidicommand(int delta, int command, int length, B
return BX_SOUNDLOW_OK;
}
int bx_soundlow_midiout_c::closemidioutput()
{
return BX_SOUNDLOW_OK;
}
// bx_sound_lowlevel_c class implemenzation
// This is the base class of the sound lowlevel support.

View File

@ -122,6 +122,7 @@ public:
virtual int openmidioutput(const char *mididev);
virtual int midiready();
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
virtual int closemidioutput();
};
// the lowlevel sound driver class returns pointers to the child objects

View File

@ -65,72 +65,140 @@ void CDECL libsoundmod_LTX_plugin_fini(void)
bx_soundmod_ctl_c::bx_soundmod_ctl_c()
{
put("soundctl", "SNDCTL");
soundmod = NULL;
n_sound_drivers = 0;
waveout = NULL;
}
bx_soundmod_ctl_c::~bx_soundmod_ctl_c()
{
delete soundmod;
for (unsigned i = 0; i < n_sound_drivers; i++) {
delete soundmod[i].module;
}
}
void bx_soundmod_ctl_c::init()
{
int ret;
static const char default_name[] = BX_SOUND_LOWLEVEL_NAME;
const char *driver = SIM->get_param_string(BXPN_SOUND_DRIVER)->getptr();
const char *pwaveout = SIM->get_param_string(BXPN_SOUND_WAVEOUT)->getptr();
const char *wavein = SIM->get_param_string(BXPN_SOUND_WAVEIN)->getptr();
if (strcmp(driver, "default") == 0) {
driver = default_name;
}
if (strcmp(driver, "dummy") == 0) {
soundmod = new bx_sound_lowlevel_c();
} else if (!strcmp(driver, "file")) {
soundmod = new bx_sound_file_c();
#if BX_HAVE_ALSASOUND
} else if (!strcmp(driver, "alsa")) {
soundmod = new bx_sound_alsa_c();
#endif
#if BX_WITH_SDL || BX_WITH_SDL2
} else if (!strcmp(driver, "sdl")) {
soundmod = new bx_sound_sdl_c();
#endif
#if (defined(linux) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__))
} else if (!strcmp(driver, "oss")) {
soundmod = new bx_sound_oss_c();
#endif
#if defined(macintosh)
} else if (!strcmp(driver, "osx")) {
soundmod = new bx_sound_osx_c();
#endif
#if defined(WIN32)
} else if (!strcmp(driver, "win")) {
soundmod = new bx_sound_windows_c();
#endif
} else {
BX_PANIC(("unknown lowlevel sound driver '%s'", driver));
return;
}
if (!strlen(wavein)) {
SIM->get_param_string(BXPN_SOUND_WAVEIN)->set(pwaveout);
}
waveout = soundmod->get_waveout();
if (waveout != NULL) {
ret = waveout->openwaveoutput(pwaveout);
if (ret != BX_SOUNDLOW_OK) {
BX_PANIC(("Could not open wave output device"));
if (get_driver(driver) != NULL) {
if (!strlen(wavein)) {
SIM->get_param_string(BXPN_SOUND_WAVEIN)->set(pwaveout);
}
waveout = soundmod[0].module->get_waveout();
if (waveout != NULL) {
ret = waveout->openwaveoutput(pwaveout);
if (ret != BX_SOUNDLOW_OK) {
BX_PANIC(("Could not open wave output device"));
}
} else {
BX_PANIC(("no waveout support in sound driver '%s'", driver));
}
} else {
BX_PANIC(("no waveout support in sound driver '%s'", driver));
}
}
void* bx_soundmod_ctl_c::get_module()
bx_sound_lowlevel_c* bx_soundmod_ctl_c::get_driver(const char *name)
{
return soundmod;
static const char default_name[] = BX_SOUND_LOWLEVEL_NAME;
bx_sound_lowlevel_c *driver = NULL;
unsigned i;
if (strcmp(name, "default") == 0) {
name = default_name;
}
for (i = 0; i < n_sound_drivers; i++) {
if (!strcmp(name, soundmod[i].name)) {
return soundmod[i].module;
}
}
if (i == BX_MAX_SOUND_DRIVERS) {
BX_PANIC(("Too many sound drivers!"));
return NULL;
}
if (strcmp(name, "dummy") == 0) {
driver = new bx_sound_lowlevel_c();
} else if (!strcmp(name, "file")) {
driver = new bx_sound_file_c();
#if BX_HAVE_ALSASOUND
} else if (!strcmp(name, "alsa")) {
driver = new bx_sound_alsa_c();
#endif
#if BX_WITH_SDL || BX_WITH_SDL2
} else if (!strcmp(name, "sdl")) {
driver = new bx_sound_sdl_c();
#endif
#if (defined(linux) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__))
} else if (!strcmp(name, "oss")) {
driver = new bx_sound_oss_c();
#endif
#if defined(macintosh)
} else if (!strcmp(name, "osx")) {
driver = new bx_sound_osx_c();
#endif
#if defined(WIN32)
} else if (!strcmp(name, "win")) {
driver = new bx_sound_windows_c();
#endif
} else {
BX_PANIC(("unknown lowlevel sound driver '%s'", name));
}
if (driver != NULL) {
BX_INFO(("Installed sound driver '%s' at index #%d", name, i));
strcpy(soundmod[i].name, name);
soundmod[i].module = driver;
n_sound_drivers++;
}
return driver;
}
bx_soundlow_waveout_c* bx_soundmod_ctl_c::get_waveout(const char *driver)
{
bx_sound_lowlevel_c *module = NULL;
if (!strcmp(driver, "default")) {
module = soundmod[0].module;
} else {
module = get_driver(driver);
}
if (module != NULL) {
return module->get_waveout();
} else {
return NULL;
}
}
bx_soundlow_wavein_c* bx_soundmod_ctl_c::get_wavein(const char *driver)
{
bx_sound_lowlevel_c *module = NULL;
if (!strcmp(driver, "default")) {
module = soundmod[0].module;
} else {
module = get_driver(driver);
}
if (module != NULL) {
return module->get_wavein();
} else {
return NULL;
}
}
bx_soundlow_midiout_c* bx_soundmod_ctl_c::get_midiout(const char *driver)
{
bx_sound_lowlevel_c *module = NULL;
if (!strcmp(driver, "default")) {
module = soundmod[0].module;
} else {
module = get_driver(driver);
}
if (module != NULL) {
return module->get_midiout();
} else {
return NULL;
}
}
/* Handlers for the VOC file output */

View File

@ -20,6 +20,8 @@
// Common code for sound lowlevel modules
#define BX_MAX_SOUND_DRIVERS 4
class bx_sound_lowlevel_c;
class bx_soundlow_waveout_c;
@ -29,11 +31,20 @@ public:
bx_soundmod_ctl_c();
virtual ~bx_soundmod_ctl_c();
virtual void init(void);
virtual void* get_module();
virtual bx_soundlow_waveout_c* get_waveout(const char *driver);
virtual bx_soundlow_wavein_c* get_wavein(const char *driver);
virtual bx_soundlow_midiout_c* get_midiout(const char *driver);
virtual void VOC_init_file(FILE *stream);
virtual void VOC_write_block(FILE *stream, int block, Bit32u headerlen,
Bit8u header[], Bit32u datalen, Bit8u data[]);
private:
bx_sound_lowlevel_c *soundmod;
bx_sound_lowlevel_c* get_driver(const char *name);
struct {
char name[8];
bx_sound_lowlevel_c *module;
} soundmod[BX_MAX_SOUND_DRIVERS];
unsigned n_sound_drivers;
bx_soundlow_waveout_c *waveout;
};

View File

@ -461,11 +461,7 @@ bx_soundlow_midiout_osx_c::bx_soundlow_midiout_osx_c()
bx_soundlow_midiout_osx_c::~bx_soundlow_midiout_osx_c()
{
MidiOpen = 0;
#ifdef BX_SOUND_OSX_use_converter
AUGraphStop(MidiGraph);
AUGraphClose(MidiGraph);
#endif
closemidioutput();
}
int bx_soundlow_midiout_osx_c::openmidioutput(const char *mididev)
@ -533,6 +529,16 @@ int bx_soundlow_midiout_osx_c::sendmidicommand(int delta, int command, int lengt
return BX_SOUNDLOW_OK;
}
int bx_soundlow_midiout_osx_c::closemidioutput()
{
MidiOpen = 0;
#ifdef BX_SOUND_OSX_use_converter
AUGraphStop(MidiGraph);
AUGraphClose(MidiGraph);
#endif
return BX_SOUNDLOW_OK;
}
// bx_sound_osx_c class implemenzation
bx_sound_osx_c::bx_sound_osx_c()

View File

@ -69,6 +69,7 @@ public:
virtual int openmidioutput(const char *mididev);
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
virtual int closemidioutput();
private:
int MidiOpen;

View File

@ -353,15 +353,7 @@ bx_soundlow_midiout_win_c::bx_soundlow_midiout_win_c()
bx_soundlow_midiout_win_c::~bx_soundlow_midiout_win_c()
{
UINT ret;
if (MidiOpen == 1) {
ret = midiOutReset(MidiOut);
if (ismidiready == 0)
checkmidiready(); // to clear any pending SYSEX
ret = midiOutClose(MidiOut);
BX_DEBUG(("midiOutClose() = %d", ret));
}
closemidioutput();
}
int bx_soundlow_midiout_win_c::openmidioutput(const char *mididev)
@ -438,6 +430,20 @@ int bx_soundlow_midiout_win_c::sendmidicommand(int delta, int command, int lengt
return (ret == 0) ? BX_SOUNDLOW_OK : BX_SOUNDLOW_ERR;
}
int bx_soundlow_midiout_win_c::closemidioutput()
{
UINT ret;
if (MidiOpen == 1) {
ret = midiOutReset(MidiOut);
if (ismidiready == 0)
checkmidiready(); // to clear any pending SYSEX
ret = midiOutClose(MidiOut);
BX_DEBUG(("midiOutClose() = %d", ret));
}
return BX_SOUNDLOW_OK;
}
void bx_soundlow_midiout_win_c::checkmidiready()
{
if ((MidiHeader->dwFlags & MHDR_DONE) != 0) {

View File

@ -207,6 +207,7 @@ public:
virtual int openmidioutput(const char *mididev);
virtual int midiready();
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
virtual int closemidioutput();
private:
HMIDIOUT MidiOut; // Midi output device

View File

@ -178,11 +178,7 @@ void bx_speaker_c::init(void)
if (!strcmp(mode, "sound")) {
output_mode = BX_SPK_MODE_SOUND;
#if BX_SUPPORT_SOUNDLOW
bx_sound_lowlevel_c *soundmod = DEV_sound_get_module();
if (soundmod == NULL) {
BX_PANIC(("Couldn't initialize lowlevel driver"));
}
waveout = soundmod->get_waveout();
waveout = DEV_sound_get_waveout("default");
if (waveout != NULL) {
beep_active = 0;
BX_INIT_MUTEX(beep_mutex);
@ -190,6 +186,7 @@ void bx_speaker_c::init(void)
BX_INFO(("Using lowlevel sound support for output"));
} else {
BX_ERROR(("Failed to use lowlevel sound support for output"));
output_mode = BX_SPK_MODE_NONE;
}
#endif
} else if (!strcmp(mode, "system")) {

View File

@ -255,8 +255,9 @@ extern "C" {
#define DEV_usb_send_msg(a,b) bx_devices.pluginUsbDevCtl->usb_send_msg((void*)a,b)
///////// Sound module macros
#define DEV_sound_get_module() \
((bx_sound_lowlevel_c*)bx_devices.pluginSoundModCtl->get_module())
#define DEV_sound_get_waveout(a) (bx_devices.pluginSoundModCtl->get_waveout(a))
#define DEV_sound_get_wavein(a) (bx_devices.pluginSoundModCtl->get_wavein(a))
#define DEV_sound_get_midiout(a) (bx_devices.pluginSoundModCtl->get_midiout(a))
#define DEV_soundmod_VOC_init_file(a) \
(bx_devices.pluginSoundModCtl->VOC_init_file(a))
#define DEV_soundmod_VOC_write_block(a,b,c,d,e,f) \