shithub: hexen

Download patch

ref: ccf2bfb8f14f347510963da242adf74f4131e5f9
parent: 78e9b63d292b42b7fc988e814fed81bab6b338c7
author: Jacob Moody <moody@posixcafe.org>
date: Sun Jan 22 02:44:49 EST 2023

first video blit

--- a/i_sound.c
+++ b/i_sound.c
@@ -1,182 +1,437 @@
-/* i_sound.c */
+//**************************************************************************
+//**
+//** i_soundpi.c: unix sound driver using a plugin interface
+//**
+//** $Revision: 512 $
+//** $Date: 2009-06-04 18:00:34 +0300 (Thu, 04 Jun 2009) $
+//**
+//**************************************************************************
 
-#include "i_system.h"
+
+#include "h2stdinc.h"
+#include "h2def.h"
+#include "sounds.h"
 #include "i_sound.h"
-//#include "w_wad.h"	// W_GetNumForName()
-//#include "z_zone.h"
-//#include "m_argv.h"
+#include "audio_plugin.h"
 
-/* The number of internal mixing channels,
-**  the samples calculated for each mixing step,
-**  the size of the 16bit, 2 hardware channel (stereo)
-**  mixing buffer, and the samplerate of the raw data.
-*/
 
-/* Needed for calling the actual sound output. */
-#define	AUDFREQ		44100
-#define	SFXFREQ		11025
-#define	SAMPLECOUNT	(AUDFREQ/TICRATE)
-#define	NUM_CHANNELS	8
+#define SAMPLE_FORMAT	FMT_S16_NE
+#define SAMPLE_ZERO	0
+#define SAMPLE_RATE	11025	/* Hz */
+#define SAMPLE_CHANNELS	2
 
-/* The actual lengths of all sound effects. */
-int	lengths[NUMSFX];
+#if 0
+#define SAMPLE_TYPE	char
+#else
+#define SAMPLE_TYPE	short
+#endif
 
-/* The actual output device. */
-static int audio_fd = -1;
 
-/* The global mixing buffer.
-** Basically, samples from all active internal channels
-**  are modified and added, and stored in the buffer
-**  that is submitted to the audio device.
-*/
-uchar mixbuf[SAMPLECOUNT*4];
+/*
+ *	SOUND HEADER & DATA
+ */
 
-/* The channel step amount... */
-uint	channelstep[NUM_CHANNELS];
-/* ... and a 0.16 bit remainder of last step. */
-uint	channelstepremainder[NUM_CHANNELS];
+int snd_Channels;
+int snd_MaxVolume,		/* maximum volume for sound */
+	snd_MusicVolume;	/* maximum volume for music */
+boolean snd_MusicAvail,		/* whether music is available */
+	snd_SfxAvail;		/* whether sfx are available */
 
-/* The channel data pointers, start and end. */
-uchar*	channels[NUM_CHANNELS];
-uchar*	channelsend[NUM_CHANNELS];
+/*
+ *	SOUND FX API
+ */
 
-/* Time/gametic that the channel started playing,
-**  used to determine oldest, which automatically
-**  has lowest priority.
-** In case number of active sounds exceeds
-**  available channels.
-*/
-int	channelstart[NUM_CHANNELS];
-
-/* The sound in channel handles,
-**  determined on registration,
-**  might be used to unregister/stop/modify,
-**  currently unused.
-*/
-int	channelhandles[NUM_CHANNELS];
+typedef struct
+{
+	unsigned char	*begin;		/* pointers into Sample.firstSample */
+	unsigned char	*end;
+
+	SAMPLE_TYPE	*lvol_table;	/* point into vol_lookup */
+	SAMPLE_TYPE	*rvol_table;
+
+	unsigned int	pitch_step;
+	unsigned int	step_remainder;	/* 0.16 bit remainder of last step. */
+
+	int		pri;
+	unsigned int	time;
+} Channel;
+
+#pragma pack on
+typedef struct
+{
+/* Sample data is a lump from a wad: byteswap the a, freq
+ * and the length fields before using them		*/
+	short		a;		/* always 3	*/
+	short		freq;		/* always 11025	*/
+	int32_t		length;		/* sample length */
+	unsigned char	firstSample;
+} Sample;
 
-/* SFX id of the playing sound effect.
-** Used to catch duplicates (like chainsaw).
-*/
-int	channelids[NUM_CHANNELS];
+#pragma pack off
 
-/* Pitch to stepping lookup, unused. */
-int	steptable[256];
+static int	audio_exit_thread = 1;
+//static pthread_t	audio_thread;
 
-/* Volume lookups. */
-int	vol_lookup[128*256];
 
