Some work in the lowlevel sound code.

- Added framework for polling wave data and use it for beep output in sdl.
- Some work in the beep thread code (to be continued).
- Moved macros required for multithreading to bochs.h.
This commit is contained in:
Volker Ruppert 2015-01-04 21:12:41 +00:00
parent 2357175d79
commit 0c205fce26
7 changed files with 164 additions and 65 deletions

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2014 The Bochs Project
// Copyright (C) 2001-2015 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -600,4 +600,19 @@ BX_CPP_INLINE Bit64u bx_bswap64(Bit64u val64)
#define CopyHostQWordLittleEndian(hostAddrDst, hostAddrSrc) \
(* (Bit64u *)(hostAddrDst)) = (* (Bit64u *)(hostAddrSrc));
// multithreading support
#ifdef WIN32
#define BX_LOCK(mutex) EnterCriticalSection(&(mutex))
#define BX_UNLOCK(mutex) LeaveCriticalSection(&(mutex))
#define BX_MUTEX(mutex) CRITICAL_SECTION (mutex)
#define BX_INIT_MUTEX(mutex) InitializeCriticalSection(&(mutex))
#define BX_FINI_MUTEX(mutex) DeleteCriticalSection(&(mutex))
#else
#define BX_LOCK(mutex) pthread_mutex_lock(&(mutex));
#define BX_UNLOCK(mutex) pthread_mutex_unlock(&(mutex));
#define BX_MUTEX(mutex) pthread_mutex_t (mutex)
#define BX_INIT_MUTEX(mutex) pthread_mutex_init(&(mutex),NULL)
#define BX_FINI_MUTEX(mutex) pthread_mutex_destroy(&(mutex))
#endif
#endif /* BX_BOCHS_H */

View File

