Implemented support for the new mixer thread in the lowlevel sound module
'alsa'. Cleaned up the code a little bit. TODO #1: Implement mixer thread support in the OSX sound driver. TODO #2: Code cleanups in the Bochs sound code. TODO #3: Resampling support and improvements in the wave recording code.
This commit is contained in:
parent
bfb5ec8cf9
commit
9c1070cbed
@ -27,6 +27,10 @@
|
||||
|
||||
#if BX_HAVE_ALSASOUND && BX_SUPPORT_SOUNDLOW
|
||||
|
||||
#ifndef WIN32
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define LOG_THIS
|
||||
|
||||
bx_sound_alsa_c::bx_sound_alsa_c()
|
||||
@ -202,6 +206,9 @@ int bx_sound_alsa_c::closemidioutput()
|
||||
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;
|
||||
}
|
||||
|
||||
@ -216,7 +223,7 @@ int bx_sound_alsa_c::alsa_pcm_open(bx_bool mode, int frequency, int bits, bx_boo
|
||||
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, SND_PCM_NONBLOCK);
|
||||
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;
|
||||
}
|
||||
@ -226,16 +233,18 @@ int bx_sound_alsa_c::alsa_pcm_open(bx_bool mode, int frequency, int bits, bx_boo
|
||||
snd_pcm_hw_params_any(alsa_pcm[mode].handle, params);
|
||||
snd_pcm_hw_params_set_access(alsa_pcm[mode].handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
|
||||
if ((frequency == wave_ch[mode].oldfreq) &&
|
||||
(bits == wave_ch[mode].oldbits) &&
|
||||
(stereo == wave_ch[mode].oldstereo) &&
|
||||
(format == wave_ch[mode].oldformat))
|
||||
if (mode == 1) {
|
||||
if ((frequency == wavein_param.samplerate) &&
|
||||
(bits == wavein_param.bits) &&
|
||||
(stereo == (wavein_param.channels == 2)) &&
|
||||
(format == wavein_param.format))
|
||||
return BX_SOUNDLOW_OK; // nothing to do
|
||||
|
||||
wave_ch[mode].oldfreq = frequency;
|
||||
wave_ch[mode].oldbits = bits;
|
||||
wave_ch[mode].oldstereo = stereo;
|
||||
wave_ch[mode].oldformat = format;
|
||||
wavein_param.samplerate = frequency;
|
||||
wavein_param.bits = bits;
|
||||
wavein_param.channels = stereo + 1;
|
||||
wavein_param.format = format;
|
||||
}
|
||||
|
||||
freq = (unsigned int)frequency;
|
||||
|
||||
@ -283,18 +292,17 @@ int bx_sound_alsa_c::set_pcm_params(bx_pcm_param_t param)
|
||||
return alsa_pcm_open(0, param.samplerate, param.bits, param.channels == 2, param.format);
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::alsa_pcm_write()
|
||||
int bx_sound_alsa_c::get_waveout_packetsize()
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (alsa_pcm[0].buffer == NULL) {
|
||||
alsa_pcm[0].buffer = (char *)malloc(alsa_pcm[0].alsa_bufsize);
|
||||
return alsa_pcm[0].alsa_bufsize;
|
||||
}
|
||||
while (alsa_pcm[0].audio_bufsize >= alsa_pcm[0].alsa_bufsize) {
|
||||
memcpy(alsa_pcm[0].buffer, audio_buffer[0], alsa_pcm[0].alsa_bufsize);
|
||||
ret = snd_pcm_writei(alsa_pcm[0].handle, alsa_pcm[0].buffer, alsa_pcm[0].frames);
|
||||
if (ret == -EAGAIN)
|
||||
continue;
|
||||
|
||||
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"));
|
||||
@ -304,61 +312,6 @@ int bx_sound_alsa_c::alsa_pcm_write()
|
||||
} else if (ret != (int)alsa_pcm[0].frames) {
|
||||
BX_ERROR(("ALSA: short write, write %d frames", ret));
|
||||
}
|
||||
alsa_pcm[0].audio_bufsize -= alsa_pcm[0].alsa_bufsize;
|
||||
memmove(audio_buffer[0], audio_buffer[0]+alsa_pcm[0].alsa_bufsize, alsa_pcm[0].audio_bufsize);
|
||||
}
|
||||
if ((alsa_pcm[0].audio_bufsize == 0) && (alsa_pcm[0].buffer != NULL)) {
|
||||
free(alsa_pcm[0].buffer);
|
||||
alsa_pcm[0].buffer = NULL;
|
||||
}
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
int bx_sound_alsa_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;
|
||||
if (!alsa_pcm[0].handle) {
|
||||
// Alert indicating that caller is probably erroneous
|
||||
BX_ERROR(("sendwavepacket(): pcm is not open"));
|
||||
return BX_SOUNDLOW_ERR;
|
||||
}
|
||||
if ((alsa_pcm[0].audio_bufsize+len2) > BX_SOUND_ALSA_BUFSIZE) {
|
||||
len2 = BX_SOUND_ALSA_BUFSIZE - alsa_pcm[0].audio_bufsize;
|
||||
BX_ERROR(("ALSA: audio buffer overflow"));
|
||||
}
|
||||
if (len2 > 0) {
|
||||
convert_pcm_data(data, length, audio_buffer[0]+alsa_pcm[0].audio_bufsize, len2, src_param);
|
||||
alsa_pcm[0].audio_bufsize += len2;
|
||||
}
|
||||
if (alsa_pcm[0].audio_bufsize < alsa_pcm[0].alsa_bufsize) {
|
||||
return BX_SOUNDLOW_OK;
|
||||
} else {
|
||||
return alsa_pcm_write();
|
||||
}
|
||||
}
|
||||
|
||||
int bx_sound_alsa_c::stopwaveplayback()
|
||||
{
|
||||
if (alsa_pcm[0].handle && alsa_pcm[0].audio_bufsize > 0) {
|
||||
if (alsa_pcm[0].audio_bufsize < alsa_pcm[0].alsa_bufsize) {
|
||||
memset(audio_buffer[0]+alsa_pcm[0].audio_bufsize, 0, alsa_pcm[0].alsa_bufsize-alsa_pcm[0].audio_bufsize);
|
||||
alsa_pcm[0].audio_bufsize = alsa_pcm[0].alsa_bufsize;
|
||||
}
|
||||
alsa_pcm_write();
|
||||
}
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
@ -369,7 +322,6 @@ int bx_sound_alsa_c::closewaveoutput()
|
||||
snd_pcm_close(alsa_pcm[0].handle);
|
||||
alsa_pcm[0].handle = NULL;
|
||||
}
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
|
||||
@ -380,6 +332,7 @@ int bx_sound_alsa_c::openwaveinput(const char *wavedev, sound_record_handler_t r
|
||||
record_timer_index = bx_pc_system.register_timer(this, record_timer_handler, 1, 1, 0, "soundlnx");
|
||||
// record timer: inactive, continuous, frequency variable
|
||||
}
|
||||
wavein_param.samplerate = 0;
|
||||
|
||||
return BX_SOUNDLOW_OK;
|
||||
}
|
||||
@ -422,10 +375,10 @@ int bx_sound_alsa_c::getwavepacket(int length, Bit8u data[])
|
||||
} else if (ret != (int)alsa_pcm[1].frames) {
|
||||
BX_ERROR(("short read, read %d frames", ret));
|
||||
}
|
||||
memcpy(audio_buffer[1]+alsa_pcm[1].audio_bufsize, alsa_pcm[1].buffer, alsa_pcm[1].alsa_bufsize);
|
||||
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(data, audio_buffer[1], length);
|
||||
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);
|
||||
@ -470,4 +423,14 @@ void bx_sound_alsa_c::record_timer(void)
|
||||
record_handler(this, record_packet_size);
|
||||
}
|
||||
|
||||
int bx_sound_alsa_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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -42,8 +42,8 @@ public:
|
||||
|
||||
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 stopwaveplayback();
|
||||
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);
|
||||
@ -54,11 +54,12 @@ public:
|
||||
|
||||
static void record_timer_handler(void *);
|
||||
void record_timer(void);
|
||||
|
||||
virtual int register_wave_callback(void *, get_wave_cb_t wd_cb);
|
||||
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, int frequency, int bits, bx_bool stereo, int format);
|
||||
int alsa_pcm_write();
|
||||
|
||||
struct {
|
||||
snd_seq_t *handle;
|
||||
@ -70,11 +71,8 @@ private:
|
||||
int alsa_bufsize, audio_bufsize;
|
||||
char *buffer;
|
||||
} alsa_pcm[2];
|
||||
struct {
|
||||
int oldfreq, oldbits, oldformat;
|
||||
bx_bool oldstereo;
|
||||
} wave_ch[2];
|
||||
Bit8u audio_buffer[2][BX_SOUND_ALSA_BUFSIZE];
|
||||
bx_pcm_param_t wavein_param;
|
||||
Bit8u audio_buffer[BX_SOUND_ALSA_BUFSIZE];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user