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
- Lines: 140
- Date:
Tue Sep 30 08:46:55 1997
- Orig file:
v2.1.62/linux/drivers/sound/softoss_rs.c
- Orig date:
Wed Dec 31 16:00:00 1969
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