-/* Hardware left and right channel volume lookup. */
-int*	channelleftvol_lookup[NUM_CHANNELS];
-int*	channelrightvol_lookup[NUM_CHANNELS];
+#define CHAN_COUNT	8
+static Channel	channel[CHAN_COUNT];
 
-int snd_MaxVolume;
-int UpdateState;
-int snd_Channels;
-int snd_MusicVolume;
+#define MAX_VOL		64	/* 64 keeps our table down to 16Kb */
+static SAMPLE_TYPE	vol_lookup[MAX_VOL * 256];
 
-void I_StartupSound(void)
-{
-}
+static int	steptable[256];		/* Pitch to stepping lookup */
 
-void I_InitSound(void)
-{
-}
+#define BUF_LEN		(256 * 2)
 
-/* This function loops all active (internal) sound
-**  channels, retrieves a given number of samples
-**  from the raw sound data, modifies it according
-**  to the current (internal) channel parameters,
-**  mixes the per-channel samples into the global
-**  mixbuffer, clamping it to the allowed range,
-**  and sets up everything for transferring the
-**  contents of the mixbuffer to the (two)
-**  hardware channels (left and right, that is).
-**
-** This function currently supports only 16bit.
-*/
-void I_UpdateSound(void)
-{
-}
 
-void I_ShutdownSound(void)
+static void audio_loop (void *arg)
 {
+	Channel* chan;
+	Channel* cend;
+	char buf[BUF_LEN];
+	SAMPLE_TYPE *begin;
+	SAMPLE_TYPE *end;
+	unsigned int sample;
+	register int dl;
+	register int dr;
+
+	end = (SAMPLE_TYPE *) (buf + BUF_LEN);
+	cend = channel + CHAN_COUNT;
+
+    while (! audio_exit_thread) {
+
+	begin = (SAMPLE_TYPE *) buf;
+	while (begin < end)
+	{
+	// Mix all the channels together.
+		dl = SAMPLE_ZERO;
+		dr = SAMPLE_ZERO;
+
+		chan = channel;
+		for ( ; chan < cend; chan++)
+		{
+			// Check channel, if active.
+			if (chan->begin)
+			{
+				// Get the sample from the channel.
+				sample = *chan->begin;
+
+				// Adjust volume accordingly.
+				dl += chan->lvol_table[sample];
+				dr += chan->rvol_table[sample];
+
+				// Increment sample pointer with pitch adjustment.
+				chan->step_remainder += chan->pitch_step;
+				chan->begin += chan->step_remainder >> 16;
+				chan->step_remainder &= 65535;
+
+				// Check whether we are done.
+				if (chan->begin >= chan->end)
+				{
+					chan->begin = NULL;
+				//	printf ("  channel done %d\n", chan);
+				}
+			}
+		}
+
+#if 0	/* SAMPLE_FORMAT */
+		if (dl > 127)
+			dl = 127;
+		else if (dl < -128)
+			dl = -128;
+		if (dr > 127)
+			dr = 127;
+		else if (dr < -128)
+			dr = -128;
+#else
+		if (dl > 0x7fff)
+			dl = 0x7fff;
+		else if (dl < -0x8000)
+			dl = -0x8000;
+		if (dr > 0x7fff)
+			dr = 0x7fff;
+		else if (dr < -0x8000)
+			dr = -0x8000;
+#endif
+
+		*begin++ = dl;
+		*begin++ = dr;
+	}
+
+	// This write is expected to block.
+	//audioPI->write_audio(buf, BUF_LEN);
+
+    } /* end of the while(!audio_exit_thread) loop. */
+
+    //pthread_exit(NULL);
 }
 
-void I_SetChannels(int channels)
+
+void I_SetSfxVolume(int volume)
 {
 }
 
-int I_GetSfxLumpNum(sfxinfo_t *sfxinfo)
+// Gets lump nums of the named sound.  Returns pointer which will be
+// passed to I_StartSound() when you want to start an SFX.  Must be
+// sure to pass this to UngetSoundEffect() so that they can be
+// freed!
+
+int I_GetSfxLumpNum(sfxinfo_t *sound)
 {
-	return 0;
+	return W_GetNumForName(sound->lumpname);
 }
 