@ -7,7 +7,7 @@
// Donald Becker
// http://www.psyon.org
//
// Copyright (C) 2001-2014 The Bochs Project
// Copyright (C) 2001-2015 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -89,17 +89,6 @@ IMPLEMENT_GUI_PLUGIN_CODE(vncsrv)
#include <winsock2.h>
#include <process.h>
#undef LOCK
#undef UNLOCK
#undef MUTEX
#undef INIT_MUTEX
#undef TINI_MUTEX
#define LOCK(mutex) EnterCriticalSection(&(mutex))
#define UNLOCK(mutex) LeaveCriticalSection(&(mutex))
#define MUTEX(mutex) CRITICAL_SECTION (mutex)
#define INIT_MUTEX(mutex) InitializeCriticalSection(&(mutex))
#define TINI_MUTEX(mutex) DeleteCriticalSection(&(mutex))
#else
#include <sys/socket.h>
@ -153,7 +142,7 @@ static struct _rfbKeyboardEvent {
int z;
} rfbKeyboardEvent[MAX_KEY_EVENTS];
static unsigned long rfbKeyboardEvents = 0;
static MUTEX(bKeyboardInUse);
static BX_MUTEX(bKeyboardInUse);
// Misc Stuff
@ -325,7 +314,7 @@ void bx_vncsrv_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y)
rfbInitServer(screen);
client_connected = 0;
INIT_MUTEX(bKeyboardInUse);
BX_INIT_MUTEX(bKeyboardInUse);
vncStartThread();
#ifdef WIN32
@ -376,7 +365,7 @@ void bx_vncsrv_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y)
void bx_vncsrv_gui_c::handle_events(void)
{
LOCK(bKeyboardInUse);
BX_LOCK(bKeyboardInUse);
if (rfbKeyboardEvents > 0) {
for (unsigned i = 0; i < rfbKeyboardEvents; i++) {
@ -388,7 +377,7 @@ void bx_vncsrv_gui_c::handle_events(void)
}
rfbKeyboardEvents = 0;
}
UNLOCK(bKeyboardInUse);
BX_UNLOCK(bKeyboardInUse);
#if BX_SHOW_IPS
if (rfbIPSupdate) {
@ -810,7 +799,7 @@ void bx_vncsrv_gui_c::exit(void)
while (!rfbServerDown) {
usleep(10000); //10ms
}
TINI_MUTEX(bKeyboardInUse);
BX_FINI_MUTEX(bKeyboardInUse);
for (i = 0; i < rfbBitmapCount; i++) {
free(rfbBitmaps[i].bmap);
@ -1424,14 +1413,14 @@ void dokey(rfbBool down, rfbKeySym key, rfbClientPtr cl)
if (mouse_toggle) {
bx_gui->toggle_mouse_enable();
} else {
LOCK(bKeyboardInUse);
BX_LOCK(bKeyboardInUse);
if (rfbKeyboardEvents >= MAX_KEY_EVENTS)
return;
rfbKeyboardEvent[rfbKeyboardEvents].type = KEYBOARD;
rfbKeyboardEvent[rfbKeyboardEvents].key = key;
rfbKeyboardEvent[rfbKeyboardEvents].down = down;
rfbKeyboardEvents++;
UNLOCK(bKeyboardInUse);
BX_UNLOCK(bKeyboardInUse);
}
}
@ -1442,7 +1431,7 @@ void doptr(int buttonMask, int x, int y, rfbClientPtr cl)
if (bx_gui->mouse_toggle_check(BX_MT_MBUTTON, (buttonMask & 0x02) > 0)) {
bx_gui->toggle_mouse_enable();
} else {
LOCK(bKeyboardInUse);
BX_LOCK(bKeyboardInUse);
if (rfbKeyboardEvents >= MAX_KEY_EVENTS)
return;
rfbKeyboardEvent[rfbKeyboardEvents].type = MOUSE;
@ -1461,7 +1450,7 @@ void doptr(int buttonMask, int x, int y, rfbClientPtr cl)
wheel_status = buttonMask & 0x18;
}
rfbKeyboardEvents++;
UNLOCK(bKeyboardInUse);
BX_UNLOCK(bKeyboardInUse);
}
}

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011-2014 The Bochs Project
// Copyright (C) 2011-2015 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -38,6 +38,7 @@
#define BX_SOUNDLOW_ALSA 5
typedef Bit32u (*sound_record_handler_t)(void *arg, Bit32u len);
typedef Bit32u (*waveout_callback_t)(void *arg, Bit16u rate, Bit8u *buffer, Bit32u len);
// The class with the input/output functions
class bx_sound_lowlevel_c : public logfunctions {
@ -76,6 +77,8 @@ public:
static void record_timer_handler(void *);
void record_timer(void);
virtual bx_bool set_waveout_callback(void *, waveout_callback_t wocb) {return 0;}
protected:
int record_timer_index;
int record_packet_size;

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011-2014 The Bochs Project
// Copyright (C) 2011-2015 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -48,6 +48,12 @@
bx_soundmod_ctl_c* theSoundModCtl = NULL;
Bit8u *beep_buffer;
unsigned int beep_bufsize;
BX_MUTEX(beep_mutex);
Bit32u beep_callback(void *dev, Bit16u rate, Bit8u *buffer, Bit32u len);
int CDECL libsoundmod_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
{
if (type == PLUGTYPE_CORE) {
@ -72,6 +78,7 @@ bx_soundmod_ctl_c::bx_soundmod_ctl_c()
bx_soundmod_ctl_c::~bx_soundmod_ctl_c()
{
free(beep_buffer);
if (soundmod != NULL) {
soundmod->closewaveoutput();
}
@ -121,6 +128,17 @@ void bx_soundmod_ctl_c::init()
int ret = soundmod->openwaveoutput(waveout);
if (ret != BX_SOUNDLOW_OK) {
BX_PANIC(("Could not open wave output device"));
} else {
beep_active = 0;
use_new_sound_api = soundmod->set_waveout_callback(theSoundModCtl, beep_callback);
beep_cur_freq = 0.0;
beep_level = 0x40;
beep_bufsize = 4410;
beep_buffer = (Bit8u*)malloc(beep_bufsize);
BX_INIT_MUTEX(beep_mutex);
if (use_new_sound_api) {
soundmod->startwaveplayback(44100, 16, 1, 1);
}
}
}
@ -129,11 +147,38 @@ void* bx_soundmod_ctl_c::get_module()
return soundmod;
}
#ifndef WIN32
pthread_t thread;
Bit32u bx_soundmod_ctl_c::beep_generator(Bit16u rate, Bit8u *buffer, Bit32u len)
{
Bit32u j = 0;
if (!beep_active) {
return 0;
}
do {
buffer[j++] = 0;
buffer[j++] = beep_level;
buffer[j++] = 0;
buffer[j++] = beep_level;
BX_LOCK(beep_mutex);
if ((++beep_pos % beep_samples) == 0) {
beep_level ^= 0x80;
beep_pos = 0;
}
BX_UNLOCK(beep_mutex);
} while (j < len);
return len;
}
Bit32u beep_callback(void *dev, Bit16u rate, Bit8u *buffer, Bit32u len)
{
return ((bx_soundmod_ctl_c*)dev)->beep_generator(rate, buffer, len);
}
#ifdef WIN32
DWORD threadID;
#else
pthread_t threadID;
#endif
Bit8u *beep_buffer;
unsigned int beep_bytes, beep_bufsize;
Bit8u beep_control = 0;
#ifdef WIN32
@ -142,33 +187,24 @@ DWORD WINAPI beep_thread(LPVOID indata)
void beep_thread(void *indata)
#endif
{
Bit8u level;
unsigned int i, j;
int ret;
bx_sound_lowlevel_c *soundmod = (bx_sound_lowlevel_c*)indata;
level = 0x40;
i = 0;
while (beep_control == 2) {
j = 0;
do {
beep_buffer[j++] = level;
if ((++i % beep_bytes) == 0) level ^= 0x40;
} while (j < beep_bufsize);
theSoundModCtl->beep_generator(44100, beep_buffer, beep_bufsize);
ret = soundmod->sendwavepacket(beep_bufsize, beep_buffer);
if (ret == BX_SOUNDLOW_ERR) break;
if (soundmod->get_type() == BX_SOUNDLOW_WIN) {
#ifdef WIN32
Sleep(100);
Sleep(25);
#endif
} else if (soundmod->get_type() == BX_SOUNDLOW_SDL) {
#if BX_WITH_SDL || BX_WITH_SDL2
SDL_Delay(100);
SDL_Delay(25);
#endif
}
}
soundmod->stopwaveplayback();
free(beep_buffer);
beep_control = 0;
#ifdef WIN32
return 0;
@ -181,23 +217,29 @@ bx_bool bx_soundmod_ctl_c::beep_on(float frequency)
{
if (soundmod != NULL) {
BX_DEBUG(("Beep ON (frequency=%.2f)",frequency));
if (beep_control > 0) {
beep_off();
if (frequency != beep_cur_freq) {
BX_LOCK(beep_mutex);
beep_cur_freq = frequency;
beep_samples = (Bit32u)(44100.0 / beep_cur_freq / 2);
beep_active = 1;
BX_UNLOCK(beep_mutex);
}
if (soundmod->startwaveplayback(44100, 8, 0, 0) == BX_SOUNDLOW_ERR) {
return 0;
}
beep_bytes = (int)(44100.0 / frequency / 2);
beep_bufsize = 4410;
beep_buffer = (Bit8u*)malloc(beep_bufsize);
beep_control = 2;
if (use_new_sound_api) {
return 1;
} else {
if (beep_control != 2) {
if (soundmod->startwaveplayback(44100, 16, 1, 1) == BX_SOUNDLOW_ERR) {
return 0;
}
beep_control = 2;
#ifdef WIN32
DWORD threadID;
CreateThread(NULL, 0, beep_thread, soundmod, 0, &threadID);
CreateThread(NULL, 0, beep_thread, soundmod, 0, &threadID);
#else
pthread_create(&thread, NULL, (void *(*)(void *))&beep_thread, soundmod);
pthread_create(&threadID, NULL, (void *(*)(void *))&beep_thread, soundmod);
#endif
return 1;
}
return 1;
}
}
return 0;
}
@ -206,15 +248,20 @@ bx_bool bx_soundmod_ctl_c::beep_off()
{
if (soundmod != NULL) {
BX_DEBUG(("Beep OFF"));
if (beep_control > 0) {
beep_control = 1;
beep_active = 0;
if (use_new_sound_api) {
return 1;
} else {
if (beep_control > 0) {
beep_control = 1;
#ifdef WIN32
while (beep_control > 0) Sleep(1);
while (beep_control > 0) Sleep(1);
#else
pthread_join(thread, NULL);
pthread_join(threadID, NULL);
#endif
}
return 1;
}
return 1;
}
return 0;
}

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011-2014 The Bochs Project
// Copyright (C) 2011-2015 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -36,6 +36,12 @@ public:
Bit8u header[], Bit32u datalen, Bit8u data[]);
virtual void pcm_apply_volume(Bit32u datalen, Bit8u data[], Bit16u volume,
Bit8u bits, bx_bool stereo, bx_bool issigned);
Bit32u beep_generator(Bit16u rate, Bit8u *buffer, Bit32u len);
private:
bx_sound_lowlevel_c *soundmod;
bx_bool use_new_sound_api;
bx_bool beep_active;
Bit8u beep_level;
Bit16u beep_samples, beep_pos;
float beep_cur_freq;
};

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2012-2014 The Bochs Project
// Copyright (C) 2012-2015 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -43,6 +43,7 @@ bx_sound_sdl_c::bx_sound_sdl_c()
:bx_sound_lowlevel_c()
{
WaveOpen = 0;
wo_cb = NULL;
if (SDL_InitSubSystem(SDL_INIT_AUDIO)) {
BX_PANIC(("Initialization of sound lowlevel module 'sdl' failed"));
} else {
@ -58,12 +59,31 @@ bx_sound_sdl_c::~bx_sound_sdl_c()
int bx_sound_sdl_c::openwaveoutput(const char *wavedev)
{
WaveOpen = 1;
return BX_SOUNDLOW_OK;
}
void sdl_callback(void *unused, Bit8u *stream, int len)
Bit32u bx_sound_sdl_c::get_wave_data(Bit8u *stream, int len)
{
if (wo_cb == NULL) {
return 0;
}
Bit8u *tmpbuffer = (Bit8u*)malloc(len);
memset(tmpbuffer, 0, len);
Bit32u len2 = wo_cb(dev, 44100, tmpbuffer, len);
if (len2 > 0) {
SDL_MixAudio(stream, tmpbuffer, len2, SDL_MIX_MAXVOLUME);
}
free(tmpbuffer);
return len2;
}
void sdl_callback(void *thisptr, Bit8u *stream, int len)
{
memset(stream, 0, len);
// FIXME: mix wave data
if (((bx_sound_sdl_c*)thisptr)->get_wave_data(stream, len) > 0) {
return;
}
int amount = audio_buffer.iptr - audio_buffer.optr;
if (amount < 0) {
amount += BX_SOUND_SDL_BUFSIZE;
@ -107,13 +127,20 @@ int bx_sound_sdl_c::startwaveplayback(int frequency, int bits, bx_bool stereo, i
fmt.channels = stereo + 1;
fmt.samples = frequency / 10;
fmt.callback = sdl_callback;
fmt.userdata = NULL;
fmt.userdata = this;
if (WaveOpen) {
SDL_CloseAudio();
}
if (SDL_OpenAudio(&fmt, NULL) < 0) {
BX_PANIC(("SDL_OpenAudio() failed"));
WaveOpen = 0;
return BX_SOUNDLOW_ERR;
} else {
WaveOpen = 1;
}
audio_buffer.iptr = 0;
audio_buffer.optr = 0;
SDL_PauseAudio(0);
return BX_SOUNDLOW_OK;
}
@ -166,13 +193,20 @@ int bx_sound_sdl_c::stopwaveplayback()
SDL_Delay(1);
}
SDL_CloseAudio();
WaveOpen = 0;
return BX_SOUNDLOW_OK;
}
int bx_sound_sdl_c::closewaveoutput()
{
WaveOpen = 0;
return BX_SOUNDLOW_OK;
}
bx_bool bx_sound_sdl_c::set_waveout_callback(void *arg, waveout_callback_t wocb)
{
dev = arg;
wo_cb = wocb;
return 1;
}
#endif // BX_WITH_SDL || BX_WITH_SDL2

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2012 The Bochs Project
// Copyright (C) 2012-2015 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -39,8 +39,13 @@ public:
virtual int sendwavepacket(int length, Bit8u data[]);
virtual int stopwaveplayback();
virtual int closewaveoutput();
virtual bx_bool set_waveout_callback(void *, waveout_callback_t wocb);
Bit32u get_wave_data(Bit8u *stream, int len);
private:
bx_bool WaveOpen;
void *dev;
waveout_callback_t wo_cb;
};
#endif // BX_WITH_SDL || BX_WITH_SDL2