patch-2.1.63 linux/drivers/sound/softoss_rs.c

Next file: linux/drivers/sound/sound_calls.h
Previous file: linux/drivers/sound/softoss.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.62/linux/drivers/sound/softoss_rs.c linux/drivers/sound/softoss_rs.c
@@ -0,0 +1,139 @@
+/*
+ * sound/softoss_rs.c
+ *
+ * Software based MIDI synthsesizer driver, the actual mixing loop.
+ * Keep the loop as simple as possible to make it easier to rewrite this 
+ * routine in assembly.
+ */
+/*
+ * Copyright (C) by Hannu Savolainen 1993-1997
+ *
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
+ */
+#include <linux/config.h>
+
+
+#include "sound_config.h"
+
+#ifdef CONFIG_SOFTOSS
+#include "softoss.h"
+
+void
+softsynth_resample_loop (short *buf, int loops)
+{
+  int             iloop, voice;
+  volatile voice_info *v;
+
+#ifdef OSS_BIG_ENDIAN
+  unsigned char  *cbuf = (unsigned char *) buf;
+
+#endif
+
+  for (iloop = 0; iloop < loops; iloop++)
+    {				/* Mix one sample */
+
+      int             accum, left = 0, right = 0;
+      int             ix, position;
+
+      for (voice = 0; voice < devc->maxvoice; voice++)
+	if (voice_active[voice])
+	  {			/* Compute voice */
+
+	    v = &softoss_voices[voice];
+#ifdef SOFTOSS_TEST
+	    ix = iloop << 3;
+	    position = v->ptr;
+#else
+	    ix = (position = v->ptr) >> 9;
+#endif
+	    /* Interpolation (resolution of 512 steps) */
+	    {
+	      int             fract = v->ptr & 0x1f;	/* 9 bits */
+
+	      /* This method works with less arithmetic operations */
+	      register int    v1 = v->wave[ix];
+
+	      accum = v1 + ((((v->wave[ix + 1] - v1)) * (fract)) >> 9);
+	    }
+
+	    left += (accum * v->leftvol);
+	    right += (accum * v->rightvol);
+
+	    /* Update sample pointer */
+
+	    position += v->step;
+	    if (position <= v->endloop)
+	      v->ptr = position;
+	    else if (v->mode & WAVE_LOOPING)
+	      {
+		if (v->mode & WAVE_BIDIR_LOOP)
+		  {
+		    v->mode ^= WAVE_LOOP_BACK;	/* Turn around */
+		    v->step *= -1;
+		  }
+		else
+		  {
+		    position -= v->looplen;
+		    v->ptr = position;
+		  }
+	      }
+	    /*  else leave the voice looping the current sample */
+
+	    if (v->mode & WAVE_LOOP_BACK && position < v->startloop)
+	      {
+		if (v->mode & WAVE_BIDIR_LOOP)
+		  {
+		    v->mode ^= WAVE_LOOP_BACK;	/* Turn around */
+		    v->step *= -1;
+		  }
+		else
+		  {
+		    position += v->looplen;
+		    v->ptr = position;
+		  }
+	      }
+
+	  }			/* Compute voice */
+
+#if 1				/* Delay */
+      left += left_delay[delayp];
+      right += right_delay[delayp];
+
+      left_delay[delayp] = right >> 2;
+      right_delay[delayp] = left >> 2;
+      delayp = (delayp + 1) % devc->delay_size;
+#endif
+
+#define AFTERSCALE devc->afterscale;
+
+      left >>= AFTERSCALE;
+      right >>= AFTERSCALE;
+
+      if (left > 32767)
+	left = 32767;
+      if (left < -32768)
+	left = -32768;
+      if (right > 32767)
+	right = 32767;
+      if (right < -32768)
+	right = -32768;
+
+#ifdef OSS_BIG_ENDIAN
+      *cbuf++ = left & 0xff;
+      *cbuf++ = (left >> 8) & 0xff;
+      *cbuf++ = right & 0xff;
+      *cbuf++ = (right >> 8) & 0xff;
+#else
+      *buf++ = left;
+      *buf++ = right;
+#endif
+      if (devc->control_counter++ >= devc->control_rate)
+	{
+	  devc->control_counter = 0;
+	  softsyn_control_loop ();
+	}
+    }				/* Mix one sample */
+}
+#endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov