Hi,
I have been playing with getting sound to work for RPCEmu on Linux. I
have attached a patch.
I have modified sound.c slightly, but have not tested it under Windows.
I see no reason why it should not work.
It seems OK, the occasional glitch. I have played some Maestro files,
and Asylum.
Hope it is useful.
James
Index: rpcemu.c
===================================================================
--- rpcemu.c (revision 132)
+++ rpcemu.c (working copy)
@@ -105,8 +105,8 @@
//printf("About to init video...\n");
initvideo();
//printf("Video inited!\n");
+ loadconfig();
initsound();
- loadconfig();
reallocmem(rammask+1);
initcodeblocks();
iso_init();
Index: rpc-linux.c
===================================================================
--- rpc-linux.c (revision 132)
+++ rpc-linux.c (working copy)
@@ -14,14 +14,63 @@
int mousecapture=0;
float mips;
int updatemips=0;
+int quited=0;
+pthread_t sound_thread;
+pthread_cond_t sound_cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t sound_mutex = PTHREAD_MUTEX_INITIALIZER;
static uint32_t mipscount;
float mipstotal;
+void *_soundthread(void *p)
+{
+ int c;
+
+ if (pthread_mutex_lock(&sound_mutex))
+ {
+ fatal("Cannot lock mutex");
+ }
+ while (!quited)
+ {
+ if (pthread_cond_wait(&sound_cond, &sound_mutex))
+ {
+ fatal("pthread_cond_wait failed");
+ }
+ if (!quited)
+ {
+ do {
+ c = updatesoundbuffer();
+ } while(c);
+ }
+ }
+ pthread_mutex_unlock(&sound_mutex);
+
+ return NULL;
+}
+
void wakeupsoundthread()
{
+ if (pthread_cond_signal(&sound_cond))
+ {
+ fatal("Couldn't signal vidc thread");
+ }
}
+void closesoundthread()
+{
+ wakeupsoundthread();
+ pthread_join(sound_thread, NULL);
+}
+
+void startsoundthread(void)
+{
+ int r;
+ if (pthread_create(&sound_thread,NULL,_soundthread,NULL))
+ {
+ fatal("Couldn't create vidc thread");
+ }
+}
+
static void domips(void)
{
mips=(float)inscount/1000000.0f;
@@ -70,8 +119,6 @@
{
}
-int quited=0;
-
#ifdef VIDC_THREAD
pthread_t thread;
pthread_cond_t vidccond = PTHREAD_COND_INITIALIZER;
@@ -160,6 +207,7 @@
install_int_ex(domips,MSEC_TO_TIMER(1000));
install_int_ex(vblupdate,BPS_TO_TIMER(refresh));
+ startsoundthread();
if (soundenabled) initsound();
infocus=1;
mousehackon=1;
Index: sound.c
===================================================================
--- sound.c (revision 132)
+++ sound.c (working copy)
@@ -7,38 +7,43 @@
#include "mem.h"
#include "iomd.h"
+int getbufferlen();
+
int soundenabled;
-int soundbufferfull;
-int getbufferlen();
uint32_t soundaddr[4];
static int samplefreq;
int soundinited,soundlatch,soundcount;
+static unsigned short bigsoundbuffer[8][44100<<1];
+static int bigsoundpos=0;
+static int bigsoundbufferhead=0; // sound buffer being written to
+static int bigsoundbuffertail=0; // sound buffer being read from
+static int oldsamplefreq=44100;
+static int soundon=0;
+static AUDIOSTREAM *as;
-AUDIOSTREAM *as;
#define BUFFERLEN (4410>>1)
//#define BUFFERLEN 11025
-int soundon=0;
-
void initsound()
{
if (soundon)
{
stop_audio_stream(as);
- if (soundenabled) as=play_audio_stream(BUFFERLEN,16,1,44100,0,128);
- else as=play_audio_stream(BUFFERLEN,16,1,44100,255,128);
}
- install_sound(DIGI_AUTODETECT,MIDI_NONE,0);
- if (soundenabled) as=play_audio_stream(BUFFERLEN,16,1,44100,0,128);
- else as=play_audio_stream(BUFFERLEN,16,1,44100,255,128);
- samplefreq=44100;
- soundon=1;
+ else
+ {
+ install_sound(DIGI_AUTODETECT,MIDI_NONE,0);
+ samplefreq=44100;
+ soundon=1;
+ }
+ if (soundenabled) as=play_audio_stream(BUFFERLEN,16,1,samplefreq,255,128);
+ else as=play_audio_stream(BUFFERLEN,16,1,samplefreq,0,128);
}
void closesound()
{
stop_audio_stream(as);
- as=play_audio_stream(BUFFERLEN,16,1,44100,0,128);
+ as=play_audio_stream(BUFFERLEN,16,1,samplefreq,0,128);
// remove_sound();
}
@@ -50,19 +55,7 @@
return end-start;
}
-int bufferlen=100;
-unsigned short sndbuffer[16384];
-int sndsamples,sndpos=0,sndoffset=0;
-int soundinited;
-
-int soundcount=0,soundlatch;
-unsigned short bigsoundbuffer[8][44100<<1];
-int bigsoundbufferselect=0,bigsoundpos=0;
-int updatebigsound=0;
-
-int oldsamplefreq=44100;
-
int getsamplefreq()
{
return samplefreq;
@@ -94,17 +87,25 @@
voice_set_volume(as->voice,255);
}
-int curbigsoundbuffer=0;
-
void updatesoundirq()
{
uint32_t page,start,end,temp;
int offset=(iomd.sndstat&1)<<1;
int len;
unsigned int c;
- if (soundbufferfull && bigsoundbufferselect==curbigsoundbuffer)
+
+ if (!soundenabled)
{
+ return;
+ }
+
+ // If bigsoundbufferhead is 1 less than bigsoundbuffertail, then
+ // the buffer list is full.
+ if (((bigsoundbufferhead+1)&7)==bigsoundbuffertail)
+ {
soundcount+=4000;
+ // kick the sound thread to clear the list
+ wakeupsoundthread();
return;
}
page=soundaddr[offset]&0xFFFFF000;
@@ -120,51 +121,54 @@
for (c=start;c<end;c+=4)
{
temp=ram[((c+page)&rammask)>>2];
- bigsoundbuffer[bigsoundbufferselect][bigsoundpos++]=(temp&0xFFFF);//^0x8000;
- bigsoundbuffer[bigsoundbufferselect][bigsoundpos++]=(temp>>16);//&0x8000;
+ bigsoundbuffer[bigsoundbufferhead][bigsoundpos++]=(temp&0xFFFF);//^0x8000;
+ bigsoundbuffer[bigsoundbufferhead][bigsoundpos++]=(temp>>16);//&0x8000;
if (bigsoundpos>=(BUFFERLEN<<1))
{
-// rpclog("Just finished buffer %i\n",bigsoundbufferselect);
- bigsoundbufferselect++;
- bigsoundbufferselect&=7;
+// rpclog("Just finished buffer %i\n",bigsoundbufferhead);
+ bigsoundbufferhead++;
+ bigsoundbufferhead&=7;
bigsoundpos=0;
- soundbufferfull++;
wakeupsoundthread();
}
}
// fwrite(bigsoundbuffer,len<<2,1,sndfile);
}
-FILE *sndfile;
+static FILE *sndfile;
int updatesoundbuffer()
{
unsigned short *p;
int c;
+ static int cnt = 0;
+
if (!soundenabled)
{
- soundbufferfull=0;
return 0;
}
/* if (!sndfile)
{
sndfile=fopen("sound.pcm","wb");
}*/
- p=get_audio_stream_buffer(as);
- while (!p)
+ while (bigsoundbuffertail!=bigsoundbufferhead)
{
-// sleep(0);
p=get_audio_stream_buffer(as);
+ if (p)
+ {
+ for (c=0;c<(BUFFERLEN<<1);c++)
+ p[c]=bigsoundbuffer[bigsoundbuffertail][c]^0x8000;
+ free_audio_stream_buffer(as);
+// rpclog("Writing buffer %i\n",bigsoundbuffertail);
+// fwrite(bigsoundbuffer[bigsoundbufferhead^1],BUFFERLEN<<2,1,sndfile);
+ bigsoundbuffertail++;
+ bigsoundbuffertail&=7;
+ }
+ else
+ {
+ // No free audio buffer, try again later.
+ break;
+ }
}
- soundbufferfull--;
-// while (!p)
-// p=get_audio_stream_buffer(as);
- for (c=0;c<(BUFFERLEN<<1);c++)
- p[c]=bigsoundbuffer[curbigsoundbuffer][c]^0x8000;
- free_audio_stream_buffer(as);
-// rpclog("Writing buffer %i\n",curbigsoundbuffer);
- curbigsoundbuffer++;
- curbigsoundbuffer&=7;
return 0;
-// fwrite(bigsoundbuffer[bigsoundbufferselect^1],BUFFERLEN<<2,1,sndfile);
}
_______________________________________________
Rpcemu mailing list
[email protected]
http://www.riscos.info/cgi-bin/mailman/listinfo/rpcemu