Import 2.3.18pre1
[davej-history.git] / drivers / sound / softoss_rs.c
blob2fa95f748b355d9df16aaaa24a527ea9e08e16ad
2 /*
3 * sound/softoss_rs.c
5 * Software based MIDI synthsesizer driver, the actual mixing loop.
6 * Keep the loop as simple as possible to make it easier to rewrite this
7 * routine in assembly.
10 * Copyright (C) by Hannu Savolainen 1993-1997
12 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
13 * Version 2 (June 1991). See the "COPYING" file distributed with this software
14 * for more info.
16 #include <linux/config.h>
19 #include "sound_config.h"
21 #ifdef CONFIG_SOFTOSS
22 #include "softoss.h"
24 void softsynth_resample_loop(short *buf, int loops)
26 int iloop, voice;
27 volatile voice_info *v;
29 #ifdef OSS_BIG_ENDIAN
30 unsigned char *cbuf = (unsigned char *) buf;
32 #endif
34 for (iloop = 0; iloop < loops; iloop++)
35 { /* Mix one sample */
36 int accum, left = 0, right = 0;
37 int ix, position;
39 for (voice = 0; voice < devc->maxvoice; voice++)
41 if (voice_active[voice])
42 { /* Compute voice */
43 v = &softoss_voices[voice];
44 #ifdef SOFTOSS_TEST
45 ix = iloop << 3;
46 position = v->ptr;
47 #else
48 ix = (position = v->ptr) >> 9;
49 #endif
50 /* Interpolation (resolution of 512 steps) */
52 int fract = v->ptr & 0x1ff; /* 9 bits */
54 /* This method works with less arithmetic operations */
55 register int v1 = v->wave[ix];
56 accum = v1 + ((((v->wave[ix + 1] - v1)) * (fract)) >> 9);
59 left += (accum * v->leftvol);
60 right += (accum * v->rightvol);
62 /* Update sample pointer */
63 position += v->step;
64 if (position <= v->endloop)
65 v->ptr = position;
66 else if (v->mode & WAVE_LOOPING)
68 if (v->mode & WAVE_BIDIR_LOOP)
69 { v->mode ^= WAVE_LOOP_BACK; /* Turn around */
70 v->step *= -1;
72 else
74 position -= v->looplen;
75 v->ptr = position;
78 /* else leave the voice looping the current sample */
80 if (v->mode & WAVE_LOOP_BACK && position < v->startloop)
82 if (v->mode & WAVE_BIDIR_LOOP)
83 { v->mode ^= WAVE_LOOP_BACK; /* Turn around */
84 v->step *= -1;
86 else
88 position += v->looplen;
89 v->ptr = position;
92 } /* Compute voice */
94 #if 1 /* Delay */
95 left += left_delay[delayp];
96 right += right_delay[delayp];
98 left_delay[delayp] = right >> 2;
99 right_delay[delayp] = left >> 2;
100 delayp = (delayp + 1) % devc->delay_size;
101 #endif
103 #define AFTERSCALE devc->afterscale;
105 left >>= AFTERSCALE;
106 right >>= AFTERSCALE;
108 if (left > 32767)
109 left = 32767;
110 if (left < -32768)
111 left = -32768;
112 if (right > 32767)
113 right = 32767;
114 if (right < -32768)
115 right = -32768;
117 #ifdef OSS_BIG_ENDIAN
118 *cbuf++ = left & 0xff;
119 *cbuf++ = (left >> 8) & 0xff;
120 *cbuf++ = right & 0xff;
121 *cbuf++ = (right >> 8) & 0xff;
122 #else
123 *buf++ = left;
124 *buf++ = right;
125 #endif
126 if (devc->control_counter++ >= devc->control_rate)
128 devc->control_counter = 0;
129 softsyn_control_loop();
131 } /* Mix one sample */
133 #endif