-int I_StartSound(int id, void *data, int vol, int sep, int pitch, int)
+
+// Id is unused.
+// Data is a pointer to a Sample structure.
+// Volume ranges from 0 to 127.
+// Separation (orientation/stereo) ranges from 0 to 255.  128 is balanced.
+// Pitch ranges from 0 to 255.  Normal is 128.
+// Priority looks to be unused (always 0).
+
+int I_StartSound(int id, void *data, int vol, int sep, int pitch, int priority)
 {
-	return 0;
+	// Relative time order to find oldest sound.
+	static unsigned int soundTime = 0;
+	int chanId;
+	Sample *sample;
+	Channel *chan;
+	int oldest;
+	int i;
+
+	// Find an empty channel, the oldest playing channel, or default to 0.
+	// Currently ignoring priority.
+
+	chanId = 0;
+	oldest = soundTime;
+	for (i = 0; i < CHAN_COUNT; i++)
+	{
+		if (! channel[ i ].begin)
+		{
+			chanId = i;
+			break;
+		}
+		if (channel[ i ].time < oldest)
+		{
+			chanId = i;
+			oldest = channel[ i ].time;
+		}
+	}
+
+	sample = (Sample *) data;
+	chan = &channel[chanId];
+
+	I_UpdateSoundParams(chanId + 1, vol, sep, pitch);
+
+	// begin must be set last because the audio thread will access the channel
+	// once it is non-zero.  Perhaps this should be protected by a mutex.
+	chan->pri = priority;
+	chan->time = soundTime;
+	chan->end = &sample->firstSample + LONG(sample->length);
+	chan->begin = &sample->firstSample;
+
+	soundTime++;
+
+#if 0
+	printf ("I_StartSound %d: v:%d s:%d p:%d pri:%d | %d %d %d %d\n",
+		id, vol, sep, pitch, priority,
+		chanId, chan->pitch_step, SHORT(sample->a), SHORT(sample->freq));
+#endif
+
+	return chanId + 1;
 }
 
 void I_StopSound(int handle)
 {
-	USED(handle);
-//	printf("PORTME i_sound.c I_StopSound\n");
+	handle--;
+	handle &= 7;
+	channel[handle].begin = NULL;
 }
 
 int I_SoundIsPlaying(int handle)
 {
-	return 1;
+	handle--;
+	handle &= 7;
+	return (channel[ handle ].begin != NULL);
 }
 
 void I_UpdateSoundParams(int handle, int vol, int sep, int pitch)
 {
-	/* I fail to see that this is used.
-	** Would be using the handle to identify
-	**  on which channel the sound might be active,
-	**  and resetting the channel parameters.
+	int lvol, rvol;
+	Channel *chan;
+
+	// Set left/right channel volume based on seperation.
+	sep += 1;	// range 1 - 256
+	lvol = vol - ((vol * sep * sep) >> 16);	// (256*256);
+	sep = sep - 257;
+	rvol = vol - ((vol * sep * sep) >> 16);
+
+	// Sanity check, clamp volume.
+	if (rvol < 0)
+	{
+	//	printf ("rvol out of bounds %d, id %d\n", rvol, handle);
+		rvol = 0;
+	}
+	else if (rvol > 127)
+	{
+	//	printf ("rvol out of bounds %d, id %d\n", rvol, handle);
+		rvol = 127;
+	}
+
+	if (lvol < 0)
+	{
+	//	printf ("lvol out of bounds %d, id %d\n", lvol, handle);
+		lvol = 0;
+	}
+	else if (lvol > 127)
+	{
+	//	printf ("lvol out of bounds %d, id %d\n", lvol, handle);
+		lvol = 127;
+	}
+
+	// Limit to MAX_VOL (64)
+	lvol >>= 1;
+	rvol >>= 1;
+
+	handle--;
+	handle &= 7;
+	chan = &channel[handle];
+	chan->pitch_step = steptable[pitch];
+	chan->step_remainder = 0;
+	chan->lvol_table = &vol_lookup[lvol * 256];
+	chan->rvol_table = &vol_lookup[rvol * 256];
+}
+
+
+/*
+ *	SOUND STARTUP STUFF
+ */
+
+// inits all sound stuff
+void I_StartupSound (void)
+{
+	/*
+	int ok;
+
+	snd_SfxAvail = false;
+
+	if (M_CheckParm("--nosound") || M_CheckParm("-s") || M_CheckParm("-nosound"))
+	{
+		ST_Message("I_StartupSound: Sound Disabled.\n");
+		return;
+	}
+
+	// Using get_oplugin_info() from oss.c.  In the future this could
+	//   load from a real shared library plugin.
+	audioPI = get_oplugin_info();
+	if (!audioPI)
+		return;
+	audioPI->init();
+	audioPI->about();
+
+	ok = audioPI->open_audio(SAMPLE_FORMAT, SAMPLE_RATE, SAMPLE_CHANNELS);
+	if (ok)
+	{
+		audio_exit_thread = 0;
+		pthread_create(&audio_thread, NULL, audio_loop, NULL);
+		fprintf (stdout, "I_StartupSound: success\n");
+		snd_SfxAvail = true;
+	}
+	else
+	{
+		fprintf (stderr, "I_StartupSound: failed\n");
+	}
 	*/
-	USED(handle, vol, sep, pitch);
 }
 
-void I_InitMusic(void)
+// shuts down all sound stuff
+void I_ShutdownSound (void)
 {
+	snd_SfxAvail = false;
 }
 
-void I_ShutdownMusic(void)
+void I_SetChannels(int channels)
 {
+	int v, j;
+	int *steptablemid;
+
+	// We always have CHAN_COUNT channels.
+
+	for (j = 0; j < CHAN_COUNT; j++)
+	{
+		channel[j].begin = NULL;
+		channel[j].end   = NULL;
+		channel[j].time = 0;
+	}
+
+	// This table provides step widths for pitch parameters.
+	steptablemid = steptable + 128;
+	for (j = -128; j < 128; j++)
+	{
+		steptablemid[j] = (int) (pow(2.0, (j/64.0)) * 65536.0);
+	}
+
+	// Generate the volume lookup tables.
+	for (v = 0; v < MAX_VOL; v++)
+	{
+		for (j = 0; j < 256; j++)
+		{
+		//	vol_lookup[v*256+j] = 128 + ((v * (j-128)) / (MAX_VOL-1));
+
+		// Turn the unsigned samples into signed samples.
+
+#if 0	/* SAMPLE_FORMAT */
+			vol_lookup[v*256+j] = (v * (j-128)) / (MAX_VOL-1);
+#else
+			vol_lookup[v*256+j] = (v * (j-128) * 256) / (MAX_VOL-1);
+#endif
+		//	printf ("vol_lookup[%d*256+%d] = %d\n", v, j, vol_lookup[v*256+j]);
+		}
+	}
 }
 
-void I_SetMusicVolume(int)
+
+/*
+ *	SONG API
+ */
+
+int I_RegisterSong(void *data)
 {
+	return 0;
 }
 
-void I_PauseSong(int)
+int I_RegisterExternalSong(const char *nm)
 {
+	return 0;
 }
 
-void I_ResumeSong(int)
+void I_UnRegisterSong(int handle)
 {
 }
 
-void I_PlaySong(int handle, int loop)
+void I_PauseSong(int handle)
 {
 }
 
-void I_StopSong(int)
+void I_ResumeSong(int handle)
 {
-	I_ShutdownMusic();
 }
 
-int I_RegisterSong(void *data)
+void I_SetMusicVolume(int volume)
 {
+}
+
+int I_QrySongPlaying(int handle)
+{
 	return 0;
 }
 
-void I_UnRegisterSong(int handle)
+// Stops a song.  MUST be called before I_UnregisterSong().
+void I_StopSong(int handle)
 {
 }
 
-int I_RegisterExternalSong(char *name)
+void I_PlaySong(int handle, boolean looping)
 {
-	return 0;
 }
+
--- a/i_system.c
+++ b/i_system.c
@@ -13,7 +13,7 @@
 
 void I_Init (void)
 {
-	I_InitSound();
+	S_Init();
 	I_MouseEnable(1);
 }
 
@@ -39,7 +39,6 @@
 {
 	D_QuitNetGame ();
 	I_ShutdownSound();
-	I_ShutdownMusic();
 	M_SaveDefaults ();
 	I_ShutdownGraphics();
 	exits(nil);
--- a/i_video.c
+++ b/i_video.c
@@ -7,6 +7,7 @@
 
 extern byte *screens;
 int DisplayTicker = 0;
+int UpdateState = 0;
 
 #include <draw.h>
 #include <mouse.h>
@@ -61,6 +62,8 @@
 		exits(nil);
 	}
 	mousepid = pid;
+
+	I_SetPalette ((byte *)W_CacheLumpName("PLAYPAL", PU_CACHE));
 }
 
 void I_ShutdownGraphics(void)
@@ -101,6 +104,9 @@
 	uchar *s, *e, *d, *m;
 	uchar buf[SCREENWIDTH*3*12];
 
+	if(UpdateState == I_NOUPDATE)
+		return;
+
 	if(resized){
 		resized = 0;
 		if(getwindow(display, Refnone) < 0)
@@ -118,6 +124,9 @@
 		scale = 1;
 	else if(scale > 12)
 		scale = 12;
+	if (UpdateState & I_FULLSCRN){
+		UpdateState = I_NOUPDATE;
+	}
 
 	/* where to draw the scaled row */
 	r = rectsubpt(rectaddpt(Rect(0, 0, scale*SCREENWIDTH, scale), center),
@@ -200,6 +209,7 @@
 	static char nocurs[2*4+2*2*16];
 	static int fd = -1;
 
+	/*
 	if(mouseactive == on || !usemouse)
 		return;
 	if(mouseactive = on){
@@ -210,6 +220,7 @@
 		close(fd);
 		fd = -1;
 	}
+	*/
 }
 
 void I_ReadScreen(byte *scr)