Moved wave output support to a separate C++ class. The lowlevel sound module
creates the object and returns a pointer to it. TODO: The wavein and midiout components should also move to separate classes. When finished, it should be possible to configure the sound support more detailed (e.g. waveout with sdl, midiout with alsa and the dummy driver for wavein). Creating a separate module for the output to file(s) is also possible.
This commit is contained in:
parent
59e3a4ddc6
commit
0e73185efd
@ -187,6 +187,7 @@ bx_es1370_c::bx_es1370_c()
|
||||
s.dac1_timer_index = BX_NULL_TIMER_HANDLE;
|
||||
s.dac2_timer_index = BX_NULL_TIMER_HANDLE;
|
||||
soundmod = NULL;
|
||||
waveout = NULL;
|
||||
wavefile = NULL;
|
||||
}
|
||||
|
||||
@ -225,6 +226,7 @@ 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 s.dac_outputinit = 1;
|
||||
BX_ES1370_THIS s.adc_inputinit = 0;
|
||||
BX_ES1370_THIS s.dac_nr_active = -1;
|
||||
@ -826,7 +828,7 @@ void bx_es1370_c::sendwavepacket(unsigned channel, Bit32u buflen, Bit8u *buffer)
|
||||
switch (BX_ES1370_THIS wavemode) {
|
||||
case 1:
|
||||
if (BX_ES1370_THIS s.dac_outputinit) {
|
||||
BX_ES1370_THIS soundmod->sendwavepacket(buflen, buffer, ¶m);
|
||||
BX_ES1370_THIS waveout->sendwavepacket(buflen, buffer, ¶m);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
|
@ -5,7 +5,7 @@
|
||||
// ES1370 soundcard support (ported from QEMU)
|
||||
//
|
||||
// Copyright (c) 2005 Vassili Karpov (malc)
|
||||
// Copyright (C) 2011-2013 The Bochs Project
|
||||
// Copyright (C) 2011-2015 The Bochs Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@ -70,8 +70,9 @@ typedef struct {
|
||||
} bx_es1370_t;
|
||||
|
||||
|
||||
// forward definition
|
||||
// forward definitions
|
||||
class bx_sound_lowlevel_c;
|
||||
class bx_soundlow_waveout_c;
|
||||
|
||||
class bx_es1370_c : public bx_devmodel_c, bx_pci_device_stub_c {
|
||||
public:
|
||||
@ -117,6 +118,7 @@ private:
|
||||
#endif
|
||||
|
||||
bx_sound_lowlevel_c *soundmod;
|
||||
bx_soundlow_waveout_c *waveout;
|
||||
int wavemode;
|
||||
bx_bool wave_changed;
|
||||
FILE *wavefile;
|
||||
|
@ -184,6 +184,7 @@ void CDECL libsb16_LTX_plugin_fini(void)
|
||||
#define OPL BX_SB16_THIS opl
|
||||
|
||||
#define BX_SB16_OUTPUT BX_SB16_THIS soundmod
|
||||
#define BX_SB16_WAVEOUT BX_SB16_THIS waveout
|
||||
|
||||
// here's a safe way to print out null pointeres
|
||||
#define MIGHT_BE_NULL(x) ((x==NULL)? "(null)" : x)
|
||||
@ -202,6 +203,7 @@ bx_sb16_c::bx_sb16_c(void)
|
||||
dsp.timer_handle = BX_NULL_TIMER_HANDLE;
|
||||
opl.timer_handle = BX_NULL_TIMER_HANDLE;
|
||||
soundmod = NULL;
|
||||
waveout = NULL;
|
||||
midimode = 0;
|
||||
midifile = NULL;
|
||||
wavemode = 0;
|
||||
@ -214,8 +216,8 @@ bx_sb16_c::~bx_sb16_c(void)
|
||||
{
|
||||
closemidioutput();
|
||||
|
||||
if (soundmod != NULL) {
|
||||
soundmod->unregister_wave_callback(fmopl_callback_id);
|
||||
if (waveout != NULL) {
|
||||
waveout->unregister_wave_callback(fmopl_callback_id);
|
||||
}
|
||||
if (DSP.inputinit != 0) {
|
||||
BX_SB16_OUTPUT->closewaveinput();
|
||||
@ -254,10 +256,13 @@ void bx_sb16_c::init(void)
|
||||
|
||||
// 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();
|
||||
if (BX_SB16_WAVEOUT == NULL) {
|
||||
BX_PANIC(("Couldn't initialize lowlevel driver"));
|
||||
}
|
||||
|
||||
DSP.dma.chunk = new Bit8u[BX_SOUNDLOW_WAVEPACKETSIZE];
|
||||
DSP.dma.chunkindex = 0;
|
||||
@ -378,7 +383,7 @@ void bx_sb16_c::init(void)
|
||||
(BX_SB16_THISP, opl_timer, 80, 1, 0, "sb16.opl");
|
||||
// opl timer: inactive, continuous, frequency 80us
|
||||
}
|
||||
BX_SB16_THIS fmopl_callback_id = soundmod->register_wave_callback(BX_SB16_THISP, fmopl_callback);
|
||||
BX_SB16_THIS fmopl_callback_id = waveout->register_wave_callback(BX_SB16_THISP, fmopl_callback);
|
||||
|
||||
writelog(MIDILOG(4), "Timers initialized, midi %d, dma %d, opl %d",
|
||||
MPU.timer_handle, DSP.timer_handle, OPL.timer_handle);
|
||||
@ -1394,7 +1399,7 @@ void bx_sb16_c::dsp_sendwavepacket()
|
||||
|
||||
switch (BX_SB16_THIS wavemode) {
|
||||
case 1:
|
||||
BX_SB16_OUTPUT->sendwavepacket(DSP.dma.chunkindex, DSP.dma.chunk, &DSP.dma.param);
|
||||
BX_SB16_WAVEOUT->sendwavepacket(DSP.dma.chunkindex, DSP.dma.chunk, &DSP.dma.param);
|
||||
break;
|
||||
case 3:
|
||||
fwrite(DSP.dma.chunk, 1, DSP.dma.chunkindex, WAVEDATA);
|
||||
|
@ -156,6 +156,7 @@ private:
|
||||
Bit32u dmatimer;
|
||||
FILE *logfile, *midifile, *wavefile; // the output files or devices
|
||||
bx_sound_lowlevel_c *soundmod; // the lowlevel class
|
||||
bx_soundlow_waveout_c *waveout; // waveout support
|
||||
int currentirq;
|
||||
int currentdma8;
|
||||
int currentdma16;
|
||||
|
@ -31,27 +31,146 @@
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define LOG_THIS log->
|
||||
|
||||
// helper function for wavein / waveout
|
||||
|
||||
int alsa_pcm_open(bx_bool mode, alsa_pcm_t *alsa_pcm, bx_pcm_param_t *param, logfunctions *log)
|
||||
{
|
||||
int ret;
|
||||
snd_pcm_format_t fmt;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
unsigned int size, freq;
|
||||
int dir, signeddata = param->format & 1;
|
||||
|
||||
alsa_pcm->audio_bufsize = 0;
|
||||
|
||||
if (alsa_pcm->handle == NULL) {
|
||||
ret = snd_pcm_open(&alsa_pcm->handle, "default", mode ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (ret < 0) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
BX_INFO(("ALSA: opened default PCM %s device", mode ? "input":"output"));
|
||||
}
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
snd_pcm_hw_params_any(alsa_pcm->handle, hwparams);
|
||||
snd_pcm_hw_params_set_access(alsa_pcm->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
|
||||
freq = (unsigned int)param->samplerate;
|
||||
|
||||
if (param->bits == 16) {
|
||||
if (signeddata == 1)
|
||||
fmt = SND_PCM_FORMAT_S16_LE;
|
||||
else
|
||||
fmt = SND_PCM_FORMAT_U16_LE;
|
||||
size = 2;
|
||||
} else if (param->bits == 8) {
|
||||
if (signeddata == 1)
|
||||
fmt = SND_PCM_FORMAT_S8;
|
||||
else
|
||||
fmt = SND_PCM_FORMAT_U8;
|
||||
size = 1;
|
||||
} else
|
||||
return BX_SOUNDLOW_ERR;
|
||||
|
||||
if (param->channels == 2) size *= 2;
|
||||
|
||||
snd_pcm_hw_params_set_format(alsa_pcm->handle, hwparams, fmt);
|
||||
snd_pcm_hw_params_set_channels(alsa_pcm->handle, hwparams, param->channels);
|
||||
snd_pcm_hw_params_set_rate_near(alsa_pcm->handle, hwparams, &freq, &dir);
|
||||
|
||||
alsa_pcm->frames = 32;
|
||||
snd_pcm_hw_params_set_period_size_near(alsa_pcm->handle, hwparams, &alsa_pcm->frames, &dir);
|
||||
|
||||
ret = snd_pcm_hw_params(alsa_pcm->handle, hwparams);
|
||||
if (ret < 0) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
snd_pcm_hw_params_get_period_size(hwparams, &alsa_pcm->frames, &dir);
|
||||
alsa_pcm->alsa_bufsize = alsa_pcm->frames * size;
|
||||
BX_DEBUG(("ALSA: buffer size set to %d", alsa_pcm->alsa_bufsize));
|
||||
if (alsa_pcm->buffer != NULL) {
|
||||
free(alsa_pcm->buffer);
|
||||
alsa_pcm->buffer = NULL;
|
||||
}
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
#undef LOG_THIS
|
||||
#define LOG_THIS
|
||||
|
||||
// bx_soundlow_waveout_alsa_c class implemenzation
|
||||
|
||||
bx_soundlow_waveout_alsa_c::bx_soundlow_waveout_alsa_c()
|
||||
:bx_soundlow_waveout_c()
|
||||
{
|
||||
alsa_waveout.handle = NULL;
|
||||
alsa_waveout.buffer = NULL;
|
||||
}
|
||||
|
||||
bx_soundlow_waveout_alsa_c::~bx_soundlow_waveout_alsa_c()
|
||||
{
|
||||
if (alsa_waveout.handle != NULL) {
|
||||
snd_pcm_drain(alsa_waveout.handle);
|
||||
snd_pcm_close(alsa_waveout.handle);
|
||||
alsa_waveout.handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_alsa_c::openwaveoutput(const char *wavedev)
|
||||
{
|
||||
set_pcm_params(&real_pcm_param);
|
||||
pcm_callback_id = register_wave_callback(this, pcm_callback);
|
||||
BX_INIT_MUTEX(mixer_mutex);
|
||||
start_mixer_thread();
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_alsa_c::set_pcm_params(bx_pcm_param_t *param)
|
||||
{
|
||||
return alsa_pcm_open(0, &alsa_waveout, param, this);
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_alsa_c::get_packetsize()
|
||||
{
|
||||
return alsa_waveout.alsa_bufsize;
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_alsa_c::output(int length, Bit8u data[])
|
||||
{
|
||||
if (!alsa_waveout.handle || (length > alsa_waveout.alsa_bufsize)) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
int ret = snd_pcm_writei(alsa_waveout.handle, data, alsa_waveout.frames);
|
||||
if (ret == -EPIPE) {
|
||||
/* EPIPE means underrun */
|
||||
BX_ERROR(("ALSA: underrun occurred"));
|
||||
snd_pcm_prepare(alsa_waveout.handle);
|
||||
} else if (ret < 0) {
|
||||
BX_ERROR(("ALSA: error from writei: %s", snd_strerror(ret)));
|
||||
} else if (ret != (int)alsa_waveout.frames) {
|
||||
BX_ERROR(("ALSA: short write, write %d frames", ret));
|
||||
}
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
// bx_sound_alsa_c class implemenzation
|
||||
|
||||
bx_sound_alsa_c::bx_sound_alsa_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
{
|
||||
alsa_seq.handle = NULL;
|
||||
alsa_pcm[0].handle = NULL;
|
||||
alsa_pcm[1].handle = NULL;
|
||||
alsa_pcm[0].buffer = NULL;
|
||||
alsa_pcm[1].buffer = NULL;
|
||||
alsa_wavein.handle = NULL;
|
||||
alsa_wavein.buffer = NULL;
|
||||
BX_INFO(("Sound lowlevel module 'alsa' initialized"));
|
||||
}
|
||||
|
||||
bx_sound_alsa_c::~bx_sound_alsa_c()
|
||||
bx_soundlow_waveout_c* bx_sound_alsa_c::get_waveout()
|
||||
{
|
||||
// nothing for now
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::midiready()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
if (waveout == NULL) {
|
||||
waveout = new bx_soundlow_waveout_alsa_c();
|
||||
}
|
||||
return waveout;
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::alsa_seq_open(const char *alsadev)
|
||||
@ -115,6 +234,10 @@ int bx_sound_alsa_c::openmidioutput(const char *mididev)
|
||||
return alsa_seq_open(mididev);
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::midiready()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::alsa_seq_output(int delta, int command, int length, Bit8u data[])
|
||||
{
|
||||
@ -192,7 +315,6 @@ int bx_sound_alsa_c::sendmidicommand(int delta, int command, int length, Bit8u d
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
|
||||
int bx_sound_alsa_c::closemidioutput()
|
||||
{
|
||||
if (alsa_seq.handle != NULL) {
|
||||
@ -202,123 +324,6 @@ int bx_sound_alsa_c::closemidioutput()
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
|
||||
int bx_sound_alsa_c::openwaveoutput(const char *wavedev)
|
||||
{
|
||||
set_pcm_params(real_pcm_param);
|
||||
pcm_callback_id = register_wave_callback(this, pcm_callback);
|
||||
BX_INIT_MUTEX(mixer_mutex);
|
||||
start_mixer_thread();
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::alsa_pcm_open(bx_bool mode, bx_pcm_param_t *param)
|
||||
{
|
||||
int ret;
|
||||
snd_pcm_format_t fmt;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
unsigned int size, freq;
|
||||
int dir, signeddata = param->format & 1;
|
||||
|
||||
alsa_pcm[mode].audio_bufsize = 0;
|
||||
|
||||
if (alsa_pcm[mode].handle == NULL) {
|
||||
ret = snd_pcm_open(&alsa_pcm[mode].handle, "default", mode ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (ret < 0) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
BX_INFO(("ALSA: opened default PCM %s device", mode ? "input":"output"));
|
||||
}
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
snd_pcm_hw_params_any(alsa_pcm[mode].handle, hwparams);
|
||||
snd_pcm_hw_params_set_access(alsa_pcm[mode].handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
|
||||
if (mode == 1) {
|
||||
if (memcmp(param, &wavein_param, sizeof(bx_pcm_param_t)) == 0) {
|
||||
return BX_SOUNDLOW_OK; // nothing to do
|
||||
}
|
||||
wavein_param = *param;
|
||||
}
|
||||
|
||||
freq = (unsigned int)param->samplerate;
|
||||
|
||||
if (param->bits == 16) {
|
||||
if (signeddata == 1)
|
||||
fmt = SND_PCM_FORMAT_S16_LE;
|
||||
else
|
||||
fmt = SND_PCM_FORMAT_U16_LE;
|
||||
size = 2;
|
||||
} else if (param->bits == 8) {
|
||||
if (signeddata == 1)
|
||||
fmt = SND_PCM_FORMAT_S8;
|
||||
else
|
||||
fmt = SND_PCM_FORMAT_U8;
|
||||
size = 1;
|
||||
} else
|
||||
return BX_SOUNDLOW_ERR;
|
||||
|
||||
if (param->channels == 2) size *= 2;
|
||||
|
||||
snd_pcm_hw_params_set_format(alsa_pcm[mode].handle, hwparams, fmt);
|
||||
snd_pcm_hw_params_set_channels(alsa_pcm[mode].handle, hwparams, param->channels);
|
||||
snd_pcm_hw_params_set_rate_near(alsa_pcm[mode].handle, hwparams, &freq, &dir);
|
||||
|
||||
alsa_pcm[mode].frames = 32;
|
||||
snd_pcm_hw_params_set_period_size_near(alsa_pcm[mode].handle, hwparams, &alsa_pcm[mode].frames, &dir);
|
||||
|
||||
ret = snd_pcm_hw_params(alsa_pcm[mode].handle, hwparams);
|
||||
if (ret < 0) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
snd_pcm_hw_params_get_period_size(hwparams, &alsa_pcm[mode].frames, &dir);
|
||||
alsa_pcm[mode].alsa_bufsize = alsa_pcm[mode].frames * size;
|
||||
BX_DEBUG(("ALSA: buffer size set to %d", alsa_pcm[mode].alsa_bufsize));
|
||||
if (alsa_pcm[mode].buffer != NULL) {
|
||||
free(alsa_pcm[mode].buffer);
|
||||
alsa_pcm[mode].buffer = NULL;
|
||||
}
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::set_pcm_params(bx_pcm_param_t param)
|
||||
{
|
||||
return alsa_pcm_open(0, ¶m);
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::get_waveout_packetsize()
|
||||
{
|
||||
return alsa_pcm[0].alsa_bufsize;
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::waveout(int length, Bit8u data[])
|
||||
{
|
||||
if (!alsa_pcm[0].handle || (length > alsa_pcm[0].alsa_bufsize)) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
int ret = snd_pcm_writei(alsa_pcm[0].handle, data, alsa_pcm[0].frames);
|
||||
if (ret == -EPIPE) {
|
||||
/* EPIPE means underrun */
|
||||
BX_ERROR(("ALSA: underrun occurred"));
|
||||
snd_pcm_prepare(alsa_pcm[0].handle);
|
||||
} else if (ret < 0) {
|
||||
BX_ERROR(("ALSA: error from writei: %s", snd_strerror(ret)));
|
||||
} else if (ret != (int)alsa_pcm[0].frames) {
|
||||
BX_ERROR(("ALSA: short write, write %d frames", ret));
|
||||
}
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::closewaveoutput()
|
||||
{
|
||||
if (alsa_pcm[0].handle != NULL) {
|
||||
snd_pcm_drain(alsa_pcm[0].handle);
|
||||
snd_pcm_close(alsa_pcm[0].handle);
|
||||
alsa_pcm[0].handle = NULL;
|
||||
}
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::openwaveinput(const char *wavedev, sound_record_handler_t rh)
|
||||
{
|
||||
record_handler = rh;
|
||||
@ -346,37 +351,42 @@ int bx_sound_alsa_c::startwaverecord(bx_pcm_param_t *param)
|
||||
timer_val = (Bit64u)record_packet_size * 1000000 / (param->samplerate << shift);
|
||||
bx_pc_system.activate_timer(record_timer_index, (Bit32u)timer_val, 1);
|
||||
}
|
||||
return alsa_pcm_open(1, param);
|
||||
if (memcmp(param, &wavein_param, sizeof(bx_pcm_param_t)) == 0) {
|
||||
return BX_SOUNDLOW_OK;
|
||||
} else {
|
||||
wavein_param = *param;
|
||||
return alsa_pcm_open(1, &alsa_wavein, param, this);
|
||||
}
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::getwavepacket(int length, Bit8u data[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (alsa_pcm[1].buffer == NULL) {
|
||||
alsa_pcm[1].buffer = (char *)malloc(alsa_pcm[1].alsa_bufsize);
|
||||
if (alsa_wavein.buffer == NULL) {
|
||||
alsa_wavein.buffer = (char *)malloc(alsa_wavein.alsa_bufsize);
|
||||
}
|
||||
while (alsa_pcm[1].audio_bufsize < length) {
|
||||
ret = snd_pcm_readi(alsa_pcm[1].handle, alsa_pcm[1].buffer, alsa_pcm[1].frames);
|
||||
while (alsa_wavein.audio_bufsize < length) {
|
||||
ret = snd_pcm_readi(alsa_wavein.handle, alsa_wavein.buffer, alsa_wavein.frames);
|
||||
if (ret == -EAGAIN)
|
||||
continue;
|
||||
if (ret == -EPIPE) {
|
||||
/* EPIPE means overrun */
|
||||
BX_ERROR(("overrun occurred"));
|
||||
snd_pcm_prepare(alsa_pcm[1].handle);
|
||||
snd_pcm_prepare(alsa_wavein.handle);
|
||||
} else if (ret < 0) {
|
||||
BX_ERROR(("error from read: %s", snd_strerror(ret)));
|
||||
} else if (ret != (int)alsa_pcm[1].frames) {
|
||||
} else if (ret != (int)alsa_wavein.frames) {
|
||||
BX_ERROR(("short read, read %d frames", ret));
|
||||
}
|
||||
memcpy(audio_buffer+alsa_pcm[1].audio_bufsize, alsa_pcm[1].buffer, alsa_pcm[1].alsa_bufsize);
|
||||
alsa_pcm[1].audio_bufsize += alsa_pcm[1].alsa_bufsize;
|
||||
memcpy(audio_buffer+alsa_wavein.audio_bufsize, alsa_wavein.buffer, alsa_wavein.alsa_bufsize);
|
||||
alsa_wavein.audio_bufsize += alsa_wavein.alsa_bufsize;
|
||||
}
|
||||
memcpy(data, audio_buffer, length);
|
||||
alsa_pcm[1].audio_bufsize -= length;
|
||||
if ((alsa_pcm[1].audio_bufsize <= 0) && (alsa_pcm[1].buffer != NULL)) {
|
||||
free(alsa_pcm[1].buffer);
|
||||
alsa_pcm[1].buffer = NULL;
|
||||
alsa_wavein.audio_bufsize -= length;
|
||||
if ((alsa_wavein.audio_bufsize <= 0) && (alsa_wavein.buffer != NULL)) {
|
||||
free(alsa_wavein.buffer);
|
||||
alsa_wavein.buffer = NULL;
|
||||
}
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
@ -386,8 +396,8 @@ int bx_sound_alsa_c::stopwaverecord()
|
||||
if (record_timer_index != BX_NULL_TIMER_HANDLE) {
|
||||
bx_pc_system.deactivate_timer(record_timer_index);
|
||||
}
|
||||
if (alsa_pcm[1].handle != NULL) {
|
||||
snd_pcm_drain(alsa_pcm[1].handle);
|
||||
if (alsa_wavein.handle != NULL) {
|
||||
snd_pcm_drain(alsa_wavein.handle);
|
||||
}
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
@ -396,10 +406,10 @@ int bx_sound_alsa_c::stopwaverecord()
|
||||
int bx_sound_alsa_c::closewaveinput()
|
||||
{
|
||||
stopwaverecord();
|
||||
if (alsa_pcm[1].handle != NULL) {
|
||||
snd_pcm_drain(alsa_pcm[1].handle);
|
||||
snd_pcm_close(alsa_pcm[1].handle);
|
||||
alsa_pcm[1].handle = NULL;
|
||||
if (alsa_wavein.handle != NULL) {
|
||||
snd_pcm_drain(alsa_wavein.handle);
|
||||
snd_pcm_close(alsa_wavein.handle);
|
||||
alsa_wavein.handle = NULL;
|
||||
}
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
|
@ -28,24 +28,38 @@
|
||||
#define ALSA_PCM_NEW_HW_PARAMS_API
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
typedef struct {
|
||||
snd_pcm_t *handle;
|
||||
snd_pcm_uframes_t frames;
|
||||
int alsa_bufsize, audio_bufsize;
|
||||
char *buffer;
|
||||
} alsa_pcm_t;
|
||||
|
||||
class bx_soundlow_waveout_alsa_c : public bx_soundlow_waveout_c {
|
||||
public:
|
||||
bx_soundlow_waveout_alsa_c();
|
||||
virtual ~bx_soundlow_waveout_alsa_c();
|
||||
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t *param);
|
||||
virtual int get_packetsize();
|
||||
virtual int output(int length, Bit8u data[]);
|
||||
private:
|
||||
alsa_pcm_t alsa_waveout;
|
||||
};
|
||||
|
||||
class bx_sound_alsa_c : public bx_sound_lowlevel_c {
|
||||
public:
|
||||
bx_sound_alsa_c();
|
||||
virtual ~bx_sound_alsa_c();
|
||||
virtual ~bx_sound_alsa_c() {}
|
||||
|
||||
virtual int get_type() {return BX_SOUNDLOW_ALSA;}
|
||||
virtual bx_soundlow_waveout_c* get_waveout();
|
||||
|
||||
virtual int openmidioutput(const char *mididev);
|
||||
virtual int midiready();
|
||||
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
|
||||
virtual int closemidioutput();
|
||||
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t param);
|
||||
virtual int get_waveout_packetsize();
|
||||
virtual int waveout(int length, Bit8u data[]);
|
||||
virtual int closewaveoutput();
|
||||
|
||||
virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh);
|
||||
virtual int startwaverecord(bx_pcm_param_t *param);
|
||||
virtual int getwavepacket(int length, Bit8u data[]);
|
||||
@ -57,18 +71,12 @@ public:
|
||||
private:
|
||||
int alsa_seq_open(const char *alsadev);
|
||||
int alsa_seq_output(int delta, int command, int length, Bit8u data[]);
|
||||
int alsa_pcm_open(bx_bool input, bx_pcm_param_t *param);
|
||||
|
||||
struct {
|
||||
snd_seq_t *handle;
|
||||
int source_port;
|
||||
} alsa_seq;
|
||||
struct {
|
||||
snd_pcm_t *handle;
|
||||
snd_pcm_uframes_t frames;
|
||||
int alsa_bufsize, audio_bufsize;
|
||||
char *buffer;
|
||||
} alsa_pcm[2];
|
||||
alsa_pcm_t alsa_wavein;
|
||||
bx_pcm_param_t wavein_param;
|
||||
Bit8u audio_buffer[BX_SOUND_ALSA_BUFSIZE];
|
||||
};
|
||||
|
@ -38,23 +38,135 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/soundcard.h>
|
||||
|
||||
// bx_soundlow_waveout_oss_c class implemenzation
|
||||
|
||||
bx_soundlow_waveout_oss_c::bx_soundlow_waveout_oss_c()
|
||||
:bx_soundlow_waveout_c()
|
||||
{
|
||||
waveout_fd = -1;
|
||||
}
|
||||
|
||||
bx_soundlow_waveout_oss_c::~bx_soundlow_waveout_oss_c()
|
||||
{
|
||||
if (waveout_fd != -1) {
|
||||
close(waveout_fd);
|
||||
waveout_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_oss_c::openwaveoutput(const char *wavedev)
|
||||
{
|
||||
if (waveout_fd == -1) {
|
||||
waveout_fd = open(wavedev, O_WRONLY);
|
||||
if (waveout_fd == -1) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
} else {
|
||||
BX_INFO(("OSS: opened output device %s", wavedev));
|
||||
}
|
||||
}
|
||||
set_pcm_params(&real_pcm_param);
|
||||
pcm_callback_id = register_wave_callback(this, pcm_callback);
|
||||
BX_INIT_MUTEX(mixer_mutex);
|
||||
start_mixer_thread();
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_oss_c::set_pcm_params(bx_pcm_param_t *param)
|
||||
{
|
||||
int fmt, ret;
|
||||
int frequency = param->samplerate;
|
||||
int channels = param->channels;
|
||||
int signeddata = param->format & 1;
|
||||
|
||||
BX_DEBUG(("set_pcm_params(): %u, %u, %u, %02x", param->samplerate, param->bits,
|
||||
param->channels, param->format));
|
||||
|
||||
if (waveout_fd == -1) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
if (param->bits == 16) {
|
||||
if (signeddata == 1) {
|
||||
fmt = AFMT_S16_LE;
|
||||
} else {
|
||||
fmt = AFMT_U16_LE;
|
||||
}
|
||||
} else if (param->bits == 8) {
|
||||
if (signeddata == 1) {
|
||||
fmt = AFMT_S8;
|
||||
} else {
|
||||
fmt = AFMT_U8;
|
||||
}
|
||||
} else {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
// set frequency etc.
|
||||
ret = ioctl(waveout_fd, SNDCTL_DSP_RESET);
|
||||
if (ret != 0)
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_RESET): %s", strerror(errno)));
|
||||
|
||||
/*
|
||||
ret = ioctl(waveout_fd], SNDCTL_DSP_SETFRAGMENT, &fragment);
|
||||
if (ret != 0)
|
||||
BX_DEBUG(("ioctl(SNDCTL_DSP_SETFRAGMENT, %d): %s",
|
||||
fragment, strerror(errno)));
|
||||
*/
|
||||
|
||||
ret = ioctl(waveout_fd, SNDCTL_DSP_SETFMT, &fmt);
|
||||
if (ret != 0) { // abort if the format is unknown, to avoid playing noise
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_SETFMT, %d): %s",
|
||||
fmt, strerror(errno)));
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
ret = ioctl(waveout_fd, SNDCTL_DSP_CHANNELS, &channels);
|
||||
if (ret != 0)
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_CHANNELS, %d): %s",
|
||||
channels, strerror(errno)));
|
||||
|
||||
ret = ioctl(waveout_fd, SNDCTL_DSP_SPEED, &frequency);
|
||||
if (ret != 0)
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_SPEED, %d): %s",
|
||||
frequency, strerror(errno)));
|
||||
|
||||
// ioctl(wave_fd[0], SNDCTL_DSP_GETBLKSIZE, &fragment);
|
||||
// BX_DEBUG(("current output block size is %d", fragment));
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_oss_c::output(int length, Bit8u data[])
|
||||
{
|
||||
int odelay, delay;
|
||||
|
||||
if (waveout_fd == -1) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
if (write(waveout_fd, data, length) == length) {
|
||||
ioctl(waveout_fd, SNDCTL_DSP_GETODELAY, &odelay);
|
||||
delay = odelay * 1000 / (real_pcm_param.samplerate * 4);
|
||||
BX_MSLEEP(delay);
|
||||
return BX_SOUNDLOW_OK;
|
||||
} else {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
// bx_sound_oss_c class implemenzation
|
||||
|
||||
bx_sound_oss_c::bx_sound_oss_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
{
|
||||
midi = NULL;
|
||||
wave_fd[0] = -1;
|
||||
wave_fd[1] = -1;
|
||||
wavein_fd = -1;
|
||||
BX_INFO(("Sound lowlevel module 'oss' initialized"));
|
||||
}
|
||||
|
||||
bx_sound_oss_c::~bx_sound_oss_c()
|
||||
bx_soundlow_waveout_c* bx_sound_oss_c::get_waveout()
|
||||
{
|
||||
// nothing for now
|
||||
}
|
||||
|
||||
int bx_sound_oss_c::midiready()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
if (waveout == NULL) {
|
||||
waveout = new bx_soundlow_waveout_oss_c();
|
||||
}
|
||||
return waveout;
|
||||
}
|
||||
|
||||
int bx_sound_oss_c::openmidioutput(const char *mididev)
|
||||
@ -74,6 +186,11 @@ int bx_sound_oss_c::openmidioutput(const char *mididev)
|
||||
}
|
||||
|
||||
|
||||
int bx_sound_oss_c::midiready()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_oss_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
|
||||
{
|
||||
UNUSED(delta);
|
||||
@ -85,7 +202,6 @@ int bx_sound_oss_c::sendmidicommand(int delta, int command, int length, Bit8u da
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
|
||||
int bx_sound_oss_c::closemidioutput()
|
||||
{
|
||||
fclose(midi);
|
||||
@ -93,113 +209,6 @@ int bx_sound_oss_c::closemidioutput()
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
|
||||
int bx_sound_oss_c::openwaveoutput(const char *wavedev)
|
||||
{
|
||||
if (wave_fd[0] == -1) {
|
||||
wave_fd[0] = open(wavedev, O_WRONLY);
|
||||
if (wave_fd[0] == -1) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
} else {
|
||||
BX_INFO(("OSS: opened output device %s", wavedev));
|
||||
}
|
||||
}
|
||||
set_pcm_params(real_pcm_param);
|
||||
pcm_callback_id = register_wave_callback(this, pcm_callback);
|
||||
BX_INIT_MUTEX(mixer_mutex);
|
||||
start_mixer_thread();
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_oss_c::set_pcm_params(bx_pcm_param_t param)
|
||||
{
|
||||
int fmt, ret;
|
||||
int frequency = param.samplerate;
|
||||
int channels = param.channels;
|
||||
int signeddata = param.format & 1;
|
||||
|
||||
BX_DEBUG(("set_pcm_params(): %u, %u, %u, %02x", param.samplerate, param.bits,
|
||||
param.channels, param.format));
|
||||
|
||||
if (wave_fd[0] == -1) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
if (param.bits == 16) {
|
||||
if (signeddata == 1) {
|
||||
fmt = AFMT_S16_LE;
|
||||
} else {
|
||||
fmt = AFMT_U16_LE;
|
||||
}
|
||||
} else if (param.bits == 8) {
|
||||
if (signeddata == 1) {
|
||||
fmt = AFMT_S8;
|
||||
} else {
|
||||
fmt = AFMT_U8;
|
||||
}
|
||||
} else {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
// set frequency etc.
|
||||
ret = ioctl(wave_fd[0], SNDCTL_DSP_RESET);
|
||||
if (ret != 0)
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_RESET): %s", strerror(errno)));
|
||||
|
||||
/*
|
||||
ret = ioctl(wave_fd[0], SNDCTL_DSP_SETFRAGMENT, &fragment);
|
||||
if (ret != 0)
|
||||
BX_DEBUG(("ioctl(SNDCTL_DSP_SETFRAGMENT, %d): %s",
|
||||
fragment, strerror(errno)));
|
||||
*/
|
||||
|
||||
ret = ioctl(wave_fd[0], SNDCTL_DSP_SETFMT, &fmt);
|
||||
if (ret != 0) { // abort if the format is unknown, to avoid playing noise
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_SETFMT, %d): %s",
|
||||
fmt, strerror(errno)));
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
ret = ioctl(wave_fd[0], SNDCTL_DSP_CHANNELS, &channels);
|
||||
if (ret != 0)
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_CHANNELS, %d): %s",
|
||||
channels, strerror(errno)));
|
||||
|
||||
ret = ioctl(wave_fd[0], SNDCTL_DSP_SPEED, &frequency);
|
||||
if (ret != 0)
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_SPEED, %d): %s",
|
||||
frequency, strerror(errno)));
|
||||
|
||||
// ioctl(wave_fd[0], SNDCTL_DSP_GETBLKSIZE, &fragment);
|
||||
// BX_DEBUG(("current output block size is %d", fragment));
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_oss_c::waveout(int length, Bit8u data[])
|
||||
{
|
||||
int odelay, delay;
|
||||
|
||||
if (wave_fd[0] == -1) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
if (write(wave_fd[0], data, length) == length) {
|
||||
ioctl(wave_fd[0], SNDCTL_DSP_GETODELAY, &odelay);
|
||||
delay = odelay * 1000 / (real_pcm_param.samplerate * 4);
|
||||
BX_MSLEEP(delay);
|
||||
return BX_SOUNDLOW_OK;
|
||||
} else {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
int bx_sound_oss_c::closewaveoutput()
|
||||
{
|
||||
if (wave_fd[0] != -1) {
|
||||
close(wave_fd[0]);
|
||||
wave_fd[0] = -1;
|
||||
}
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_oss_c::openwaveinput(const char *wavedev, sound_record_handler_t rh)
|
||||
{
|
||||
record_handler = rh;
|
||||
@ -207,9 +216,9 @@ int bx_sound_oss_c::openwaveinput(const char *wavedev, sound_record_handler_t rh
|
||||
record_timer_index = bx_pc_system.register_timer(this, record_timer_handler, 1, 1, 0, "soundlnx");
|
||||
// record timer: inactive, continuous, frequency variable
|
||||
}
|
||||
if (wave_fd[1] == -1) {
|
||||
wave_fd[1] = open(wavedev, O_RDONLY);
|
||||
if (wave_fd[1] == -1) {
|
||||
if (wavein_fd == -1) {
|
||||
wavein_fd = open(wavedev, O_RDONLY);
|
||||
if (wavein_fd == -1) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
} else {
|
||||
BX_INFO(("OSS: opened input device %s", wavedev));
|
||||
@ -238,7 +247,7 @@ int bx_sound_oss_c::startwaverecord(bx_pcm_param_t *param)
|
||||
timer_val = (Bit64u)record_packet_size * 1000000 / (param->samplerate << shift);
|
||||
bx_pc_system.activate_timer(record_timer_index, (Bit32u)timer_val, 1);
|
||||
}
|
||||
if (wave_fd[1] == -1) {
|
||||
if (wavein_fd == -1) {
|
||||
return BX_SOUNDLOW_ERR;
|
||||
} else {
|
||||
if (memcmp(param, &wavein_param, sizeof(bx_pcm_param_t)) == 0) {
|
||||
@ -264,25 +273,25 @@ int bx_sound_oss_c::startwaverecord(bx_pcm_param_t *param)
|
||||
}
|
||||
|
||||
// set frequency etc.
|
||||
ret = ioctl(wave_fd[1], SNDCTL_DSP_RESET);
|
||||
ret = ioctl(wavein_fd, SNDCTL_DSP_RESET);
|
||||
if (ret != 0)
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_RESET): %s", strerror(errno)));
|
||||
|
||||
ret = ioctl(wave_fd[1], SNDCTL_DSP_SETFMT, &fmt);
|
||||
ret = ioctl(wavein_fd, SNDCTL_DSP_SETFMT, &fmt);
|
||||
if (ret != 0) { // abort if the format is unknown, to avoid playing noise
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_SETFMT, %d): %s",
|
||||
fmt, strerror(errno)));
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
ret = ioctl(wave_fd[1], SNDCTL_DSP_CHANNELS, &channels);
|
||||
ret = ioctl(wavein_fd, SNDCTL_DSP_CHANNELS, &channels);
|
||||
if (ret != 0) {
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_CHANNELS, %d): %s",
|
||||
channels, strerror(errno)));
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
ret = ioctl(wave_fd[1], SNDCTL_DSP_SPEED, &frequency);
|
||||
ret = ioctl(wavein_fd, SNDCTL_DSP_SPEED, &frequency);
|
||||
if (ret != 0) {
|
||||
BX_ERROR(("ioctl(SNDCTL_DSP_SPEED, %d): %s",
|
||||
frequency, strerror(errno)));
|
||||
@ -296,7 +305,7 @@ int bx_sound_oss_c::getwavepacket(int length, Bit8u data[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = read(wave_fd[1], data, length);
|
||||
ret = read(wavein_fd, data, length);
|
||||
|
||||
if (ret == length) {
|
||||
return BX_SOUNDLOW_OK;
|
||||
@ -318,9 +327,9 @@ int bx_sound_oss_c::closewaveinput()
|
||||
{
|
||||
stopwaverecord();
|
||||
|
||||
if (wave_fd[1] != -1) {
|
||||
close(wave_fd[1]);
|
||||
wave_fd[1] = -1;
|
||||
if (wavein_fd != -1) {
|
||||
close(wavein_fd);
|
||||
wavein_fd = -1;
|
||||
}
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
@ -25,23 +25,30 @@
|
||||
|
||||
#if (defined(linux) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__))
|
||||
|
||||
class bx_soundlow_waveout_oss_c : public bx_soundlow_waveout_c {
|
||||
public:
|
||||
bx_soundlow_waveout_oss_c();
|
||||
virtual ~bx_soundlow_waveout_oss_c();
|
||||
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t *param);
|
||||
virtual int output(int length, Bit8u data[]);
|
||||
private:
|
||||
int waveout_fd;
|
||||
};
|
||||
|
||||
class bx_sound_oss_c : public bx_sound_lowlevel_c {
|
||||
public:
|
||||
bx_sound_oss_c();
|
||||
virtual ~bx_sound_oss_c();
|
||||
virtual ~bx_sound_oss_c() {}
|
||||
|
||||
virtual int get_type() {return BX_SOUNDLOW_OSS;}
|
||||
virtual bx_soundlow_waveout_c* get_waveout();
|
||||
|
||||
virtual int openmidioutput(const char *mididev);
|
||||
virtual int midiready();
|
||||
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
|
||||
virtual int closemidioutput();
|
||||
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t param);
|
||||
virtual int waveout(int length, Bit8u data[]);
|
||||
virtual int closewaveoutput();
|
||||
|
||||
virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh);
|
||||
virtual int startwaverecord(bx_pcm_param_t *param);
|
||||
virtual int getwavepacket(int length, Bit8u data[]);
|
||||
@ -52,7 +59,7 @@ public:
|
||||
void record_timer(void);
|
||||
private:
|
||||
FILE *midi;
|
||||
int wave_fd[2];
|
||||
int wavein_fd;
|
||||
bx_pcm_param_t wavein_param;
|
||||
};
|
||||
|
||||
|
@ -111,14 +111,14 @@ BX_THREAD_FUNC(mixer_thread, indata)
|
||||
{
|
||||
int len;
|
||||
|
||||
bx_sound_lowlevel_c *soundmod = (bx_sound_lowlevel_c*)indata;
|
||||
bx_soundlow_waveout_c *waveout = (bx_soundlow_waveout_c*)indata;
|
||||
Bit8u *mixbuffer = new Bit8u[BX_SOUNDLOW_WAVEPACKETSIZE];
|
||||
mixer_control = 1;
|
||||
while (mixer_control > 0) {
|
||||
len = soundmod->get_waveout_packetsize();
|
||||
len = waveout->get_packetsize();
|
||||
memset(mixbuffer, 0, len);
|
||||
if (soundmod->mixer_common(mixbuffer, len)) {
|
||||
soundmod->waveout(len, mixbuffer);
|
||||
if (waveout->mixer_common(mixbuffer, len)) {
|
||||
waveout->output(len, mixbuffer);
|
||||
} else {
|
||||
BX_MSLEEP(25);
|
||||
}
|
||||
@ -128,21 +128,21 @@ BX_THREAD_FUNC(mixer_thread, indata)
|
||||
BX_THREAD_EXIT;
|
||||
}
|
||||
|
||||
// The base class of the sound lowlevel support.
|
||||
// bx_soundlow_waveout_c class implemenzation
|
||||
// The dummy output methods don't do anything.
|
||||
|
||||
bx_sound_lowlevel_c::bx_sound_lowlevel_c()
|
||||
bx_soundlow_waveout_c::bx_soundlow_waveout_c()
|
||||
{
|
||||
put("soundlow", "SNDLOW");
|
||||
record_timer_index = BX_NULL_TIMER_HANDLE;
|
||||
put("waveout", "WAVOUT");
|
||||
real_pcm_param = default_pcm_param;
|
||||
emu_pcm_param = default_pcm_param;
|
||||
cb_count = 0;
|
||||
pcm_callback_id = -1;
|
||||
mixer_control = 0;
|
||||
set_pcm_params(&real_pcm_param);
|
||||
}
|
||||
|
||||
bx_sound_lowlevel_c::~bx_sound_lowlevel_c()
|
||||
bx_soundlow_waveout_c::~bx_soundlow_waveout_c()
|
||||
{
|
||||
unregister_wave_callback(pcm_callback_id);
|
||||
if (mixer_control > 0) {
|
||||
@ -154,47 +154,113 @@ bx_sound_lowlevel_c::~bx_sound_lowlevel_c()
|
||||
BX_FINI_MUTEX(mixer_mutex);
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::openmidioutput(const char *mididev)
|
||||
{
|
||||
UNUSED(mididev);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::midiready()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
|
||||
{
|
||||
UNUSED(delta);
|
||||
UNUSED(command);
|
||||
UNUSED(length);
|
||||
UNUSED(data);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::closemidioutput()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
// wave playback support
|
||||
|
||||
int bx_sound_lowlevel_c::openwaveoutput(const char *wavedev)
|
||||
int bx_soundlow_waveout_c::openwaveoutput(const char *wavedev)
|
||||
{
|
||||
UNUSED(wavedev);
|
||||
set_pcm_params(real_pcm_param);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::set_pcm_params(bx_pcm_param_t param)
|
||||
int bx_soundlow_waveout_c::set_pcm_params(bx_pcm_param_t *param)
|
||||
{
|
||||
UNUSED(param);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
void bx_sound_lowlevel_c::convert_pcm_data(Bit8u *src, int srcsize, Bit8u *dst, int dstsize, bx_pcm_param_t *param)
|
||||
int bx_soundlow_waveout_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param)
|
||||
{
|
||||
int len2;
|
||||
|
||||
if (memcmp(src_param, &emu_pcm_param, sizeof(bx_pcm_param_t)) != 0) {
|
||||
emu_pcm_param = *src_param;
|
||||
cvt_mult = (src_param->bits == 8) ? 2 : 1;
|
||||
if (src_param->channels == 1) cvt_mult <<= 1;
|
||||
if (src_param->samplerate != real_pcm_param.samplerate) {
|
||||
real_pcm_param.samplerate = src_param->samplerate;
|
||||
set_pcm_params(&real_pcm_param);
|
||||
}
|
||||
}
|
||||
len2 = length * cvt_mult;
|
||||
BX_LOCK(mixer_mutex);
|
||||
audio_buffer_t *newbuffer = new_audio_buffer(len2);
|
||||
convert_pcm_data(data, length, newbuffer->data, len2, src_param);
|
||||
BX_UNLOCK(mixer_mutex);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_c::get_packetsize()
|
||||
{
|
||||
return (real_pcm_param.samplerate * 4 / 10);
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_c::output(int length, Bit8u data[])
|
||||
{
|
||||
UNUSED(length);
|
||||
UNUSED(data);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_soundlow_waveout_c::register_wave_callback(void *arg, get_wave_cb_t wd_cb)
|
||||
{
|
||||
if (cb_count < BX_MAX_WAVE_CALLBACKS) {
|
||||
get_wave[cb_count].device = arg;
|
||||
get_wave[cb_count].cb = wd_cb;
|
||||
return cb_count++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bx_soundlow_waveout_c::unregister_wave_callback(int callback_id)
|
||||
{
|
||||
BX_LOCK(mixer_mutex);
|
||||
if ((callback_id >= 0) && (callback_id < BX_MAX_WAVE_CALLBACKS)) {
|
||||
get_wave[callback_id].device = NULL;
|
||||
get_wave[callback_id].cb = NULL;
|
||||
}
|
||||
BX_UNLOCK(mixer_mutex);
|
||||
}
|
||||
|
||||
bx_bool bx_soundlow_waveout_c::mixer_common(Bit8u *buffer, int len)
|
||||
{
|
||||
Bit32u count, len2 = 0, len3 = 0;
|
||||
Bit16s src1, src2, dst_val;
|
||||
Bit32s tmp_val;
|
||||
Bit8u *src, *dst;
|
||||
|
||||
Bit8u *tmpbuffer = new Bit8u[len];
|
||||
BX_LOCK(mixer_mutex);
|
||||
for (int i = 0; i < cb_count; i++) {
|
||||
if (get_wave[i].cb != NULL) {
|
||||
memset(tmpbuffer, 0, len);
|
||||
len2 = get_wave[i].cb(get_wave[i].device, real_pcm_param.samplerate, tmpbuffer, len);
|
||||
if (len2 > 0) {
|
||||
src = tmpbuffer;
|
||||
dst = buffer;
|
||||
count = len / 2;
|
||||
while (count--) {
|
||||
src1 = (src[0] | (src[1] << 8));
|
||||
src2 = (dst[0] | (dst[1] << 8));
|
||||
tmp_val = (Bit32s)src1 + (Bit32s)src2;
|
||||
if (tmp_val > BX_MAX_BIT16S) {
|
||||
tmp_val = BX_MAX_BIT16S;
|
||||
} else if (tmp_val < BX_MIN_BIT16S) {
|
||||
tmp_val = BX_MIN_BIT16S;
|
||||
}
|
||||
dst_val = (Bit16s)tmp_val;
|
||||
dst[0] = dst_val & 0xff;
|
||||
dst[1] = (Bit8u)(dst_val >> 8);
|
||||
src += 2;
|
||||
dst += 2;
|
||||
}
|
||||
if (len3 < len2) len3 = len2;
|
||||
}
|
||||
}
|
||||
}
|
||||
BX_UNLOCK(mixer_mutex);
|
||||
delete [] tmpbuffer;
|
||||
return (len3 > 0);
|
||||
}
|
||||
|
||||
void bx_soundlow_waveout_c::convert_pcm_data(Bit8u *src, int srcsize, Bit8u *dst, int dstsize, bx_pcm_param_t *param)
|
||||
{
|
||||
int i, j;
|
||||
Bit8u xor_val;
|
||||
@ -250,115 +316,64 @@ void bx_sound_lowlevel_c::convert_pcm_data(Bit8u *src, int srcsize, Bit8u *dst,
|
||||
}
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param)
|
||||
{
|
||||
int len2;
|
||||
|
||||
if (memcmp(src_param, &emu_pcm_param, sizeof(bx_pcm_param_t)) != 0) {
|
||||
emu_pcm_param = *src_param;
|
||||
cvt_mult = (src_param->bits == 8) ? 2 : 1;
|
||||
if (src_param->channels == 1) cvt_mult <<= 1;
|
||||
if (src_param->samplerate != real_pcm_param.samplerate) {
|
||||
real_pcm_param.samplerate = src_param->samplerate;
|
||||
set_pcm_params(real_pcm_param);
|
||||
}
|
||||
}
|
||||
len2 = length * cvt_mult;
|
||||
BX_LOCK(mixer_mutex);
|
||||
audio_buffer_t *newbuffer = new_audio_buffer(len2);
|
||||
convert_pcm_data(data, length, newbuffer->data, len2, src_param);
|
||||
BX_UNLOCK(mixer_mutex);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::get_waveout_packetsize()
|
||||
{
|
||||
return (real_pcm_param.samplerate * 4 / 10);
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::waveout(int length, Bit8u data[])
|
||||
{
|
||||
UNUSED(length);
|
||||
UNUSED(data);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::closewaveoutput()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
// mixer thread related methods
|
||||
|
||||
void bx_sound_lowlevel_c::start_mixer_thread()
|
||||
void bx_soundlow_waveout_c::start_mixer_thread()
|
||||
{
|
||||
BX_THREAD_ID(threadID);
|
||||
|
||||
BX_THREAD_CREATE(mixer_thread, this, threadID);
|
||||
}
|
||||
|
||||
bx_bool bx_sound_lowlevel_c::mixer_common(Bit8u *buffer, int len)
|
||||
{
|
||||
Bit32u count, len2 = 0, len3 = 0;
|
||||
Bit16s src1, src2, dst_val;
|
||||
Bit32s tmp_val;
|
||||
Bit8u *src, *dst;
|
||||
// bx_sound_lowlevel_c class implemenzation
|
||||
// This is the base class of the sound lowlevel support.
|
||||
|
||||
Bit8u *tmpbuffer = new Bit8u[len];
|
||||
BX_LOCK(mixer_mutex);
|
||||
for (int i = 0; i < cb_count; i++) {
|
||||
if (get_wave[i].cb != NULL) {
|
||||
memset(tmpbuffer, 0, len);
|
||||
len2 = get_wave[i].cb(get_wave[i].device, real_pcm_param.samplerate, tmpbuffer, len);
|
||||
if (len2 > 0) {
|
||||
src = tmpbuffer;
|
||||
dst = buffer;
|
||||
count = len / 2;
|
||||
while (count--) {
|
||||
src1 = (src[0] | (src[1] << 8));
|
||||
src2 = (dst[0] | (dst[1] << 8));
|
||||
tmp_val = (Bit32s)src1 + (Bit32s)src2;
|
||||
if (tmp_val > BX_MAX_BIT16S) {
|
||||
tmp_val = BX_MAX_BIT16S;
|
||||
} else if (tmp_val < BX_MIN_BIT16S) {
|
||||
tmp_val = BX_MIN_BIT16S;
|
||||
}
|
||||
dst_val = (Bit16s)tmp_val;
|
||||
dst[0] = dst_val & 0xff;
|
||||
dst[1] = (Bit8u)(dst_val >> 8);
|
||||
src += 2;
|
||||
dst += 2;
|
||||
}
|
||||
if (len3 < len2) len3 = len2;
|
||||
}
|
||||
}
|
||||
}
|
||||
BX_UNLOCK(mixer_mutex);
|
||||
delete [] tmpbuffer;
|
||||
return (len3 > 0);
|
||||
bx_sound_lowlevel_c::bx_sound_lowlevel_c()
|
||||
{
|
||||
put("soundlow", "SNDLOW");
|
||||
waveout = NULL;
|
||||
record_timer_index = BX_NULL_TIMER_HANDLE;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::register_wave_callback(void *arg, get_wave_cb_t wd_cb)
|
||||
bx_sound_lowlevel_c::~bx_sound_lowlevel_c()
|
||||
{
|
||||
if (cb_count < BX_MAX_WAVE_CALLBACKS) {
|
||||
get_wave[cb_count].device = arg;
|
||||
get_wave[cb_count].cb = wd_cb;
|
||||
return cb_count++;
|
||||
if (waveout != NULL) {
|
||||
delete waveout;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bx_sound_lowlevel_c::unregister_wave_callback(int callback_id)
|
||||
bx_soundlow_waveout_c* bx_sound_lowlevel_c::get_waveout()
|
||||
{
|
||||
BX_LOCK(mixer_mutex);
|
||||
if ((callback_id >= 0) && (callback_id < BX_MAX_WAVE_CALLBACKS)) {
|
||||
get_wave[callback_id].device = NULL;
|
||||
get_wave[callback_id].cb = NULL;
|
||||
if (waveout == NULL) {
|
||||
waveout = new bx_soundlow_waveout_c();
|
||||
}
|
||||
BX_UNLOCK(mixer_mutex);
|
||||
return waveout;
|
||||
}
|
||||
|
||||
// wave recording support (dummy driver returns silence
|
||||
int bx_sound_lowlevel_c::openmidioutput(const char *mididev)
|
||||
{
|
||||
UNUSED(mididev);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::midiready()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
|
||||
{
|
||||
UNUSED(delta);
|
||||
UNUSED(command);
|
||||
UNUSED(length);
|
||||
UNUSED(data);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_lowlevel_c::closemidioutput()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
// wave recording support (dummy driver returns silence)
|
||||
|
||||
int bx_sound_lowlevel_c::openwaveinput(const char *wavedev, sound_record_handler_t rh)
|
||||
{
|
||||
|
@ -28,14 +28,6 @@
|
||||
#define BX_SOUNDLOW_OK 0
|
||||
#define BX_SOUNDLOW_ERR 1
|
||||
|
||||
// Lowlvel sound modules
|
||||
#define BX_SOUNDLOW_DUMMY 0
|
||||
#define BX_SOUNDLOW_OSS 1
|
||||
#define BX_SOUNDLOW_OSX 2
|
||||
#define BX_SOUNDLOW_WIN 3
|
||||
#define BX_SOUNDLOW_SDL 4
|
||||
#define BX_SOUNDLOW_ALSA 5
|
||||
|
||||
#define BX_MAX_WAVE_CALLBACKS 3
|
||||
|
||||
typedef struct {
|
||||
@ -68,42 +60,18 @@ Bit32u pcm_callback(void *dev, Bit16u rate, Bit8u *buffer, Bit32u len);
|
||||
|
||||
extern BX_MUTEX(mixer_mutex);
|
||||
|
||||
// The class with the input/output functions
|
||||
class bx_sound_lowlevel_c : public logfunctions {
|
||||
// the waveout class
|
||||
|
||||
class bx_soundlow_waveout_c : public logfunctions {
|
||||
public:
|
||||
|
||||
/*
|
||||
These functions are the sound lowlevel functions, sending
|
||||
the music or sending/receiving sound to/from the OS specific driver.
|
||||
They are in a different file (soundxxx.cc) because they are
|
||||
non-portable, while everything in the soundcard code is portable
|
||||
*/
|
||||
|
||||
bx_sound_lowlevel_c();
|
||||
virtual ~bx_sound_lowlevel_c();
|
||||
|
||||
virtual int get_type() {return BX_SOUNDLOW_DUMMY;}
|
||||
|
||||
virtual int openmidioutput(const char *mididev);
|
||||
virtual int midiready();
|
||||
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
|
||||
virtual int closemidioutput();
|
||||
bx_soundlow_waveout_c();
|
||||
virtual ~bx_soundlow_waveout_c();
|
||||
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t param);
|
||||
virtual int set_pcm_params(bx_pcm_param_t *param);
|
||||
virtual int sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param);
|
||||
virtual int get_waveout_packetsize();
|
||||
virtual int waveout(int length, Bit8u data[]);
|
||||
virtual int closewaveoutput();
|
||||
|
||||
virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh);
|
||||
virtual int startwaverecord(bx_pcm_param_t *param);
|
||||
virtual int getwavepacket(int length, Bit8u data[]);
|
||||
virtual int stopwaverecord();
|
||||
virtual int closewaveinput();
|
||||
|
||||
static void record_timer_handler(void *);
|
||||
void record_timer(void);
|
||||
virtual int get_packetsize();
|
||||
virtual int output(int length, Bit8u data[]);
|
||||
|
||||
virtual int register_wave_callback(void *, get_wave_cb_t wd_cb);
|
||||
virtual void unregister_wave_callback(int callback_id);
|
||||
@ -122,6 +90,39 @@ protected:
|
||||
get_wave_cb_t cb;
|
||||
} get_wave[BX_MAX_WAVE_CALLBACKS];
|
||||
int pcm_callback_id;
|
||||
};
|
||||
|
||||
// The class with the input/output functions
|
||||
class bx_sound_lowlevel_c : public logfunctions {
|
||||
public:
|
||||
|
||||
/*
|
||||
These functions are the sound lowlevel functions, sending
|
||||
the music or sending/receiving sound to/from the OS specific driver.
|
||||
They are in a different file (soundxxx.cc) because they are
|
||||
non-portable, while everything in the soundcard code is portable
|
||||
*/
|
||||
|
||||
bx_sound_lowlevel_c();
|
||||
virtual ~bx_sound_lowlevel_c();
|
||||
|
||||
virtual bx_soundlow_waveout_c* get_waveout();
|
||||
|
||||
virtual int openmidioutput(const char *mididev);
|
||||
virtual int midiready();
|
||||
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
|
||||
virtual int closemidioutput();
|
||||
|
||||
virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh);
|
||||
virtual int startwaverecord(bx_pcm_param_t *param);
|
||||
virtual int getwavepacket(int length, Bit8u data[]);
|
||||
virtual int stopwaverecord();
|
||||
virtual int closewaveinput();
|
||||
|
||||
static void record_timer_handler(void *);
|
||||
void record_timer(void);
|
||||
protected:
|
||||
bx_soundlow_waveout_c *waveout;
|
||||
|
||||
int record_timer_index;
|
||||
int record_packet_size;
|
||||
|
@ -72,25 +72,26 @@ bx_soundmod_ctl_c::bx_soundmod_ctl_c()
|
||||
{
|
||||
put("soundctl", "SNDCTL");
|
||||
soundmod = NULL;
|
||||
waveout = NULL;
|
||||
}
|
||||
|
||||
bx_soundmod_ctl_c::~bx_soundmod_ctl_c()
|
||||
{
|
||||
beep_active = 0;
|
||||
if (beep_callback_id >= 0) {
|
||||
soundmod->unregister_wave_callback(beep_callback_id);
|
||||
}
|
||||
if (soundmod != NULL) {
|
||||
soundmod->closewaveoutput();
|
||||
if (waveout != NULL) {
|
||||
if (beep_callback_id >= 0) {
|
||||
waveout->unregister_wave_callback(beep_callback_id);
|
||||
}
|
||||
}
|
||||
delete soundmod;
|
||||
}
|
||||
|
||||
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 *waveout = SIM->get_param_string(BXPN_SOUND_WAVEOUT)->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) {
|
||||
@ -124,16 +125,21 @@ void bx_soundmod_ctl_c::init()
|
||||
return;
|
||||
}
|
||||
if (!strlen(wavein)) {
|
||||
SIM->get_param_string(BXPN_SOUND_WAVEIN)->set(waveout);
|
||||
SIM->get_param_string(BXPN_SOUND_WAVEIN)->set(pwaveout);
|
||||
}
|
||||
int ret = soundmod->openwaveoutput(waveout);
|
||||
if (ret != BX_SOUNDLOW_OK) {
|
||||
BX_PANIC(("Could not open wave output device"));
|
||||
waveout = soundmod->get_waveout();
|
||||
if (waveout != NULL) {
|
||||
ret = waveout->openwaveoutput(pwaveout);
|
||||
if (ret != BX_SOUNDLOW_OK) {
|
||||
BX_PANIC(("Could not open wave output device"));
|
||||
} else {
|
||||
beep_active = 0;
|
||||
beep_cur_freq = 0.0;
|
||||
BX_INIT_MUTEX(beep_mutex);
|
||||
beep_callback_id = waveout->register_wave_callback(theSoundModCtl, beep_callback);
|
||||
}
|
||||
} else {
|
||||
beep_active = 0;
|
||||
beep_cur_freq = 0.0;
|
||||
BX_INIT_MUTEX(beep_mutex);
|
||||
beep_callback_id = soundmod->register_wave_callback(theSoundModCtl, beep_callback);
|
||||
BX_PANIC(("no waveout support in sound driver '%s'", driver));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
// Common code for sound lowlevel modules
|
||||
|
||||
class bx_sound_lowlevel_c;
|
||||
class bx_soundlow_waveout_c;
|
||||
|
||||
// Pseudo device that loads the lowlevel sound module
|
||||
class bx_soundmod_ctl_c : public bx_soundmod_ctl_stub_c {
|
||||
@ -37,6 +38,7 @@ public:
|
||||
Bit32u beep_generator(Bit16u rate, Bit8u *buffer, Bit32u len);
|
||||
private:
|
||||
bx_sound_lowlevel_c *soundmod;
|
||||
bx_soundlow_waveout_c *waveout;
|
||||
int beep_callback_id;
|
||||
bx_bool beep_active;
|
||||
float beep_cur_freq;
|
||||
|
@ -76,110 +76,36 @@ AudioUnit WaveOutputUnit = NULL;
|
||||
AudioConverterRef WaveConverter = NULL;
|
||||
#endif
|
||||
|
||||
bx_sound_osx_c::bx_sound_osx_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
// bx_soundlow_waveout_osx_c class implemenzation
|
||||
|
||||
bx_soundlow_waveout_osx_c::bx_soundlow_waveout_osx_c()
|
||||
:bx_soundlow_waveout_c()
|
||||
{
|
||||
MidiOpen = 0;
|
||||
WaveOpen = 0;
|
||||
head = 0;
|
||||
tail = 0;
|
||||
for (int i=0; i<BX_SOUND_OSX_NBUF; i++)
|
||||
WaveLength[i] = 0;
|
||||
BX_INFO(("Sound lowlevel module 'osx' initialized"));
|
||||
WaveOpen = 0;
|
||||
head = 0;
|
||||
tail = 0;
|
||||
for (int i=0; i<BX_SOUND_OSX_NBUF; i++)
|
||||
WaveLength[i] = 0;
|
||||
}
|
||||
|
||||
bx_sound_osx_c::~bx_sound_osx_c()
|
||||
{
|
||||
// nothing for now
|
||||
}
|
||||
|
||||
|
||||
int bx_sound_osx_c::midiready()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::openmidioutput(const char *mididev)
|
||||
bx_soundlow_waveout_osx_c::~bx_soundlow_waveout_osx_c()
|
||||
{
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
ComponentDescription description;
|
||||
AUNode synthNode, outputNode;
|
||||
|
||||
// Create the graph
|
||||
NewAUGraph (&MidiGraph);
|
||||
|
||||
// Open the DLS Synth
|
||||
description.componentType = kAudioUnitType_MusicDevice;
|
||||
description.componentSubType = kAudioUnitSubType_DLSSynth;
|
||||
description.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
description.componentFlags = 0;
|
||||
description.componentFlagsMask = 0;
|
||||
AUGraphNewNode (MidiGraph, &description, 0, NULL, &synthNode);
|
||||
|
||||
// Open the output device
|
||||
description.componentType = kAudioUnitType_Output;
|
||||
description.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||
description.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
description.componentFlags = 0;
|
||||
description.componentFlagsMask = 0;
|
||||
AUGraphNewNode (MidiGraph, &description, 0, NULL, &outputNode);
|
||||
|
||||
// Connect the devices up
|
||||
AUGraphConnectNodeInput (MidiGraph, synthNode, 1, outputNode, 0);
|
||||
AUGraphUpdate (MidiGraph, NULL);
|
||||
|
||||
// Open and initialize the audio units
|
||||
AUGraphOpen (MidiGraph);
|
||||
AUGraphInitialize (MidiGraph);
|
||||
|
||||
// Turn off the reverb on the synth
|
||||
AUGraphGetNodeInfo (MidiGraph, synthNode, NULL, NULL, NULL, &synthUnit);
|
||||
UInt32 usesReverb = 0;
|
||||
AudioUnitSetProperty (synthUnit, kMusicDeviceProperty_UsesInternalReverb,
|
||||
kAudioUnitScope_Global, 0, &usesReverb, sizeof (usesReverb));
|
||||
|
||||
// Start playing
|
||||
AUGraphStart (MidiGraph);
|
||||
if (WavePlaying) AudioOutputUnitStop (WaveOutputUnit);
|
||||
if (WaveConverter) AudioConverterDispose (WaveConverter);
|
||||
if (WaveOutputUnit) CloseComponent (WaveOutputUnit);
|
||||
WavePlaying = 0;
|
||||
WaveOpen = 0;
|
||||
WaveConverter = NULL;
|
||||
WaveOutputUnit = NULL;
|
||||
#endif
|
||||
BX_DEBUG(("openmidioutput(%s)", mididev));
|
||||
MidiOpen = 1;
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
|
||||
{
|
||||
BX_DEBUG(("sendmidicommand(%i,%02x,%i)", delta, command, length));
|
||||
if (!MidiOpen) return BX_SOUNDLOW_ERR;
|
||||
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
if (length <= 2) {
|
||||
Bit8u arg1 = (length >=1) ? data[0] : 0;
|
||||
Bit8u arg2 = (length >=2) ? data[1] : 0;
|
||||
MusicDeviceMIDIEvent (synthUnit, command, arg1, arg2, delta);
|
||||
}
|
||||
else {
|
||||
MusicDeviceSysEx (synthUnit, data, length);
|
||||
}
|
||||
#endif
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::closemidioutput()
|
||||
{
|
||||
BX_DEBUG(("closemidioutput()"));
|
||||
MidiOpen = 0;
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
AUGraphStop (MidiGraph);
|
||||
AUGraphClose (MidiGraph);
|
||||
#endif
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
#ifdef BX_SOUND_OSX_use_quicktime
|
||||
#if BX_WITH_MACOS
|
||||
pascal
|
||||
#endif
|
||||
void WaveCallbackProc (SndChannelPtr chan, SndCommand *cmd)
|
||||
void WaveCallbackProc(SndChannelPtr chan, SndCommand *cmd)
|
||||
{
|
||||
// a new buffer is available, so increment tail pointer
|
||||
int *tail = (int *) (cmd->param2);
|
||||
@ -187,7 +113,7 @@ void WaveCallbackProc (SndChannelPtr chan, SndCommand *cmd)
|
||||
}
|
||||
#endif
|
||||
|
||||
int bx_sound_osx_c::openwaveoutput(const char *wavedev)
|
||||
int bx_soundlow_waveout_osx_c::openwaveoutput(const char *wavedev)
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
@ -245,7 +171,7 @@ int bx_sound_osx_c::openwaveoutput(const char *wavedev)
|
||||
}
|
||||
#endif
|
||||
|
||||
set_pcm_params(real_pcm_param);
|
||||
set_pcm_params(&real_pcm_param);
|
||||
pcm_callback_id = register_wave_callback(this, pcm_callback);
|
||||
BX_INIT_MUTEX(mixer_mutex);
|
||||
start_mixer_thread();
|
||||
@ -254,7 +180,7 @@ int bx_sound_osx_c::openwaveoutput(const char *wavedev)
|
||||
}
|
||||
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
OSStatus bx_sound_osx_c::core_audio_pause()
|
||||
OSStatus bx_soundlow_waveout_osx_c::core_audio_pause()
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
|
||||
@ -269,7 +195,7 @@ OSStatus bx_sound_osx_c::core_audio_pause()
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus bx_sound_osx_c::core_audio_resume()
|
||||
OSStatus bx_soundlow_waveout_osx_c::core_audio_resume()
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
|
||||
@ -293,7 +219,7 @@ OSStatus bx_sound_osx_c::core_audio_resume()
|
||||
}
|
||||
#endif
|
||||
|
||||
int bx_sound_osx_c::set_pcm_params(bx_pcm_param_t param)
|
||||
int bx_soundlow_waveout_osx_c::set_pcm_params(bx_pcm_param_t *param)
|
||||
{
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
AudioStreamBasicDescription srcFormat, dstFormat;
|
||||
@ -301,31 +227,31 @@ int bx_sound_osx_c::set_pcm_params(bx_pcm_param_t param)
|
||||
OSStatus err;
|
||||
#endif
|
||||
|
||||
BX_DEBUG(("set_pcm_params(): %u, %u, %u, %02x", param.samplerate, param.bits,
|
||||
param.channels, param.format));
|
||||
BX_DEBUG(("set_pcm_params(): %u, %u, %u, %02x", param->samplerate, param->bits,
|
||||
param->channels, param->format));
|
||||
|
||||
#ifdef BX_SOUND_OSX_use_quicktime
|
||||
WaveInfo.samplePtr = NULL;
|
||||
WaveInfo.numChannels = param.channels;
|
||||
WaveInfo.sampleRate = param.samplerate << 16; // sampleRate is a 16.16 fixed-point value
|
||||
WaveInfo.numChannels = param->channels;
|
||||
WaveInfo.sampleRate = param->samplerate << 16; // sampleRate is a 16.16 fixed-point value
|
||||
WaveInfo.loopStart = 0;
|
||||
WaveInfo.loopEnd = 0;
|
||||
WaveInfo.encode = extSH; // WaveInfo has type ExtSoundHeader
|
||||
WaveInfo.baseFrequency = 1; // not sure what means. It's only a Uint8.
|
||||
WaveInfo.numFrames = 0;
|
||||
//WaveInfo.AIFFSampleRate = param.samplerate; // frequency as float80
|
||||
//WaveInfo.AIFFSampleRate = param->samplerate; // frequency as float80
|
||||
WaveInfo.markerChunk = NULL;
|
||||
|
||||
WaveInfo.instrumentChunks = NULL;
|
||||
WaveInfo.AESRecording = NULL;
|
||||
WaveInfo.sampleSize = param.bits * WaveInfo.numChannels;
|
||||
WaveInfo.sampleSize = param->bits * WaveInfo.numChannels;
|
||||
#endif
|
||||
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
// update the source audio format
|
||||
UInt32 bytes = param.bits / 8;
|
||||
UInt32 channels = param.channels;
|
||||
srcFormat.mSampleRate = (Float64) param.samplerate;
|
||||
UInt32 bytes = param->bits / 8;
|
||||
UInt32 channels = param->channels;
|
||||
srcFormat.mSampleRate = (Float64) param->samplerate;
|
||||
srcFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
srcFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked;
|
||||
if (param.format & 1) srcFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||
@ -392,13 +318,13 @@ int bx_sound_osx_c::set_pcm_params(bx_pcm_param_t param)
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::waveout(int length, Bit8u data[])
|
||||
int bx_soundlow_waveout_osx_c::output(int length, Bit8u data[])
|
||||
{
|
||||
#ifdef BX_SOUND_OSX_use_quicktime
|
||||
SndCommand mySndCommand;
|
||||
#endif
|
||||
|
||||
BX_DEBUG(("waveout(%d, %p), head=%u", length, data, head));
|
||||
BX_DEBUG(("output(%d, %p), head=%u", length, data, head));
|
||||
|
||||
// sanity check
|
||||
if ((!WaveOpen) || (head - tail >= BX_SOUND_OSX_NBUF))
|
||||
@ -441,20 +367,6 @@ int bx_sound_osx_c::waveout(int length, Bit8u data[])
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::closewaveoutput()
|
||||
{
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
if (WavePlaying) AudioOutputUnitStop (WaveOutputUnit);
|
||||
if (WaveConverter) AudioConverterDispose (WaveConverter);
|
||||
if (WaveOutputUnit) CloseComponent (WaveOutputUnit);
|
||||
WavePlaying = 0;
|
||||
WaveOpen = 0;
|
||||
WaveConverter = NULL;
|
||||
WaveOutputUnit = NULL;
|
||||
#endif
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
#ifndef BX_SOUND_OSX_CONVERTER_NEW_API
|
||||
OSStatus MyRenderer (void *inRefCon, AudioUnitRenderActionFlags inActionFlags,
|
||||
@ -469,7 +381,7 @@ OSStatus MyRenderer (void *inRefCon, AudioUnitRenderActionFlags inActionFlags,
|
||||
OSStatus MyACInputProc (AudioConverterRef inAudioConverter,
|
||||
UInt32* outDataSize, void** outData, void* inUserData)
|
||||
{
|
||||
bx_sound_osx_c *self = (bx_sound_osx_c*) inUserData;
|
||||
bx_soundlow_waveout_osx_c *self = (bx_soundlow_waveout_osx_c*) inUserData;
|
||||
self->nextbuffer ((int*) outDataSize, outData);
|
||||
return noErr;
|
||||
}
|
||||
@ -486,19 +398,19 @@ OSStatus MyRenderer (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
|
||||
&formatSize, &dstFormat);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
packets = inNumberFrames / dstFormat.mFramesPerPacket;
|
||||
err = AudioConverterFillComplexBuffer(WaveConverter,
|
||||
MyACInputProc, inRefCon, &packets, ioData, NULL);
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus MyACInputProc (AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData)
|
||||
{
|
||||
OSStatus err;
|
||||
bx_sound_osx_c *self = (bx_sound_osx_c*) inUserData;
|
||||
bx_soundlow_waveout_osx_c *self = (bx_soundlow_waveout_osx_c*) inUserData;
|
||||
AudioStreamBasicDescription srcFormat;
|
||||
UInt32 formatSize = sizeof(AudioStreamBasicDescription);
|
||||
|
||||
@ -520,7 +432,7 @@ OSStatus MyACInputProc (AudioConverterRef inAudioConverter, UInt32 *ioNumberData
|
||||
}
|
||||
#endif
|
||||
|
||||
void bx_sound_osx_c::nextbuffer (int *outDataSize, void **outData)
|
||||
void bx_soundlow_waveout_osx_c::nextbuffer (int *outDataSize, void **outData)
|
||||
{
|
||||
BX_DEBUG(("nextbuffer(), tail=%u", tail));
|
||||
if (head - tail <= 0) {
|
||||
@ -539,6 +451,104 @@ void bx_sound_osx_c::nextbuffer (int *outDataSize, void **outData)
|
||||
}
|
||||
#endif
|
||||
|
||||
// bx_sound_osx_c class implemenzation
|
||||
|
||||
bx_sound_osx_c::bx_sound_osx_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
{
|
||||
MidiOpen = 0;
|
||||
BX_INFO(("Sound lowlevel module 'osx' initialized"));
|
||||
}
|
||||
|
||||
bx_soundlow_waveout_c* bx_sound_osx_c::get_waveout()
|
||||
{
|
||||
if (waveout == NULL) {
|
||||
waveout = new bx_soundlow_waveout_osx_c();
|
||||
}
|
||||
return waveout;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::openmidioutput(const char *mididev)
|
||||
{
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
ComponentDescription description;
|
||||
AUNode synthNode, outputNode;
|
||||
|
||||
// Create the graph
|
||||
NewAUGraph (&MidiGraph);
|
||||
|
||||
// Open the DLS Synth
|
||||
description.componentType = kAudioUnitType_MusicDevice;
|
||||
description.componentSubType = kAudioUnitSubType_DLSSynth;
|
||||
description.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
description.componentFlags = 0;
|
||||
description.componentFlagsMask = 0;
|
||||
AUGraphNewNode (MidiGraph, &description, 0, NULL, &synthNode);
|
||||
|
||||
// Open the output device
|
||||
description.componentType = kAudioUnitType_Output;
|
||||
description.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||
description.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
description.componentFlags = 0;
|
||||
description.componentFlagsMask = 0;
|
||||
AUGraphNewNode (MidiGraph, &description, 0, NULL, &outputNode);
|
||||
|
||||
// Connect the devices up
|
||||
AUGraphConnectNodeInput (MidiGraph, synthNode, 1, outputNode, 0);
|
||||
AUGraphUpdate (MidiGraph, NULL);
|
||||
|
||||
// Open and initialize the audio units
|
||||
AUGraphOpen (MidiGraph);
|
||||
AUGraphInitialize (MidiGraph);
|
||||
|
||||
// Turn off the reverb on the synth
|
||||
AUGraphGetNodeInfo (MidiGraph, synthNode, NULL, NULL, NULL, &synthUnit);
|
||||
UInt32 usesReverb = 0;
|
||||
AudioUnitSetProperty (synthUnit, kMusicDeviceProperty_UsesInternalReverb,
|
||||
kAudioUnitScope_Global, 0, &usesReverb, sizeof (usesReverb));
|
||||
|
||||
// Start playing
|
||||
AUGraphStart (MidiGraph);
|
||||
#endif
|
||||
BX_DEBUG(("openmidioutput(%s)", mididev));
|
||||
MidiOpen = 1;
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::midiready()
|
||||
{
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
|
||||
{
|
||||
BX_DEBUG(("sendmidicommand(%i,%02x,%i)", delta, command, length));
|
||||
if (!MidiOpen) return BX_SOUNDLOW_ERR;
|
||||
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
if (length <= 2) {
|
||||
Bit8u arg1 = (length >=1) ? data[0] : 0;
|
||||
Bit8u arg2 = (length >=2) ? data[1] : 0;
|
||||
MusicDeviceMIDIEvent (synthUnit, command, arg1, arg2, delta);
|
||||
}
|
||||
else {
|
||||
MusicDeviceSysEx (synthUnit, data, length);
|
||||
}
|
||||
#endif
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::closemidioutput()
|
||||
{
|
||||
BX_DEBUG(("closemidioutput()"));
|
||||
MidiOpen = 0;
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
AUGraphStop (MidiGraph);
|
||||
AUGraphClose (MidiGraph);
|
||||
#endif
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_osx_c::openwaveinput(const char *wavedev, sound_record_handler_t rh)
|
||||
{
|
||||
UNUSED(wavedev);
|
||||
|
@ -36,25 +36,43 @@
|
||||
|
||||
#define BX_SOUND_OSX_NBUF 8 // number of buffers for digital output
|
||||
|
||||
class bx_sound_osx_c : public bx_sound_lowlevel_c {
|
||||
class bx_soundlow_waveout_osx_c : public bx_soundlow_waveout_c {
|
||||
public:
|
||||
bx_sound_osx_c();
|
||||
virtual ~bx_sound_osx_c();
|
||||
|
||||
virtual int get_type() {return BX_SOUNDLOW_OSX;}
|
||||
|
||||
virtual int openmidioutput(const char *mididev);
|
||||
virtual int midiready();
|
||||
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
|
||||
virtual int closemidioutput();
|
||||
bx_soundlow_waveout_osx_c();
|
||||
virtual ~bx_soundlow_waveout_osx_c();
|
||||
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t param);
|
||||
virtual int waveout(int length, Bit8u data[]);
|
||||
virtual int closewaveoutput();
|
||||
virtual int set_pcm_params(bx_pcm_param_t *param);
|
||||
virtual int output(int length, Bit8u data[]);
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
void nextbuffer(int *outDataSize, void **outData);
|
||||
#endif
|
||||
private:
|
||||
int WaveOpen;
|
||||
|
||||
Bit8u WaveData[BX_SOUND_OSX_NBUF][BX_SOUNDLOW_WAVEPACKETSIZE];
|
||||
int WaveLength[BX_SOUND_OSX_NBUF];
|
||||
int head, tail; // buffer pointers
|
||||
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
int WavePlaying;
|
||||
|
||||
OSStatus core_audio_pause();
|
||||
OSStatus core_audio_resume();
|
||||
#endif
|
||||
};
|
||||
|
||||
class bx_sound_osx_c : public bx_sound_lowlevel_c {
|
||||
public:
|
||||
bx_sound_osx_c();
|
||||
virtual ~bx_sound_osx_c() {}
|
||||
|
||||
virtual bx_soundlow_waveout_c* get_waveout();
|
||||
|
||||
virtual int openmidioutput(const char *mididev);
|
||||
virtual int midiready();
|
||||
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
|
||||
virtual int closemidioutput();
|
||||
|
||||
virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh);
|
||||
virtual int startwaverecord(bx_pcm_param_t *param);
|
||||
@ -65,19 +83,7 @@ public:
|
||||
static void record_timer_handler(void *);
|
||||
void record_timer(void);
|
||||
private:
|
||||
int MidiOpen;
|
||||
int WaveOpen;
|
||||
|
||||
Bit8u WaveData[BX_SOUND_OSX_NBUF][BX_SOUNDLOW_WAVEPACKETSIZE];
|
||||
int WaveLength[BX_SOUND_OSX_NBUF];
|
||||
int head, tail; // buffer pointers
|
||||
|
||||
#ifdef BX_SOUND_OSX_use_converter
|
||||
int WavePlaying;
|
||||
|
||||
OSStatus core_audio_pause();
|
||||
OSStatus core_audio_resume();
|
||||
#endif
|
||||
int MidiOpen;
|
||||
};
|
||||
|
||||
#endif // macintosh
|
||||
|
@ -35,13 +35,13 @@
|
||||
void sdl_callback(void *thisptr, Bit8u *stream, int len)
|
||||
{
|
||||
memset(stream, 0, len);
|
||||
((bx_sound_sdl_c*)thisptr)->mixer_common(stream, len);
|
||||
((bx_soundlow_waveout_sdl_c*)thisptr)->mixer_common(stream, len);
|
||||
}
|
||||
|
||||
// bx_sound_sdl_c class implemenzation
|
||||
// bx_soundlow_waveout_sdl_c class implemenzation
|
||||
|
||||
bx_sound_sdl_c::bx_sound_sdl_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
bx_soundlow_waveout_sdl_c::bx_soundlow_waveout_sdl_c()
|
||||
:bx_soundlow_waveout_c()
|
||||
{
|
||||
WaveOpen = 0;
|
||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO)) {
|
||||
@ -51,31 +51,33 @@ bx_sound_sdl_c::bx_sound_sdl_c()
|
||||
}
|
||||
}
|
||||
|
||||
bx_sound_sdl_c::~bx_sound_sdl_c()
|
||||
bx_soundlow_waveout_sdl_c::~bx_soundlow_waveout_sdl_c()
|
||||
{
|
||||
WaveOpen = 0;
|
||||
SDL_CloseAudio();
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
|
||||
int bx_sound_sdl_c::openwaveoutput(const char *wavedev)
|
||||
int bx_soundlow_waveout_sdl_c::openwaveoutput(const char *wavedev)
|
||||
{
|
||||
set_pcm_params(real_pcm_param);
|
||||
set_pcm_params(&real_pcm_param);
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_sdl_c::set_pcm_params(bx_pcm_param_t param)
|
||||
int bx_soundlow_waveout_sdl_c::set_pcm_params(bx_pcm_param_t *param)
|
||||
{
|
||||
int signeddata = param.format & 1;
|
||||
int signeddata = param->format & 1;
|
||||
|
||||
BX_DEBUG(("set_pcm_params(): %u, %u, %u, %02x", param.samplerate, param.bits,
|
||||
param.channels, param.format));
|
||||
fmt.freq = param.samplerate;
|
||||
BX_DEBUG(("set_pcm_params(): %u, %u, %u, %02x", param->samplerate, param->bits,
|
||||
param->channels, param->format));
|
||||
fmt.freq = param->samplerate;
|
||||
|
||||
if (param.bits == 16) {
|
||||
if (param->bits == 16) {
|
||||
if (signeddata == 1)
|
||||
fmt.format = AUDIO_S16;
|
||||
else
|
||||
fmt.format = AUDIO_U16;
|
||||
} else if (param.bits == 8) {
|
||||
} else if (param->bits == 8) {
|
||||
if (signeddata == 1)
|
||||
fmt.format = AUDIO_S8;
|
||||
else
|
||||
@ -83,7 +85,7 @@ int bx_sound_sdl_c::set_pcm_params(bx_pcm_param_t param)
|
||||
} else
|
||||
return BX_SOUNDLOW_ERR;
|
||||
|
||||
fmt.channels = param.channels;
|
||||
fmt.channels = param->channels;
|
||||
fmt.samples = fmt.freq / 10;
|
||||
fmt.callback = sdl_callback;
|
||||
fmt.userdata = this;
|
||||
@ -103,7 +105,7 @@ int bx_sound_sdl_c::set_pcm_params(bx_pcm_param_t param)
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_sdl_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param)
|
||||
int bx_soundlow_waveout_sdl_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param)
|
||||
{
|
||||
int ret = BX_SOUNDLOW_OK;
|
||||
int len2;
|
||||
@ -114,7 +116,7 @@ int bx_sound_sdl_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src
|
||||
if (src_param->channels == 1) cvt_mult <<= 1;
|
||||
if (src_param->samplerate != real_pcm_param.samplerate) {
|
||||
real_pcm_param.samplerate = src_param->samplerate;
|
||||
set_pcm_params(real_pcm_param);
|
||||
set_pcm_params(&real_pcm_param);
|
||||
}
|
||||
}
|
||||
len2 = length * cvt_mult;
|
||||
@ -130,14 +132,7 @@ int bx_sound_sdl_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bx_sound_sdl_c::closewaveoutput()
|
||||
{
|
||||
WaveOpen = 0;
|
||||
SDL_CloseAudio();
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
bx_bool bx_sound_sdl_c::mixer_common(Bit8u *buffer, int len)
|
||||
bx_bool bx_soundlow_waveout_sdl_c::mixer_common(Bit8u *buffer, int len)
|
||||
{
|
||||
Bit32u len2 = 0;
|
||||
|
||||
@ -155,7 +150,7 @@ bx_bool bx_sound_sdl_c::mixer_common(Bit8u *buffer, int len)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bx_sound_sdl_c::unregister_wave_callback(int callback_id)
|
||||
void bx_soundlow_waveout_sdl_c::unregister_wave_callback(int callback_id)
|
||||
{
|
||||
SDL_LockAudio();
|
||||
if ((callback_id >= 0) && (callback_id < BX_MAX_WAVE_CALLBACKS)) {
|
||||
@ -165,4 +160,20 @@ void bx_sound_sdl_c::unregister_wave_callback(int callback_id)
|
||||
SDL_UnlockAudio();
|
||||
}
|
||||
|
||||
// bx_sound_sdl_c class implemenzation
|
||||
|
||||
bx_sound_sdl_c::bx_sound_sdl_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
{
|
||||
// nothing here yet
|
||||
}
|
||||
|
||||
bx_soundlow_waveout_c* bx_sound_sdl_c::get_waveout()
|
||||
{
|
||||
if (waveout == NULL) {
|
||||
waveout = new bx_soundlow_waveout_sdl_c();
|
||||
}
|
||||
return waveout;
|
||||
}
|
||||
|
||||
#endif // BX_WITH_SDL || BX_WITH_SDL2
|
||||
|
@ -26,17 +26,16 @@
|
||||
#include "bochs.h"
|
||||
#include <SDL_audio.h>
|
||||
|
||||
class bx_sound_sdl_c : public bx_sound_lowlevel_c {
|
||||
// the waveout class
|
||||
|
||||
class bx_soundlow_waveout_sdl_c : public bx_soundlow_waveout_c {
|
||||
public:
|
||||
bx_sound_sdl_c();
|
||||
virtual ~bx_sound_sdl_c();
|
||||
bx_soundlow_waveout_sdl_c();
|
||||
virtual ~bx_soundlow_waveout_sdl_c();
|
||||
|
||||
virtual int get_type() {return BX_SOUNDLOW_SDL;}
|
||||
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t param);
|
||||
virtual int sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param);
|
||||
virtual int closewaveoutput();
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t *param);
|
||||
virtual int sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param);
|
||||
|
||||
virtual void unregister_wave_callback(int callback_id);
|
||||
virtual bx_bool mixer_common(Bit8u *buffer, int len);
|
||||
@ -45,4 +44,12 @@ private:
|
||||
SDL_AudioSpec fmt;
|
||||
};
|
||||
|
||||
class bx_sound_sdl_c : public bx_sound_lowlevel_c {
|
||||
public:
|
||||
bx_sound_sdl_c();
|
||||
virtual ~bx_sound_sdl_c() {}
|
||||
|
||||
virtual bx_soundlow_waveout_c* get_waveout();
|
||||
};
|
||||
|
||||
#endif // BX_WITH_SDL || BX_WITH_SDL2
|
||||
|
@ -34,17 +34,8 @@
|
||||
|
||||
#define LOG_THIS
|
||||
|
||||
bx_sound_windows_c::bx_sound_windows_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
{
|
||||
MidiOpen = 0;
|
||||
WaveOutOpen = 0;
|
||||
WaveInOpen = 0;
|
||||
|
||||
ismidiready = 1;
|
||||
|
||||
// size is the total size of the midi header and buffer and the
|
||||
// wave header and buffer, all aligned on a 16-byte boundary
|
||||
// size is the total size of the midi header and buffer and the
|
||||
// wave header and buffer, all aligned on a 16-byte boundary
|
||||
|
||||
#define ALIGN(size) ((size + 15) & ~15)
|
||||
|
||||
@ -53,132 +44,45 @@ bx_sound_windows_c::bx_sound_windows_c()
|
||||
+ ALIGN(BX_SOUND_WINDOWS_MAXSYSEXLEN) \
|
||||
+ ALIGN(BX_SOUNDLOW_WAVEPACKETSIZE + 64)
|
||||
|
||||
DataHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
|
||||
DataPointer = (Bit8u*) GlobalLock(DataHandle);
|
||||
// some data for the wave buffers
|
||||
HANDLE DataHandle; // returned by GlobalAlloc()
|
||||
Bit8u *DataPointer; // returned by GlobalLock()
|
||||
|
||||
if (DataPointer == NULL)
|
||||
BX_PANIC(("GlobalLock returned NULL-pointer"));
|
||||
|
||||
#define NEWBUFFER(size) &(DataPointer[offset]); offset += ALIGN(size)
|
||||
|
||||
unsigned offset = 0;
|
||||
MidiHeader = (LPMIDIHDR) NEWBUFFER(sizeof(MIDIHDR));
|
||||
MidiData = (LPSTR) NEWBUFFER(BX_SOUND_WINDOWS_MAXSYSEXLEN);
|
||||
|
||||
WaveOutHdr = (LPWAVEHDR) NEWBUFFER(sizeof(WAVEHDR));
|
||||
WaveInHdr = (LPWAVEHDR) NEWBUFFER(sizeof(WAVEHDR));
|
||||
WaveInData = (LPSTR) NEWBUFFER(BX_SOUNDLOW_WAVEPACKETSIZE+64);
|
||||
|
||||
if (offset > size)
|
||||
BX_PANIC(("Allocated memory was too small!"));
|
||||
|
||||
#undef size
|
||||
#undef ALIGN
|
||||
#undef NEWBUFFER
|
||||
|
||||
BX_INFO(("Sound lowlevel module 'win' initialized"));
|
||||
}
|
||||
|
||||
bx_sound_windows_c::~bx_sound_windows_c()
|
||||
// helper function
|
||||
Bit8u* newbuffer(unsigned blksize)
|
||||
{
|
||||
GlobalUnlock(DataHandle);
|
||||
GlobalFree(DataHandle);
|
||||
}
|
||||
static unsigned offset = 0;
|
||||
Bit8u *ptr;
|
||||
|
||||
int bx_sound_windows_c::midiready()
|
||||
{
|
||||
if (ismidiready == 0)
|
||||
checkmidiready();
|
||||
|
||||
if (ismidiready == 1)
|
||||
return BX_SOUNDLOW_OK;
|
||||
else
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::openmidioutput(const char *mididev)
|
||||
{
|
||||
UINT deviceid;
|
||||
|
||||
if (strlen(mididev) == 0) {
|
||||
deviceid = (UINT) MIDIMAPPER;
|
||||
ptr = &(DataPointer[offset]);
|
||||
if ((offset + ALIGN(blksize)) > size) {
|
||||
return NULL;
|
||||
} else {
|
||||
deviceid = atoi(mididev);
|
||||
if (((deviceid < 0) || (deviceid >= midiOutGetNumDevs())) &&
|
||||
(deviceid != (UINT) MIDIMAPPER)) {
|
||||
BX_ERROR(("MIDI device ID out of range - using default MIDI mapper"));
|
||||
deviceid = (UINT) MIDIMAPPER;
|
||||
}
|
||||
offset += ALIGN(blksize);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
MidiOpen = 0;
|
||||
|
||||
UINT ret = midiOutOpen(&MidiOut, deviceid, 0, 0, CALLBACK_NULL);
|
||||
if (ret == 0)
|
||||
MidiOpen = 1;
|
||||
|
||||
BX_DEBUG(("midiOutOpen() = %d, MidiOpen: %d", ret, MidiOpen));
|
||||
|
||||
return (MidiOpen == 1) ? BX_SOUNDLOW_OK : BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
|
||||
// bx_soundlow_waveout_win_c class implemenzation
|
||||
|
||||
bx_soundlow_waveout_win_c::bx_soundlow_waveout_win_c()
|
||||
:bx_soundlow_waveout_c()
|
||||
{
|
||||
UINT ret;
|
||||
|
||||
if (MidiOpen != 1)
|
||||
return BX_SOUNDLOW_ERR;
|
||||
|
||||
if ((command == 0xf0) || (command == 0xf7) || (length > 3))
|
||||
{
|
||||
BX_DEBUG(("SYSEX started, length %d", length));
|
||||
ismidiready = 0; // until the buffer is done
|
||||
memcpy(MidiData, data, length);
|
||||
MidiHeader->lpData = MidiData;
|
||||
MidiHeader->dwBufferLength = BX_SOUND_WINDOWS_MAXSYSEXLEN;
|
||||
MidiHeader->dwBytesRecorded = 0;
|
||||
MidiHeader->dwUser = 0;
|
||||
MidiHeader->dwFlags = 0;
|
||||
ret = midiOutPrepareHeader(MidiOut, MidiHeader, sizeof(*MidiHeader));
|
||||
if (ret != 0)
|
||||
BX_ERROR(("midiOutPrepareHeader(): error = %d", ret));
|
||||
ret = midiOutLongMsg(MidiOut, MidiHeader, sizeof(*MidiHeader));
|
||||
if (ret != 0)
|
||||
BX_ERROR(("midiOutLongMsg(): error = %d", ret));
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD msg = command;
|
||||
|
||||
for (int i = 0; i<length; i++)
|
||||
msg |= (data[i] << (8 * (i + 1)));
|
||||
|
||||
ret = midiOutShortMsg(MidiOut, msg);
|
||||
BX_DEBUG(("midiOutShortMsg(%x) = %d", msg, ret));
|
||||
}
|
||||
|
||||
return (ret == 0) ? BX_SOUNDLOW_OK : BX_SOUNDLOW_ERR;
|
||||
WaveOutOpen = 0;
|
||||
WaveOutHdr = (LPWAVEHDR) newbuffer(sizeof(WAVEHDR));
|
||||
if (WaveOutHdr == NULL)
|
||||
BX_PANIC(("Allocated memory was too small!"));
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::closemidioutput()
|
||||
bx_soundlow_waveout_win_c::~bx_soundlow_waveout_win_c()
|
||||
{
|
||||
UINT ret;
|
||||
|
||||
if (MidiOpen != 1)
|
||||
return BX_SOUNDLOW_ERR;
|
||||
|
||||
ret = midiOutReset(MidiOut);
|
||||
if (ismidiready == 0)
|
||||
checkmidiready(); // to clear any pending SYSEX
|
||||
|
||||
ret = midiOutClose(MidiOut);
|
||||
BX_DEBUG(("midiOutClose() = %d", ret));
|
||||
MidiOpen = 0;
|
||||
|
||||
return (ret == 0) ? BX_SOUNDLOW_OK : BX_SOUNDLOW_ERR;
|
||||
if (WaveOutOpen == 1) {
|
||||
waveOutReset(hWaveOut);
|
||||
waveOutClose(hWaveOut);
|
||||
}
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::openwaveoutput(const char *wavedev)
|
||||
int bx_soundlow_waveout_win_c::openwaveoutput(const char *wavedev)
|
||||
{
|
||||
// could make the output device selectable,
|
||||
// but currently only the wave mapper is supported
|
||||
@ -188,20 +92,20 @@ int bx_sound_windows_c::openwaveoutput(const char *wavedev)
|
||||
|
||||
WaveDevice = (UINT) WAVEMAPPER;
|
||||
|
||||
set_pcm_params(real_pcm_param);
|
||||
set_pcm_params(&real_pcm_param);
|
||||
pcm_callback_id = register_wave_callback(this, pcm_callback);
|
||||
BX_INIT_MUTEX(mixer_mutex);
|
||||
start_mixer_thread();
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::set_pcm_params(bx_pcm_param_t param)
|
||||
int bx_soundlow_waveout_win_c::set_pcm_params(bx_pcm_param_t *param)
|
||||
{
|
||||
UINT ret;
|
||||
PCMWAVEFORMAT waveformat;
|
||||
|
||||
BX_DEBUG(("set_pcm_params(): %u, %u, %u, %02x", param.samplerate, param.bits,
|
||||
param.channels, param.format));
|
||||
BX_DEBUG(("set_pcm_params(): %u, %u, %u, %02x", param->samplerate, param->bits,
|
||||
param->channels, param->format));
|
||||
if (WaveOutOpen != 0) {
|
||||
ret = waveOutReset(hWaveOut);
|
||||
ret = waveOutClose(hWaveOut);
|
||||
@ -266,7 +170,7 @@ int bx_sound_windows_c::set_pcm_params(bx_pcm_param_t param)
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::waveout(int length, Bit8u data[])
|
||||
int bx_soundlow_waveout_win_c::output(int length, Bit8u data[])
|
||||
{
|
||||
UINT ret;
|
||||
|
||||
@ -295,16 +199,143 @@ int bx_sound_windows_c::waveout(int length, Bit8u data[])
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::closewaveoutput()
|
||||
{
|
||||
BX_DEBUG(("closewaveoutput"));
|
||||
// bx_sound_windows_c class implemenzation
|
||||
|
||||
if (WaveOutOpen == 1) {
|
||||
waveOutReset(hWaveOut);
|
||||
waveOutClose(hWaveOut);
|
||||
bx_sound_windows_c::bx_sound_windows_c()
|
||||
:bx_sound_lowlevel_c()
|
||||
{
|
||||
MidiOpen = 0;
|
||||
WaveInOpen = 0;
|
||||
|
||||
ismidiready = 1;
|
||||
|
||||
DataHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
|
||||
DataPointer = (Bit8u*) GlobalLock(DataHandle);
|
||||
|
||||
if (DataPointer == NULL)
|
||||
BX_PANIC(("GlobalLock returned NULL-pointer"));
|
||||
|
||||
unsigned offset = 0;
|
||||
MidiHeader = (LPMIDIHDR) newbuffer(sizeof(MIDIHDR));
|
||||
MidiData = (LPSTR) newbuffer(BX_SOUND_WINDOWS_MAXSYSEXLEN);
|
||||
|
||||
WaveInHdr = (LPWAVEHDR) newbuffer(sizeof(WAVEHDR));
|
||||
WaveInData = (LPSTR) newbuffer(BX_SOUNDLOW_WAVEPACKETSIZE+64);
|
||||
|
||||
if (WaveInData == NULL)
|
||||
BX_PANIC(("Allocated memory was too small!"));
|
||||
|
||||
#undef size
|
||||
#undef ALIGN
|
||||
|
||||
BX_INFO(("Sound lowlevel module 'win' initialized"));
|
||||
}
|
||||
|
||||
bx_soundlow_waveout_c* bx_sound_windows_c::get_waveout()
|
||||
{
|
||||
if (waveout == NULL) {
|
||||
waveout = new bx_soundlow_waveout_win_c();
|
||||
}
|
||||
return waveout;
|
||||
}
|
||||
|
||||
bx_sound_windows_c::~bx_sound_windows_c()
|
||||
{
|
||||
GlobalUnlock(DataHandle);
|
||||
GlobalFree(DataHandle);
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::openmidioutput(const char *mididev)
|
||||
{
|
||||
UINT deviceid;
|
||||
|
||||
if (strlen(mididev) == 0) {
|
||||
deviceid = (UINT) MIDIMAPPER;
|
||||
} else {
|
||||
deviceid = atoi(mididev);
|
||||
if (((deviceid < 0) || (deviceid >= midiOutGetNumDevs())) &&
|
||||
(deviceid != (UINT) MIDIMAPPER)) {
|
||||
BX_ERROR(("MIDI device ID out of range - using default MIDI mapper"));
|
||||
deviceid = (UINT) MIDIMAPPER;
|
||||
}
|
||||
}
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
MidiOpen = 0;
|
||||
|
||||
UINT ret = midiOutOpen(&MidiOut, deviceid, 0, 0, CALLBACK_NULL);
|
||||
if (ret == 0)
|
||||
MidiOpen = 1;
|
||||
|
||||
BX_DEBUG(("midiOutOpen() = %d, MidiOpen: %d", ret, MidiOpen));
|
||||
|
||||
return (MidiOpen == 1) ? BX_SOUNDLOW_OK : BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::midiready()
|
||||
{
|
||||
if (ismidiready == 0)
|
||||
checkmidiready();
|
||||
|
||||
if (ismidiready == 1)
|
||||
return BX_SOUNDLOW_OK;
|
||||
else
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
|
||||
{
|
||||
UINT ret;
|
||||
|
||||
if (MidiOpen != 1)
|
||||
return BX_SOUNDLOW_ERR;
|
||||
|
||||
if ((command == 0xf0) || (command == 0xf7) || (length > 3))
|
||||
{
|
||||
BX_DEBUG(("SYSEX started, length %d", length));
|
||||
ismidiready = 0; // until the buffer is done
|
||||
memcpy(MidiData, data, length);
|
||||
MidiHeader->lpData = MidiData;
|
||||
MidiHeader->dwBufferLength = BX_SOUND_WINDOWS_MAXSYSEXLEN;
|
||||
MidiHeader->dwBytesRecorded = 0;
|
||||
MidiHeader->dwUser = 0;
|
||||
MidiHeader->dwFlags = 0;
|
||||
ret = midiOutPrepareHeader(MidiOut, MidiHeader, sizeof(*MidiHeader));
|
||||
if (ret != 0)
|
||||
BX_ERROR(("midiOutPrepareHeader(): error = %d", ret));
|
||||
ret = midiOutLongMsg(MidiOut, MidiHeader, sizeof(*MidiHeader));
|
||||
if (ret != 0)
|
||||
BX_ERROR(("midiOutLongMsg(): error = %d", ret));
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD msg = command;
|
||||
|
||||
for (int i = 0; i<length; i++)
|
||||
msg |= (data[i] << (8 * (i + 1)));
|
||||
|
||||
ret = midiOutShortMsg(MidiOut, msg);
|
||||
BX_DEBUG(("midiOutShortMsg(%x) = %d", msg, ret));
|
||||
}
|
||||
|
||||
return (ret == 0) ? BX_SOUNDLOW_OK : BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
int bx_sound_windows_c::closemidioutput()
|
||||
{
|
||||
UINT ret;
|
||||
|
||||
if (MidiOpen != 1)
|
||||
return BX_SOUNDLOW_ERR;
|
||||
|
||||
ret = midiOutReset(MidiOut);
|
||||
if (ismidiready == 0)
|
||||
checkmidiready(); // to clear any pending SYSEX
|
||||
|
||||
ret = midiOutClose(MidiOut);
|
||||
BX_DEBUG(("midiOutClose() = %d", ret));
|
||||
MidiOpen = 0;
|
||||
|
||||
return (ret == 0) ? BX_SOUNDLOW_OK : BX_SOUNDLOW_ERR;
|
||||
}
|
||||
|
||||
void bx_sound_windows_c::checkmidiready()
|
||||
|
@ -157,23 +157,35 @@ typedef struct {
|
||||
|
||||
#endif
|
||||
|
||||
class bx_soundlow_waveout_win_c : public bx_soundlow_waveout_c {
|
||||
public:
|
||||
bx_soundlow_waveout_win_c();
|
||||
virtual ~bx_soundlow_waveout_win_c();
|
||||
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t *param);
|
||||
virtual int output(int length, Bit8u data[]);
|
||||
private:
|
||||
HWAVEOUT hWaveOut; // Wave output device
|
||||
int WaveOutOpen; // is it open?
|
||||
|
||||
UINT WaveDevice; // Wave device ID, for waveOutOpen
|
||||
|
||||
LPWAVEHDR WaveOutHdr;
|
||||
};
|
||||
|
||||
class bx_sound_windows_c : public bx_sound_lowlevel_c {
|
||||
public:
|
||||
bx_sound_windows_c();
|
||||
virtual ~bx_sound_windows_c();
|
||||
|
||||
virtual int get_type() {return BX_SOUNDLOW_WIN;}
|
||||
virtual bx_soundlow_waveout_c* get_waveout();
|
||||
|
||||
virtual int openmidioutput(const char *mididev);
|
||||
virtual int midiready();
|
||||
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
|
||||
virtual int closemidioutput();
|
||||
|
||||
virtual int openwaveoutput(const char *wavedev);
|
||||
virtual int set_pcm_params(bx_pcm_param_t param);
|
||||
virtual int waveout(int length, Bit8u data[]);
|
||||
virtual int closewaveoutput();
|
||||
|
||||
virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh);
|
||||
virtual int startwaverecord(bx_pcm_param_t *param);
|
||||
virtual int getwavepacket(int length, Bit8u data[]);
|
||||
@ -187,18 +199,9 @@ private:
|
||||
|
||||
HMIDIOUT MidiOut; // Midi output device
|
||||
int MidiOpen; // is it open?
|
||||
HWAVEOUT hWaveOut; // Wave output device
|
||||
int WaveOutOpen; // is it open?
|
||||
HWAVEIN hWaveIn; // Wave input device
|
||||
int WaveInOpen; // is it open?
|
||||
|
||||
UINT WaveDevice; // Wave device ID, for waveOutOpen
|
||||
|
||||
// some data for the wave buffers
|
||||
HANDLE DataHandle; // returned by GlobalAlloc()
|
||||
Bit8u *DataPointer; // returned by GlobalLock()
|
||||
|
||||
LPWAVEHDR WaveOutHdr;
|
||||
LPWAVEHDR WaveInHdr;
|
||||
LPSTR WaveInData;
|
||||
bx_bool recording;
|
||||
|
Loading…
Reference in New Issue
Block a user