patch-2.1.67 linux/drivers/sound/softoss.c

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

diff -u --recursive --new-file v2.1.66/linux/drivers/sound/softoss.c linux/drivers/sound/softoss.c
@@ -11,7 +11,7 @@
  * for more info.
  */
 #include <linux/config.h>
-
+#include <linux/module.h>
 
 /*
  * When POLLED_MODE is defined, the resampling loop is run using a timer
@@ -26,10 +26,11 @@
 #define NO_SAMPLE		0xffff
 
 #include "sound_config.h"
+#include "soundmodule.h"
 
-#ifdef CONFIG_SOFTOSS
+#if defined(CONFIG_SOFTOSS) || defined(MODULE)
 #include "softoss.h"
-#include <sys/ultrasound.h>
+#include <linux/ultrasound.h>
 
 int             softsynth_disabled = 0;
 
@@ -49,42 +50,42 @@
  */
 static int      tremolo_table[128] =
 {
-  0, 39, 158, 355, 630, 982, 1411, 1915,
-  2494, 3146, 3869, 4662, 5522, 6448, 7438, 8489,
-  9598, 10762, 11980, 13248, 14563, 15922, 17321, 18758,
-  20228, 21729, 23256, 24806, 26375, 27960, 29556, 31160,
-  32768, 34376, 35980, 37576, 39161, 40730, 42280, 43807,
-  45308, 46778, 48215, 49614, 50973, 52288, 53556, 54774,
-  55938, 57047, 58098, 59088, 60014, 60874, 61667, 62390,
-  63042, 63621, 64125, 64554, 64906, 65181, 65378, 65497,
-  65536, 65497, 65378, 65181, 64906, 64554, 64125, 63621,
-  63042, 62390, 61667, 60874, 60014, 59087, 58098, 57047,
-  55938, 54774, 53556, 52288, 50973, 49614, 48215, 46778,
-  45308, 43807, 42280, 40730, 39161, 37576, 35980, 34376,
-  32768, 31160, 29556, 27960, 26375, 24806, 23256, 21729,
-  20228, 18758, 17321, 15922, 14563, 13248, 11980, 10762,
-  9598, 8489, 7438, 6448, 5522, 4662, 3869, 3146,
-  2494, 1915, 1411, 982, 630, 355, 158, 39
+	0, 39, 158, 355, 630, 982, 1411, 1915,
+	2494, 3146, 3869, 4662, 5522, 6448, 7438, 8489,
+	9598, 10762, 11980, 13248, 14563, 15922, 17321, 18758,
+	20228, 21729, 23256, 24806, 26375, 27960, 29556, 31160,
+	32768, 34376, 35980, 37576, 39161, 40730, 42280, 43807,
+	45308, 46778, 48215, 49614, 50973, 52288, 53556, 54774,
+	55938, 57047, 58098, 59088, 60014, 60874, 61667, 62390,
+	63042, 63621, 64125, 64554, 64906, 65181, 65378, 65497,
+	65536, 65497, 65378, 65181, 64906, 64554, 64125, 63621,
+	63042, 62390, 61667, 60874, 60014, 59087, 58098, 57047,
+	55938, 54774, 53556, 52288, 50973, 49614, 48215, 46778,
+	45308, 43807, 42280, 40730, 39161, 37576, 35980, 34376,
+	32768, 31160, 29556, 27960, 26375, 24806, 23256, 21729,
+	20228, 18758, 17321, 15922, 14563, 13248, 11980, 10762,
+	9598, 8489, 7438, 6448, 5522, 4662, 3869, 3146,
+	2494, 1915, 1411, 982, 630, 355, 158, 39
 };
 
 static int      vibrato_table[128] =
 {
-  0, 1608, 3212, 4808, 6393, 7962, 9512, 11039,
-  12540, 14010, 15447, 16846, 18205, 19520, 20788, 22006,
-  23170, 24279, 25330, 26320, 27246, 28106, 28899, 29622,
-  30274, 30853, 31357, 31786, 32138, 32413, 32610, 32729,
-  32768, 32729, 32610, 32413, 32138, 31786, 31357, 30853,
-  30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279,
-  23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010,
-  12540, 11039, 9512, 7962, 6393, 4808, 3212, 1608,
-  0, -1608, -3212, -4808, -6393, -7962, -9512, -11039,
-  -12540, -14010, -15447, -16846, -18205, -19520, -20788, -22006,
-  -23170, -24279, -25330, -26320, -27246, -28106, -28899, -29622,
-  -30274, -30853, -31357, -31786, -32138, -32413, -32610, -32729,
-  -32768, -32729, -32610, -32413, -32138, -31786, -31357, -30853,
-  -30274, -29622, -28899, -28106, -27246, -26320, -25330, -24279,
-  -23170, -22006, -20788, -19520, -18205, -16846, -15447, -14010,
-  -12540, -11039, -9512, -7962, -6393, -4808, -3212, -1608
+	0, 1608, 3212, 4808, 6393, 7962, 9512, 11039,
+	12540, 14010, 15447, 16846, 18205, 19520, 20788, 22006,
+	23170, 24279, 25330, 26320, 27246, 28106, 28899, 29622,
+	30274, 30853, 31357, 31786, 32138, 32413, 32610, 32729,
+	32768, 32729, 32610, 32413, 32138, 31786, 31357, 30853,
+	30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279,
+	23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010,
+	12540, 11039, 9512, 7962, 6393, 4808, 3212, 1608,
+	0, -1608, -3212, -4808, -6393, -7962, -9512, -11039,
+	-12540, -14010, -15447, -16846, -18205, -19520, -20788, -22006,
+	-23170, -24279, -25330, -26320, -27246, -28106, -28899, -29622,
+	-30274, -30853, -31357, -31786, -32138, -32413, -32610, -32729,
+	-32768, -32729, -32610, -32413, -32138, -31786, -31357, -30853,
+	-30274, -29622, -28899, -28106, -27246, -26320, -25330, -24279,
+	-23170, -22006, -20788, -19520, -18205, -16846, -15447, -14010,
+	-12540, -11039, -9512, -7962, -6393, -4808, -3212, -1608
 };
 
 #endif
@@ -106,1386 +107,1347 @@
 
 static struct voice_alloc_info *voice_alloc;
 
-static int      softsyn_open (int synthdev, int mode);
-static void     init_voice (softsyn_devc * devc, int voice);
-static void     compute_step (int voice);
+static int      softsyn_open(int synthdev, int mode);
+static void     init_voice(softsyn_devc * devc, int voice);
+static void     compute_step(int voice);
 
 static volatile int tmr_running = 0;
 static int      voice_limit = 24;
 
 static void
-set_max_voices (int nr)
+set_max_voices(int nr)
 {
-  int             i;
+	int             i;
 
-  if (nr < 4)
-    nr = 4;
+	if (nr < 4)
+		nr = 4;
 
-  if (nr > voice_limit)
-    nr = voice_limit;
+	if (nr > voice_limit)
+		nr = voice_limit;
 
-  voice_alloc->max_voice = devc->maxvoice = nr;
-  devc->afterscale = 5;
+	voice_alloc->max_voice = devc->maxvoice = nr;
+	devc->afterscale = 5;
 
-  for (i = 31; i > 0; i--)
-    if (nr & (1 << i))
-      {
-	devc->afterscale = i + 1;
-	return;
-      }
+	for (i = 31; i > 0; i--)
+		if (nr & (1 << i))
+		  {
+			  devc->afterscale = i + 1;
+			  return;
+		  }
 }
 
 static void
-update_vibrato (int voice)
+update_vibrato(int voice)
 {
-  voice_info     *v = &softoss_voices[voice];
+	voice_info     *v = &softoss_voices[voice];
 
 #ifdef HANDLE_LFO
-  int             x;
+	int             x;
 
-  x = vibrato_table[v->vibrato_phase >> 8];
-  v->vibrato_phase = (v->vibrato_phase + v->vibrato_step) & 0x7fff;
+	x = vibrato_table[v->vibrato_phase >> 8];
+	v->vibrato_phase = (v->vibrato_phase + v->vibrato_step) & 0x7fff;
 
-  x = (x * v->vibrato_depth) >> 15;
-  v->vibrato_level = (x * 600) >> 8;
+	x = (x * v->vibrato_depth) >> 15;
+	v->vibrato_level = (x * 600) >> 8;
 
-  compute_step (voice);
+	compute_step(voice);
 #else
-  v->vibrato_level = 0;
+	v->vibrato_level = 0;
 #endif
 }
 
 #ifdef HANDLE_LFO
 static void
-update_tremolo (int voice)
+update_tremolo(int voice)
 {
-  voice_info     *v = &softoss_voices[voice];
-  int             x;
+	voice_info     *v = &softoss_voices[voice];
+	int             x;
 
-  x = tremolo_table[v->tremolo_phase >> 8];
-  v->tremolo_phase = (v->tremolo_phase + v->tremolo_step) & 0x7fff;
+	x = tremolo_table[v->tremolo_phase >> 8];
+	v->tremolo_phase = (v->tremolo_phase + v->tremolo_step) & 0x7fff;
 
-  v->tremolo_level = (x * v->tremolo_depth) >> 20;
+	v->tremolo_level = (x * v->tremolo_depth) >> 20;
 }
 #endif
 
 static void
-start_vibrato (int voice)
+start_vibrato(int voice)
 {
-  voice_info     *v = &softoss_voices[voice];
-  int             rate;
+	voice_info     *v = &softoss_voices[voice];
+	int             rate;
 
-  if (!v->vibrato_depth)
-    return;
+	if (!v->vibrato_depth)
+		return;
 
-  rate = v->vibrato_rate * 6 * 128;
-  v->vibrato_step = (rate * devc->control_rate) / devc->speed;
+	rate = v->vibrato_rate * 6 * 128;
+	v->vibrato_step = (rate * devc->control_rate) / devc->speed;
 
-  devc->vibratomap |= (1 << voice);	/* Enable vibrato */
+	devc->vibratomap |= (1 << voice);	/* Enable vibrato */
 }
 
 static void
-start_tremolo (int voice)
+start_tremolo(int voice)
 {
-  voice_info     *v = &softoss_voices[voice];
-  int             rate;
+	voice_info     *v = &softoss_voices[voice];
+	int             rate;
 
-  if (!v->tremolo_depth)
-    return;
+	if (!v->tremolo_depth)
+		return;
 
-  rate = v->tremolo_rate * 6 * 128;
-  v->tremolo_step = (rate * devc->control_rate) / devc->speed;
+	rate = v->tremolo_rate * 6 * 128;
+	v->tremolo_step = (rate * devc->control_rate) / devc->speed;
 
-  devc->tremolomap |= (1 << voice);	/* Enable tremolo */
+	devc->tremolomap |= (1 << voice);	/* Enable tremolo */
 }
 
 static void
-update_volume (int voice)
+update_volume(int voice)
 {
-  voice_info     *v = &softoss_voices[voice];
-  unsigned int    vol;
+	voice_info     *v = &softoss_voices[voice];
+	unsigned int    vol;
 
 /*
  * Compute plain volume
  */
 
-  vol = (v->velocity * v->expression_vol * v->main_vol) >> 12;
+	vol = (v->velocity * v->expression_vol * v->main_vol) >> 12;
 
 #ifdef HANDLE_LFO
 /*
  * Handle LFO
  */
 
-  if (devc->tremolomap & (1 << voice))
-    {
-      int             t;
-
-      t = 32768 - v->tremolo_level;
-      vol = (vol * t) >> 15;
-      update_tremolo (voice);
-    }
+	if (devc->tremolomap & (1 << voice))
+	  {
+		  int             t;
+
+		  t = 32768 - v->tremolo_level;
+		  vol = (vol * t) >> 15;
+		  update_tremolo(voice);
+	  }
 #endif
 /*
  * Envelope
  */
-  if (v->mode & WAVE_ENVELOPES && !v->percussive_voice)
-    vol = (vol * (v->envelope_vol >> 16)) >> 19;
-  else
-    vol >>= 4;
+	if (v->mode & WAVE_ENVELOPES && !v->percussive_voice)
+		vol = (vol * (v->envelope_vol >> 16)) >> 19;
+	else
+		vol >>= 4;
 
 /*
  * Handle panning
  */
 
-  if (v->panning < 0)		/* Pan left */
-    v->rightvol = (vol * (128 + v->panning)) / 128;
-  else
-    v->rightvol = vol;
-
-  if (v->panning > 0)		/* Pan right */
-    v->leftvol = (vol * (128 - v->panning)) / 128;
-  else
-    v->leftvol = vol;
-}
-
-static void
-step_envelope (int voice, int do_release, int velocity)
-{
-  voice_info     *v = &softoss_voices[voice];
-  int             r, rate, time, dif;
-  unsigned int    vol;
-  unsigned long   flags;
-
-  save_flags (flags);
-  cli ();
-
-  if (!voice_active[voice] || v->sample == NULL)
-    {
-      restore_flags (flags);
-      return;
-    }
-
-  if (!do_release)
-    if (v->mode & WAVE_SUSTAIN_ON && v->envelope_phase == 2)
-      {				/* Stop envelope until note off */
-	v->envelope_volstep = 0;
-	v->envelope_time = 0x7fffffff;
-	if (v->mode & WAVE_VIBRATO)
-	  start_vibrato (voice);
-	if (v->mode & WAVE_TREMOLO)
-	  start_tremolo (voice);
-	restore_flags (flags);
-	return;
-      }
-
-  if (do_release)
-    v->envelope_phase = 3;
-  else
-    v->envelope_phase++;
-
-  if (v->envelope_phase >= 5)	/* Finished */
-    {
-      init_voice (devc, voice);
-      restore_flags (flags);
-      return;
-    }
-
-  vol = v->envelope_target = v->sample->env_offset[v->envelope_phase] << 22;
-
-
-  rate = v->sample->env_rate[v->envelope_phase];
-  r = 3 - ((rate >> 6) & 0x3);
-  r *= 3;
-  r = (int) (rate & 0x3f) << r;
-  rate = (((r * 44100) / devc->speed) * devc->control_rate) << 8;
-
-  if (rate < (1 << 20))		/* Avoid infinitely "releasing" voices */
-    rate = 1 << 20;
-
-  dif = (v->envelope_vol - vol);
-  if (dif < 0)
-    dif *= -1;
-  if (dif < rate * 2)		/* Too close */
-    {
-      step_envelope (voice, 0, 60);
-      restore_flags (flags);
-      return;
-    }
-
-  if (vol > v->envelope_vol)
-    {
-      v->envelope_volstep = rate;
-      time = (vol - v->envelope_vol) / rate;
-    }
-  else
-    {
-      v->envelope_volstep = -rate;
-      time = (v->envelope_vol - vol) / rate;
-    }
-
-  time--;
-  if (time <= 0)
-    time = 1;
-
-  v->envelope_time = time;
+	if (v->panning < 0)	/* Pan left */
+		v->rightvol = (vol * (128 + v->panning)) / 128;
+	else
+		v->rightvol = vol;
+
+	if (v->panning > 0)	/* Pan right */
+		v->leftvol = (vol * (128 - v->panning)) / 128;
+	else
+		v->leftvol = vol;
+}
+
+static void
+step_envelope(int voice, int do_release, int velocity)
+{
+	voice_info     *v = &softoss_voices[voice];
+	int             r, rate, time, dif;
+	unsigned int    vol;
+	unsigned long   flags;
+
+	save_flags(flags);
+	cli();
+
+	if (!voice_active[voice] || v->sample == NULL)
+	  {
+		  restore_flags(flags);
+		  return;
+	  }
+	if (!do_release)
+		if (v->mode & WAVE_SUSTAIN_ON && v->envelope_phase == 2)
+		  {		/* Stop envelope until note off */
+			  v->envelope_volstep = 0;
+			  v->envelope_time = 0x7fffffff;
+			  if (v->mode & WAVE_VIBRATO)
+				  start_vibrato(voice);
+			  if (v->mode & WAVE_TREMOLO)
+				  start_tremolo(voice);
+			  restore_flags(flags);
+			  return;
+		  }
+	if (do_release)
+		v->envelope_phase = 3;
+	else
+		v->envelope_phase++;
+
+	if (v->envelope_phase >= 5)	/* Finished */
+	  {
+		  init_voice(devc, voice);
+		  restore_flags(flags);
+		  return;
+	  }
+	vol = v->envelope_target = v->sample->env_offset[v->envelope_phase] << 22;
+
+
+	rate = v->sample->env_rate[v->envelope_phase];
+	r = 3 - ((rate >> 6) & 0x3);
+	r *= 3;
+	r = (int) (rate & 0x3f) << r;
+	rate = (((r * 44100) / devc->speed) * devc->control_rate) << 8;
+
+	if (rate < (1 << 20))	/* Avoid infinitely "releasing" voices */
+		rate = 1 << 20;
+
+	dif = (v->envelope_vol - vol);
+	if (dif < 0)
+		dif *= -1;
+	if (dif < rate * 2)	/* Too close */
+	  {
+		  step_envelope(voice, 0, 60);
+		  restore_flags(flags);
+		  return;
+	  }
+	if (vol > v->envelope_vol)
+	  {
+		  v->envelope_volstep = rate;
+		  time = (vol - v->envelope_vol) / rate;
+	} else
+	  {
+		  v->envelope_volstep = -rate;
+		  time = (v->envelope_vol - vol) / rate;
+	  }
+
+	time--;
+	if (time <= 0)
+		time = 1;
+
+	v->envelope_time = time;
 
 
-  restore_flags (flags);
+	restore_flags(flags);
 }
 
 static void
-step_envelope_lfo (int voice)
+step_envelope_lfo(int voice)
 {
-  voice_info     *v = &softoss_voices[voice];
+	voice_info     *v = &softoss_voices[voice];
 
 /*
  * Update pitch (vibrato) LFO 
  */
 
-  if (devc->vibratomap & (1 << voice))
-    update_vibrato (voice);
+	if (devc->vibratomap & (1 << voice))
+		update_vibrato(voice);
 
 /* 
  * Update envelope
  */
 
-  if (v->mode & WAVE_ENVELOPES)
-    {
-      v->envelope_vol += v->envelope_volstep;
-      /* Overshoot protection */
-      if (v->envelope_vol < 0)
-	{
-	  v->envelope_vol = v->envelope_target;
-	  v->envelope_volstep = 0;
-	}
-
-      if (v->envelope_time-- <= 0)
-	{
-	  v->envelope_vol = v->envelope_target;
-	  step_envelope (voice, 0, 60);
-	}
-    }
-}
-
-static void
-compute_step (int voice)
-{
-  voice_info     *v = &softoss_voices[voice];
-
-  /*
-   * Since the pitch bender may have been set before playing the note, we
-   * have to calculate the bending now.
-   */
-
-  v->current_freq = compute_finetune (v->orig_freq,
-				      v->bender,
-				      v->bender_range,
-				      v->vibrato_level);
-  v->step = (((v->current_freq << 9) + (devc->speed >> 1)) / devc->speed);
-
-  if (v->mode & WAVE_LOOP_BACK)
-    v->step *= -1;		/* Reversed playback */
-}
-
-static void
-init_voice (softsyn_devc * devc, int voice)
-{
-  voice_info     *v = &softoss_voices[voice];
-  unsigned long   flags;
-
-  save_flags (flags);
-  cli ();
-  voice_active[voice] = 0;
-  devc->vibratomap &= ~(1 << voice);
-  devc->tremolomap &= ~(1 << voice);
-  v->mode = 0;
-  v->wave = NULL;
-  v->sample = NULL;
-  v->ptr = 0;
-  v->step = 0;
-  v->startloop = 0;
-  v->startbackloop = 0;
-  v->endloop = 0;
-  v->looplen = 0;
-  v->bender = 0;
-  v->bender_range = 200;
-  v->panning = 0;
-  v->main_vol = 127;
-  v->expression_vol = 127;
-  v->patch_vol = 127;
-  v->percussive_voice = 0;
-  v->sustain_mode = 0;
-  v->envelope_phase = 1;
-  v->envelope_vol = 1 << 24;
-  v->envelope_volstep = 256;
-  v->envelope_time = 0;
-  v->vibrato_phase = 0;
-  v->vibrato_step = 0;
-  v->vibrato_level = 0;
-  v->vibrato_rate = 0;
-  v->vibrato_depth = 0;
-  v->tremolo_phase = 0;
-  v->tremolo_step = 0;
-  v->tremolo_level = 0;
-  v->tremolo_rate = 0;
-  v->tremolo_depth = 0;
-  voice_alloc->map[voice] = 0;
-  voice_alloc->alloc_times[voice] = 0;
-  restore_flags (flags);
-}
-
-static void
-reset_samples (softsyn_devc * devc)
-{
-  int             i;
-
-  for (i = 0; i < MAX_VOICE; i++)
-    voice_active[i] = 0;
-  for (i = 0; i < devc->maxvoice; i++)
-    {
-      init_voice (devc, i);
-      softoss_voices[i].instr = 0;
-    }
-
-  devc->ram_used = 0;
-
-  for (i = 0; i < MAX_PATCH; i++)
-    devc->programs[i] = NO_SAMPLE;
-
-  for (i = 0; i < devc->nrsamples; i++)
-    {
-      vfree (devc->samples[i]);
-      vfree (devc->wave[i]);
-      devc->samples[i] = NULL;
-      devc->wave[i] = NULL;
-    }
-
-  devc->nrsamples = 0;
-}
-
-static void
-init_engine (softsyn_devc * devc)
-{
-  int             i, fz, srate, sz = devc->channels;
-
-  set_max_voices (devc->default_max_voices);
-  voice_alloc->timestamp = 0;
-
-  if (devc->bits == 16)
-    sz *= 2;
-
-  fz = devc->fragsize / sz;	/* Samples per fragment */
-  devc->samples_per_fragment = fz;
-
-  devc->usecs = 0;
-  devc->usecs_per_frag = (1000000 * fz) / devc->speed;
-
-  for (i = 0; i < devc->maxvoice; i++)
-    {
-      init_voice (devc, i);
-      softoss_voices[i].instr = 0;
-    }
+	if (v->mode & WAVE_ENVELOPES)
+	  {
+		  v->envelope_vol += v->envelope_volstep;
+		  /* Overshoot protection */
+		  if (v->envelope_vol < 0)
+		    {
+			    v->envelope_vol = v->envelope_target;
+			    v->envelope_volstep = 0;
+		    }
+		  if (v->envelope_time-- <= 0)
+		    {
+			    v->envelope_vol = v->envelope_target;
+			    step_envelope(voice, 0, 60);
+		    }
+	  }
+}
+
+static void
+compute_step(int voice)
+{
+	voice_info     *v = &softoss_voices[voice];
+
+	/*
+	 * Since the pitch bender may have been set before playing the note, we
+	 * have to calculate the bending now.
+	 */
+
+	v->current_freq = compute_finetune(v->orig_freq,
+					   v->bender,
+					   v->bender_range,
+					   v->vibrato_level);
+	v->step = (((v->current_freq << 9) + (devc->speed >> 1)) / devc->speed);
+
+	if (v->mode & WAVE_LOOP_BACK)
+		v->step *= -1;	/* Reversed playback */
+}
+
+static void
+init_voice(softsyn_devc * devc, int voice)
+{
+	voice_info     *v = &softoss_voices[voice];
+	unsigned long   flags;
+
+	save_flags(flags);
+	cli();
+	voice_active[voice] = 0;
+	devc->vibratomap &= ~(1 << voice);
+	devc->tremolomap &= ~(1 << voice);
+	v->mode = 0;
+	v->wave = NULL;
+	v->sample = NULL;
+	v->ptr = 0;
+	v->step = 0;
+	v->startloop = 0;
+	v->startbackloop = 0;
+	v->endloop = 0;
+	v->looplen = 0;
+	v->bender = 0;
+	v->bender_range = 200;
+	v->panning = 0;
+	v->main_vol = 127;
+	v->expression_vol = 127;
+	v->patch_vol = 127;
+	v->percussive_voice = 0;
+	v->sustain_mode = 0;
+	v->envelope_phase = 1;
+	v->envelope_vol = 1 << 24;
+	v->envelope_volstep = 256;
+	v->envelope_time = 0;
+	v->vibrato_phase = 0;
+	v->vibrato_step = 0;
+	v->vibrato_level = 0;
+	v->vibrato_rate = 0;
+	v->vibrato_depth = 0;
+	v->tremolo_phase = 0;
+	v->tremolo_step = 0;
+	v->tremolo_level = 0;
+	v->tremolo_rate = 0;
+	v->tremolo_depth = 0;
+	voice_alloc->map[voice] = 0;
+	voice_alloc->alloc_times[voice] = 0;
+	restore_flags(flags);
+}
+
+static void
+reset_samples(softsyn_devc * devc)
+{
+	int             i;
+
+	for (i = 0; i < MAX_VOICE; i++)
+		voice_active[i] = 0;
+	for (i = 0; i < devc->maxvoice; i++)
+	  {
+		  init_voice(devc, i);
+		  softoss_voices[i].instr = 0;
+	  }
+
+	devc->ram_used = 0;
+
+	for (i = 0; i < MAX_PATCH; i++)
+		devc->programs[i] = NO_SAMPLE;
+
+	for (i = 0; i < devc->nrsamples; i++)
+	  {
+		  vfree(devc->samples[i]);
+		  vfree(devc->wave[i]);
+		  devc->samples[i] = NULL;
+		  devc->wave[i] = NULL;
+	  }
+
+	devc->nrsamples = 0;
+}
+
+static void
+init_engine(softsyn_devc * devc)
+{
+	int             i, fz, srate, sz = devc->channels;
+
+	set_max_voices(devc->default_max_voices);
+	voice_alloc->timestamp = 0;
+
+	if (devc->bits == 16)
+		sz *= 2;
+
+	fz = devc->fragsize / sz;	/* Samples per fragment */
+	devc->samples_per_fragment = fz;
+
+	devc->usecs = 0;
+	devc->usecs_per_frag = (1000000 * fz) / devc->speed;
+
+	for (i = 0; i < devc->maxvoice; i++)
+	  {
+		  init_voice(devc, i);
+		  softoss_voices[i].instr = 0;
+	  }
 
-  devc->engine_state = ES_STOPPED;
+	devc->engine_state = ES_STOPPED;
 
 /*
  *    Initialize delay
  */
 
-  for (i = 0; i < DELAY_SIZE; i++)
-    left_delay[i] = right_delay[i] = 0;
-  delayp = 0;
-  srate = (devc->speed / 10000);	/* 1 to 4 */
-  if (srate <= 0)
-    srate = 1;
-  devc->delay_size = (DELAY_SIZE * srate) / 4;
-  if (devc->delay_size == 0 || devc->delay_size > DELAY_SIZE)
-    devc->delay_size = DELAY_SIZE;
+	for (i = 0; i < DELAY_SIZE; i++)
+		left_delay[i] = right_delay[i] = 0;
+	delayp = 0;
+	srate = (devc->speed / 10000);	/* 1 to 4 */
+	if (srate <= 0)
+		srate = 1;
+	devc->delay_size = (DELAY_SIZE * srate) / 4;
+	if (devc->delay_size == 0 || devc->delay_size > DELAY_SIZE)
+		devc->delay_size = DELAY_SIZE;
 }
 
 void
-softsyn_control_loop (void)
+softsyn_control_loop(void)
 {
-  int             voice;
+	int             voice;
 
 /*
  *    Recompute envlope, LFO, etc.
  */
-  for (voice = 0; voice < devc->maxvoice; voice++)
-    if (voice_active[voice])
-      {
-	update_volume (voice);
-	step_envelope_lfo (voice);
-      }
-    else
-      voice_alloc->map[voice] = 0;
-}
-
-static void     start_engine (softsyn_devc * devc);
-
-static void
-do_resample (int dummy)
-{
-  struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out;
-  struct voice_info *vinfo;
-  unsigned long   flags, jif;
-
-  int             voice, loops;
-  short          *buf;
-
-  if (softsynth_disabled)
-    return;
-
-  save_flags (flags);
-  cli ();
-
-  if (is_running)
-    {
-      printk ("SoftOSS: Playback overrun\n");
-      restore_flags (flags);
-      return;
-    }
-
-  jif = jiffies;
-  if (jif == last_resample_jiffies)
-    {
-      if (resample_counter++ > 50)
-	{
-	  for (voice = 0; voice < devc->maxvoice; voice++)
-	    init_voice (devc, voice);
-	  voice_limit--;
-	  resample_counter = 0;
-	  printk ("SoftOSS: CPU overload. Limiting # of voices to %d\n", voice_limit);
-
-	  if (voice_limit < 10)
-	    {
-	      voice_limit = 10;
-	      devc->speed = (devc->speed * 2) / 3;
-
-	      printk ("SoftOSS: Dropping sampling rate and stopping the device.\n");
-	      softsynth_disabled = 1;
-	    }
-	}
-    }
-  else
-    {
-      last_resample_jiffies = jif;
-      resample_counter = 0;
-    }
-
-  /* is_running = 1; */
-
-  if (dmap->qlen > devc->max_playahead)
-    {
-      printk ("SoftOSS: audio buffers full\n");
-      is_running = 0;
-      restore_flags (flags);
-      return;
-    }
-
+	for (voice = 0; voice < devc->maxvoice; voice++)
+		if (voice_active[voice])
+		  {
+			  update_volume(voice);
+			  step_envelope_lfo(voice);
+		} else
+			voice_alloc->map[voice] = 0;
+}
+
+static void     start_engine(softsyn_devc * devc);
+
+static void
+do_resample(int dummy)
+{
+	struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out;
+	struct voice_info *vinfo;
+	unsigned long   flags, jif;
+
+	int             voice, loops;
+	short          *buf;
+
+	if (softsynth_disabled)
+		return;
+
+	save_flags(flags);
+	cli();
+
+	if (is_running)
+	  {
+		  printk("SoftOSS: Playback overrun\n");
+		  restore_flags(flags);
+		  return;
+	  }
+	jif = jiffies;
+	if (jif == last_resample_jiffies)
+	  {
+		  if (resample_counter++ > 50)
+		    {
+			    for (voice = 0; voice < devc->maxvoice; voice++)
+				    init_voice(devc, voice);
+			    voice_limit--;
+			    resample_counter = 0;
+			    printk("SoftOSS: CPU overload. Limiting # of voices to %d\n", voice_limit);
+
+			    if (voice_limit < 10)
+			      {
+				      voice_limit = 10;
+				      devc->speed = (devc->speed * 2) / 3;
+
+				      printk("SoftOSS: Dropping sampling rate and stopping the device.\n");
+				      softsynth_disabled = 1;
+			      }
+		    }
+	} else
+	  {
+		  last_resample_jiffies = jif;
+		  resample_counter = 0;
+	  }
+
+	/* is_running = 1; */
+
+	if (dmap->qlen > devc->max_playahead)
+	  {
+		  printk("SoftOSS: audio buffers full\n");
+		  is_running = 0;
+		  restore_flags(flags);
+		  return;
+	  }
 /*
  * First verify that all active voices are valid (do this just once per block).
  */
-  for (voice = 0; voice < devc->maxvoice; voice++)
-    if (voice_active[voice])
-      {
-	int             ptr;
-
-	vinfo = &softoss_voices[voice];
-	ptr = vinfo->ptr >> 9;
-
-	if (vinfo->wave == NULL ||
-	    ptr < 0 ||
-	    ptr > vinfo->sample->len)
-	  init_voice (devc, voice);
-	else if (!(vinfo->mode & WAVE_LOOPING) &&
-		 (vinfo->ptr + vinfo->step) > vinfo->endloop)
-	  voice_active[voice] = 0;
-      }
-
+	for (voice = 0; voice < devc->maxvoice; voice++)
+		if (voice_active[voice])
+		  {
+			  int             ptr;
+
+			  vinfo = &softoss_voices[voice];
+			  ptr = vinfo->ptr >> 9;
+
+			  if (vinfo->wave == NULL ||
+			      ptr < 0 ||
+			      ptr > vinfo->sample->len)
+				  init_voice(devc, voice);
+			  else if (!(vinfo->mode & WAVE_LOOPING) &&
+			     (vinfo->ptr + vinfo->step) > vinfo->endloop)
+				  voice_active[voice] = 0;
+		  }
 /*
  *    Start the resampling process
  */
 
-  loops = devc->samples_per_fragment;
-  buf = (short *) (dmap->raw_buf + (dmap->qtail * dmap->fragment_size));
-
-  softsynth_resample_loop (buf, loops);		/* In Xsoftsynth_rs.c */
+	loops = devc->samples_per_fragment;
+	buf = (short *) (dmap->raw_buf + (dmap->qtail * dmap->fragment_size));
 
-  dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
-  dmap->qlen++;
-  dmap->user_counter += dmap->fragment_size;
+	softsynth_resample_loop(buf, loops);	/* In Xsoftsynth_rs.c */
 
-  devc->usecs += devc->usecs_per_frag;
+	dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+	dmap->qlen++;
+	dmap->user_counter += dmap->fragment_size;
 
-  if (tmr_running)
-    {
-      sound_timer_interrupt ();
-    }
+	devc->usecs += devc->usecs_per_frag;
 
+	if (tmr_running)
+	  {
+		  sound_timer_interrupt();
+	  }
 /*
  *    Execute timer
  */
 
-  if (!tmr_running)
-    if (devc->usecs >= devc->next_event_usecs)
-      {
-	devc->next_event_usecs = ~0;
-	sequencer_timer (0);
-      }
-  is_running = 0;
-  restore_flags (flags);
+	if (!tmr_running)
+		if (devc->usecs >= devc->next_event_usecs)
+		  {
+			  devc->next_event_usecs = ~0;
+			  sequencer_timer(0);
+		  }
+	is_running = 0;
+	restore_flags(flags);
 }
 
 static void
-delayed_resample (int dummy)
+delayed_resample(int dummy)
 {
-  struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out;
-  int             n = 0;
+	struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out;
+	int             n = 0;
 
-  if (is_running)
-    return;
+	if (is_running)
+		return;
 
-  while (devc->engine_state != ES_STOPPED &&
-	 dmap->qlen < devc->max_playahead && n++ < 2)
-    do_resample (0);
-  intr_pending = 0;
+	while (devc->engine_state != ES_STOPPED &&
+	       dmap->qlen < devc->max_playahead && n++ < 2)
+		do_resample(0);
+	intr_pending = 0;
 }
 
 #ifdef POLLED_MODE
 static void
-softsyn_poll (unsigned long dummy)
+softsyn_poll(unsigned long dummy)
 {
-  delayed_resample (0);
+	delayed_resample(0);
 
-  if (devc->engine_state != ES_STOPPED)
+	if (devc->engine_state != ES_STOPPED)
 
-    {
-      poll_timer.expires = (1) + jiffies;
-      add_timer (&poll_timer);
-    };
+	  {
+		  poll_timer.expires = (1) + jiffies;
+		  add_timer(&poll_timer);
+	  };
 }
 #else
 static void
-softsyn_callback (int dev, int parm)
+softsyn_callback(int dev, int parm)
 {
-  delayed_resample (0);
+	delayed_resample(0);
 }
 #endif
 
 static void
-start_engine (softsyn_devc * devc)
+start_engine(softsyn_devc * devc)
 {
-  struct dma_buffparms *dmap;
+	struct dma_buffparms *dmap;
 
-  if (!devc->audio_opened)
-    if (softsyn_open (devc->synthdev, 0) < 0)
-      return;
+	if (!devc->audio_opened)
+		if (softsyn_open(devc->synthdev, 0) < 0)
+			return;
 
-  if (devc->audiodev >= num_audiodevs)
-    return;
+	if (devc->audiodev >= num_audiodevs)
+		return;
 
-  dmap = audio_devs[devc->audiodev]->dmap_out;
+	dmap = audio_devs[devc->audiodev]->dmap_out;
 
-  devc->usecs = 0;
-  devc->next_event_usecs = ~0;
-  devc->control_rate = 64;
-  devc->control_counter = 0;
+	devc->usecs = 0;
+	devc->next_event_usecs = ~0;
+	devc->control_rate = 64;
+	devc->control_counter = 0;
 
-  if (devc->engine_state == ES_STOPPED)
-    {
-      int             trig, n = 0;
+	if (devc->engine_state == ES_STOPPED)
+	  {
+		  int             trig, n = 0;
 
-      trig = 0;
-      dma_ioctl (devc->audiodev, SNDCTL_DSP_SETTRIGGER, (caddr_t) & trig);
+		  trig = 0;
+		  dma_ioctl(devc->audiodev, SNDCTL_DSP_SETTRIGGER, (caddr_t) & trig);
 #ifdef POLLED_MODE
-      ;
+		  ;
 
-      {
-	poll_timer.expires = (1) + jiffies;
-	add_timer (&poll_timer);
-      };			/* Start polling */
+		  {
+			  poll_timer.expires = (1) + jiffies;
+			  add_timer(&poll_timer);
+		  };		/* Start polling */
 #else
-      dmap->audio_callback = softsyn_callback;
-      dmap->qhead = dmap->qtail = dmap->qlen = 0;
+		  dmap->audio_callback = softsyn_callback;
+		  dmap->qhead = dmap->qtail = dmap->qlen = 0;
 #endif
 
-      while (dmap->qlen < devc->max_playahead && n++ < 2)
-	do_resample (0);
+		  while (dmap->qlen < devc->max_playahead && n++ < 2)
+			  do_resample(0);
 
-      devc->engine_state = ES_STARTED;
-      last_resample_jiffies = jiffies;
-      resample_counter = 0;
+		  devc->engine_state = ES_STARTED;
+		  last_resample_jiffies = jiffies;
+		  resample_counter = 0;
 
-      trig = PCM_ENABLE_OUTPUT;
-      if (dma_ioctl (devc->audiodev, SNDCTL_DSP_SETTRIGGER,
-		     (caddr_t) & trig) < 0)
-	{
-	  printk ("SoftOSS: Trigger failed\n");
-	}
-
-
-    }
+		  trig = PCM_ENABLE_OUTPUT;
+		  if (dma_ioctl(devc->audiodev, SNDCTL_DSP_SETTRIGGER,
+				(caddr_t) & trig) < 0)
+		    {
+			    printk("SoftOSS: Trigger failed\n");
+		    }
+	  }
 }
 
 static void
-stop_engine (softsyn_devc * devc)
+stop_engine(softsyn_devc * devc)
 {
 }
 
 static void
-request_engine (softsyn_devc * devc, int ticks)
+request_engine(softsyn_devc * devc, int ticks)
 {
-  if (ticks < 0)		/* Relative time */
-    devc->next_event_usecs = devc->usecs - ticks * (1000000 / HZ);
-  else
-    devc->next_event_usecs = ticks * (1000000 / HZ);
+	if (ticks < 0)		/* Relative time */
+		devc->next_event_usecs = devc->usecs - ticks * (1000000 / HZ);
+	else
+		devc->next_event_usecs = ticks * (1000000 / HZ);
 }
 
 /*
  * Softsync hook serves mode1 (timing) calls made by sequencer.c
  */
 static int
-softsynth_hook (int cmd, int parm1, int parm2, unsigned long parm3)
+softsynth_hook(int cmd, int parm1, int parm2, unsigned long parm3)
 {
-  switch (cmd)
-    {
-    case SSYN_START:
-      start_engine (devc);
-      break;
-
-    case SSYN_STOP:
-      stop_engine (devc);
-      break;
-
-    case SSYN_REQUEST:
-      request_engine (devc, parm1);
-      break;
-
-    case SSYN_GETTIME:
-      return devc->usecs / (1000000 / HZ);
-      break;
-
-    default:
-      printk ("SoftOSS: Unknown request %d\n", cmd);
-    }
+	switch (cmd)
+	  {
+	  case SSYN_START:
+		  start_engine(devc);
+		  break;
+
+	  case SSYN_STOP:
+		  stop_engine(devc);
+		  break;
+
+	  case SSYN_REQUEST:
+		  request_engine(devc, parm1);
+		  break;
+
+	  case SSYN_GETTIME:
+		  return devc->usecs / (1000000 / HZ);
+		  break;
+
+	  default:
+		  printk("SoftOSS: Unknown request %d\n", cmd);
+	  }
 
-  return 0;
+	return 0;
 }
 
 static int
-softsyn_ioctl (int dev,
-	       unsigned int cmd, caddr_t arg)
+softsyn_ioctl(int dev,
+	      unsigned int cmd, caddr_t arg)
 {
-  switch (cmd)
-    {
+	switch (cmd)
+	  {
 
-    case SNDCTL_SYNTH_INFO:
-      softsyn_info.nr_voices = devc->maxvoice;
+	  case SNDCTL_SYNTH_INFO:
+		  softsyn_info.nr_voices = devc->maxvoice;
 
-      memcpy ((&((char *) arg)[0]), (char *) &softsyn_info, sizeof (softsyn_info));
-      return 0;
-      break;
-
-    case SNDCTL_SEQ_RESETSAMPLES:
-      stop_engine (devc);
-      reset_samples (devc);
-      return 0;
-      break;
-
-    case SNDCTL_SYNTH_MEMAVL:
-      return devc->ram_size - devc->ram_used;
-      break;
-
-    default:
-      return -EINVAL;
-    }
+		  memcpy((&((char *) arg)[0]), (char *) &softsyn_info, sizeof(softsyn_info));
+		  return 0;
+		  break;
+
+	  case SNDCTL_SEQ_RESETSAMPLES:
+		  stop_engine(devc);
+		  reset_samples(devc);
+		  return 0;
+		  break;
+
+	  case SNDCTL_SYNTH_MEMAVL:
+		  return devc->ram_size - devc->ram_used;
+		  break;
+
+	  default:
+		  return -EINVAL;
+	  }
 
 }
 
 static int
-softsyn_kill_note (int devno, int voice, int note, int velocity)
+softsyn_kill_note(int devno, int voice, int note, int velocity)
 {
-  if (voice < 0 || voice > devc->maxvoice)
-    return 0;
-  voice_alloc->map[voice] = 0xffff;	/* Releasing */
-
-  if (softoss_voices[voice].sustain_mode & 1)	/* Sustain controller on */
-    {
-      softoss_voices[voice].sustain_mode = 3;	/* Note off pending */
-      return 0;
-    }
-
-  if (velocity > 127 || softoss_voices[voice].mode & WAVE_FAST_RELEASE)
-    {
-      init_voice (devc, voice);	/* Mark it inactive */
-      return 0;
-    }
-
-  if (softoss_voices[voice].mode & WAVE_ENVELOPES)
-    step_envelope (voice, 1, velocity);		/* Enter sustain phase */
-  else
-    init_voice (devc, voice);	/* Mark it inactive */
-  return 0;
+	if (voice < 0 || voice > devc->maxvoice)
+		return 0;
+	voice_alloc->map[voice] = 0xffff;	/* Releasing */
+
+	if (softoss_voices[voice].sustain_mode & 1)	/* Sustain controller on */
+	  {
+		  softoss_voices[voice].sustain_mode = 3;	/* Note off pending */
+		  return 0;
+	  }
+	if (velocity > 127 || softoss_voices[voice].mode & WAVE_FAST_RELEASE)
+	  {
+		  init_voice(devc, voice);	/* Mark it inactive */
+		  return 0;
+	  }
+	if (softoss_voices[voice].mode & WAVE_ENVELOPES)
+		step_envelope(voice, 1, velocity);	/* Enter sustain phase */
+	else
+		init_voice(devc, voice);	/* Mark it inactive */
+	return 0;
 }
 
 static int
-softsyn_set_instr (int dev, int voice, int instr)
+softsyn_set_instr(int dev, int voice, int instr)
 {
-  if (voice < 0 || voice > devc->maxvoice)
-    return 0;
-
-  if (instr < 0 || instr > MAX_PATCH)
-    {
-      printk ("SoftOSS: Invalid instrument number %d\n", instr);
-      return 0;
-    }
+	if (voice < 0 || voice > devc->maxvoice)
+		return 0;
 
-  softoss_voices[voice].instr = instr;
+	if (instr < 0 || instr > MAX_PATCH)
+	  {
+		  printk("SoftOSS: Invalid instrument number %d\n", instr);
+		  return 0;
+	  }
+	softoss_voices[voice].instr = instr;
 
-  return 0;
+	return 0;
 }
 
 static int
-softsyn_start_note (int dev, int voice, int note, int volume)
+softsyn_start_note(int dev, int voice, int note, int volume)
 {
-  int             instr = 0;
-  int             best_sample, best_delta, delta_freq, selected;
-  unsigned long   note_freq, freq, base_note, flags;
-  voice_info     *v = &softoss_voices[voice];
-
-  struct patch_info *sample;
-
-  if (voice < 0 || voice > devc->maxvoice)
-    return 0;
-
-  if (volume == 0)		/* Actually note off */
-    softsyn_kill_note (dev, voice, note, volume);
-
-  save_flags (flags);
-  cli ();
-
-  if (note == 255)
-    {				/* Just volume update */
-      v->velocity = volume;
-      if (voice_active[voice])
-	update_volume (voice);
-      restore_flags (flags);
-      return 0;
-    }
-
-  voice_active[voice] = 0;	/* Stop the voice for a while */
-  devc->vibratomap &= ~(1 << voice);
-  devc->tremolomap &= ~(1 << voice);
-
-  instr = v->instr;
-  if (instr < 0 || instr > MAX_PATCH || devc->programs[instr] == NO_SAMPLE)
-    {
-      printk ("SoftOSS: Undefined MIDI instrument %d\n", instr);
-      restore_flags (flags);
-      return 0;
-    }
-
-  instr = devc->programs[instr];
-
-  if (instr < 0 || instr >= devc->nrsamples)
-    {
-      printk ("SoftOSS: Corrupted MIDI instrument %d (%d)\n", v->instr, instr);
-      restore_flags (flags);
-      return 0;
-    }
-
-  note_freq = note_to_freq (note);
-
-  selected = -1;
-
-  best_sample = instr;
-  best_delta = 1000000;
-
-  while (instr != NO_SAMPLE && instr >= 0 && selected == -1)
-    {
-      delta_freq = note_freq - devc->samples[instr]->base_note;
-
-      if (delta_freq < 0)
-	delta_freq = -delta_freq;
-      if (delta_freq < best_delta)
-	{
-	  best_sample = instr;
-	  best_delta = delta_freq;
-	}
-      if (devc->samples[instr]->low_note <= note_freq &&
-	  note_freq <= devc->samples[instr]->high_note)
-	selected = instr;
-      else
-	instr = devc->samples[instr]->key;	/* Link to next sample */
-
-      if (instr < 0 || instr >= devc->nrsamples)
-	instr = NO_SAMPLE;
-    }
-
-  if (selected == -1)
-    instr = best_sample;
-  else
-    instr = selected;
-
-  if (instr < 0 || instr == NO_SAMPLE || instr > devc->nrsamples)
-    {
-      printk ("SoftOSS: Unresolved MIDI instrument %d\n", v->instr);
-      restore_flags (flags);
-      return 0;
-    }
-
-  sample = devc->samples[instr];
-  v->sample = sample;
-
-  if (v->percussive_voice)	/* No key tracking */
-    {
-      v->orig_freq = sample->base_freq;		/* Fixed pitch */
-    }
-  else
-    {
-      base_note = sample->base_note / 100;
-      note_freq /= 100;
-
-      freq = sample->base_freq * note_freq / base_note;
-      v->orig_freq = freq;
-    }
-
-  if (!(sample->mode & WAVE_LOOPING))
-    {
-      sample->loop_end = sample->len;
-    }
-
-  v->wave = devc->wave[instr];
-
-  if (volume < 0)
-    volume = 0;
-  else if (volume > 127)
-    volume = 127;
-
-  v->ptr = 0;
-  v->startloop = sample->loop_start * 512;
-  v->startbackloop = 0;
-  v->endloop = sample->loop_end * 512;
-  v->looplen = (sample->loop_end - sample->loop_start) * 512;
-  v->leftvol = 64;
-  v->rightvol = 64;
-  v->patch_vol = sample->volume;
-  v->velocity = volume;
-  v->mode = sample->mode;
-  v->vibrato_phase = 0;
-  v->vibrato_step = 0;
-  v->vibrato_level = 0;
-  v->vibrato_rate = 0;
-  v->vibrato_depth = 0;
-  v->tremolo_phase = 0;
-  v->tremolo_step = 0;
-  v->tremolo_level = 0;
-  v->tremolo_rate = 0;
-  v->tremolo_depth = 0;
-
-  if (!(v->mode & WAVE_LOOPING))
-    v->mode &= ~(WAVE_BIDIR_LOOP | WAVE_LOOP_BACK);
-  else if (v->mode & WAVE_LOOP_BACK)
-    {
-      v->ptr = sample->len;
-      v->startbackloop = v->startloop;
-    }
-
-  if (v->mode & WAVE_VIBRATO)
-    {
-      v->vibrato_rate = sample->vibrato_rate;
-      v->vibrato_depth = sample->vibrato_depth;
-    }
-
-  if (v->mode & WAVE_TREMOLO)
-    {
-      v->tremolo_rate = sample->tremolo_rate;
-      v->tremolo_depth = sample->tremolo_depth;
-    }
-
-  if (v->mode & WAVE_ENVELOPES)
-    {
-      v->envelope_phase = -1;
-      v->envelope_vol = 0;
-      step_envelope (voice, 0, 60);
-    }
-  update_volume (voice);
-  compute_step (voice);
+	int             instr = 0;
+	int             best_sample, best_delta, delta_freq, selected;
+	unsigned long   note_freq, freq, base_note, flags;
+	voice_info     *v = &softoss_voices[voice];
+
+	struct patch_info *sample;
+
+	if (voice < 0 || voice > devc->maxvoice)
+		return 0;
+
+	if (volume == 0)	/* Actually note off */
+		softsyn_kill_note(dev, voice, note, volume);
+
+	save_flags(flags);
+	cli();
+
+	if (note == 255)
+	  {			/* Just volume update */
+		  v->velocity = volume;
+		  if (voice_active[voice])
+			  update_volume(voice);
+		  restore_flags(flags);
+		  return 0;
+	  }
+	voice_active[voice] = 0;	/* Stop the voice for a while */
+	devc->vibratomap &= ~(1 << voice);
+	devc->tremolomap &= ~(1 << voice);
+
+	instr = v->instr;
+	if (instr < 0 || instr > MAX_PATCH || devc->programs[instr] == NO_SAMPLE)
+	  {
+		  printk("SoftOSS: Undefined MIDI instrument %d\n", instr);
+		  restore_flags(flags);
+		  return 0;
+	  }
+	instr = devc->programs[instr];
+
+	if (instr < 0 || instr >= devc->nrsamples)
+	  {
+		  printk("SoftOSS: Corrupted MIDI instrument %d (%d)\n", v->instr, instr);
+		  restore_flags(flags);
+		  return 0;
+	  }
+	note_freq = note_to_freq(note);
+
+	selected = -1;
+
+	best_sample = instr;
+	best_delta = 1000000;
+
+	while (instr != NO_SAMPLE && instr >= 0 && selected == -1)
+	  {
+		  delta_freq = note_freq - devc->samples[instr]->base_note;
+
+		  if (delta_freq < 0)
+			  delta_freq = -delta_freq;
+		  if (delta_freq < best_delta)
+		    {
+			    best_sample = instr;
+			    best_delta = delta_freq;
+		    }
+		  if (devc->samples[instr]->low_note <= note_freq &&
+		      note_freq <= devc->samples[instr]->high_note)
+			  selected = instr;
+		  else
+			  instr = devc->samples[instr]->key;	/* Link to next sample */
+
+		  if (instr < 0 || instr >= devc->nrsamples)
+			  instr = NO_SAMPLE;
+	  }
+
+	if (selected == -1)
+		instr = best_sample;
+	else
+		instr = selected;
+
+	if (instr < 0 || instr == NO_SAMPLE || instr > devc->nrsamples)
+	  {
+		  printk("SoftOSS: Unresolved MIDI instrument %d\n", v->instr);
+		  restore_flags(flags);
+		  return 0;
+	  }
+	sample = devc->samples[instr];
+	v->sample = sample;
+
+	if (v->percussive_voice)	/* No key tracking */
+	  {
+		  v->orig_freq = sample->base_freq;	/* Fixed pitch */
+	} else
+	  {
+		  base_note = sample->base_note / 100;
+		  note_freq /= 100;
+
+		  freq = sample->base_freq * note_freq / base_note;
+		  v->orig_freq = freq;
+	  }
+
+	if (!(sample->mode & WAVE_LOOPING))
+	  {
+		  sample->loop_end = sample->len;
+	  }
+	v->wave = devc->wave[instr];
+
+	if (volume < 0)
+		volume = 0;
+	else if (volume > 127)
+		volume = 127;
+
+	v->ptr = 0;
+	v->startloop = sample->loop_start * 512;
+	v->startbackloop = 0;
+	v->endloop = sample->loop_end * 512;
+	v->looplen = (sample->loop_end - sample->loop_start) * 512;
+	v->leftvol = 64;
+	v->rightvol = 64;
+	v->patch_vol = sample->volume;
+	v->velocity = volume;
+	v->mode = sample->mode;
+	v->vibrato_phase = 0;
+	v->vibrato_step = 0;
+	v->vibrato_level = 0;
+	v->vibrato_rate = 0;
+	v->vibrato_depth = 0;
+	v->tremolo_phase = 0;
+	v->tremolo_step = 0;
+	v->tremolo_level = 0;
+	v->tremolo_rate = 0;
+	v->tremolo_depth = 0;
+
+	if (!(v->mode & WAVE_LOOPING))
+		v->mode &= ~(WAVE_BIDIR_LOOP | WAVE_LOOP_BACK);
+	else if (v->mode & WAVE_LOOP_BACK)
+	  {
+		  v->ptr = sample->len;
+		  v->startbackloop = v->startloop;
+	  }
+	if (v->mode & WAVE_VIBRATO)
+	  {
+		  v->vibrato_rate = sample->vibrato_rate;
+		  v->vibrato_depth = sample->vibrato_depth;
+	  }
+	if (v->mode & WAVE_TREMOLO)
+	  {
+		  v->tremolo_rate = sample->tremolo_rate;
+		  v->tremolo_depth = sample->tremolo_depth;
+	  }
+	if (v->mode & WAVE_ENVELOPES)
+	  {
+		  v->envelope_phase = -1;
+		  v->envelope_vol = 0;
+		  step_envelope(voice, 0, 60);
+	  }
+	update_volume(voice);
+	compute_step(voice);
 
-  voice_active[voice] = 1;	/* Mark it active */
+	voice_active[voice] = 1;	/* Mark it active */
 
-  restore_flags (flags);
-  return 0;
+	restore_flags(flags);
+	return 0;
 }
 
 static int
-softsyn_open (int synthdev, int mode)
+softsyn_open(int synthdev, int mode)
 {
-  int             err;
-  extern int      softoss_dev;
-  int             frags = 0x7fff0007;	/* fragment size of 128 bytes */
+	int             err;
+	extern int      softoss_dev;
+	int             frags = 0x7fff0007;	/* fragment size of 128 bytes */
 
-  if (devc->audio_opened)	/* Already opened */
-    return 0;
+	if (devc->audio_opened)	/* Already opened */
+		return 0;
 
-  softsynth_disabled = 0;
-  devc->finfo.mode = OPEN_WRITE;
-  devc->finfo.flags = 0;
+	softsynth_disabled = 0;
+	devc->finfo.mode = OPEN_WRITE;
+	devc->finfo.flags = 0;
 
-  if (softoss_dev >= num_audiodevs)
-    softoss_dev = num_audiodevs - 1;
+	if (softoss_dev >= num_audiodevs)
+		softoss_dev = num_audiodevs - 1;
 
-  if (softoss_dev < 0)
-    softoss_dev = 0;
-  if (softoss_dev >= num_audiodevs)
-    return -ENXIO;
-  devc->audiodev = softoss_dev;
+	if (softoss_dev < 0)
+		softoss_dev = 0;
+	if (softoss_dev >= num_audiodevs)
+		return -ENXIO;
+	devc->audiodev = softoss_dev;
 
-  if (!(audio_devs[devc->audiodev]->format_mask & AFMT_S16_LE))
-    {
-      printk ("SoftOSS: The audio device doesn't support 16 bits\n");
-      return -ENXIO;
-    }
-  if ((err = audio_open ((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo)) < 0)
-    return err;
+	if (!(audio_devs[devc->audiodev]->format_mask & AFMT_S16_LE))
+	  {
+		  printk("SoftOSS: The audio device doesn't support 16 bits\n");
+		  return -ENXIO;
+	  }
+	if ((err = audio_open((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo)) < 0)
+		return err;
 
-  devc->speed = audio_devs[devc->audiodev]->d->set_speed (
-					       devc->audiodev, devc->speed);
-  devc->channels = audio_devs[devc->audiodev]->d->set_channels (
-					    devc->audiodev, devc->channels);
-  devc->bits = audio_devs[devc->audiodev]->d->set_bits (
-						devc->audiodev, devc->bits);
+	devc->speed = audio_devs[devc->audiodev]->d->set_speed(
+					    devc->audiodev, devc->speed);
+	devc->channels = audio_devs[devc->audiodev]->d->set_channels(
+					 devc->audiodev, devc->channels);
+	devc->bits = audio_devs[devc->audiodev]->d->set_bits(
+					     devc->audiodev, devc->bits);
 
 
-  DDB (printk ("SoftOSS: Using audio dev %d, speed %d, bits %d, channels %d\n", devc->audiodev, devc->speed, devc->bits, devc->channels));
+	DDB(printk("SoftOSS: Using audio dev %d, speed %d, bits %d, channels %d\n", devc->audiodev, devc->speed, devc->bits, devc->channels));
 
-  dma_ioctl (devc->audiodev, SNDCTL_DSP_SETFRAGMENT, (caddr_t) & frags);
-  dma_ioctl (devc->audiodev, SNDCTL_DSP_GETBLKSIZE, (caddr_t) & devc->fragsize);
+	dma_ioctl(devc->audiodev, SNDCTL_DSP_SETFRAGMENT, (caddr_t) & frags);
+	dma_ioctl(devc->audiodev, SNDCTL_DSP_GETBLKSIZE, (caddr_t) & devc->fragsize);
 
-  if (devc->bits != 16 || devc->channels != 2)
-    {
-      audio_release ((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo);
-      printk ("SoftOSS: A 16 bit stereo soundcard is required\n");
-      return 0;
-    }
+	if (devc->bits != 16 || devc->channels != 2)
+	  {
+		  audio_release((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo);
+		  printk("SoftOSS: A 16 bit stereo soundcard is required\n");
+		  return 0;
+	  }
+	if (devc->max_playahead >= audio_devs[devc->audiodev]->dmap_out->nbufs)
+		devc->max_playahead = audio_devs[devc->audiodev]->dmap_out->nbufs;
 
-  if (devc->max_playahead >= audio_devs[devc->audiodev]->dmap_out->nbufs)
-    devc->max_playahead = audio_devs[devc->audiodev]->dmap_out->nbufs;
+	DDB(printk("SoftOSS: Using %d fragments of %d bytes\n", devc->max_playahead, devc->fragsize));
 
-  DDB (printk ("SoftOSS: Using %d fragments of %d bytes\n", devc->max_playahead, devc->fragsize));
-
-  init_engine (devc);
-  devc->audio_opened = 1;
-  devc->sequencer_mode = mode;
-  return 0;
+	init_engine(devc);
+	devc->audio_opened = 1;
+	devc->sequencer_mode = mode;
+	return 0;
 }
 
 static void
-softsyn_close (int synthdev)
+softsyn_close(int synthdev)
 {
-  devc->engine_state = ES_STOPPED;
+	devc->engine_state = ES_STOPPED;
 #ifdef POLLED_MODE
-  del_timer (&poll_timer);;
+	del_timer(&poll_timer);;
 #endif
-  dma_ioctl (devc->audiodev, SNDCTL_DSP_RESET, 0);
-  if (devc->audio_opened)
-    audio_release ((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo);
-  devc->audio_opened = 0;
+	dma_ioctl(devc->audiodev, SNDCTL_DSP_RESET, 0);
+	if (devc->audio_opened)
+		audio_release((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo);
+	devc->audio_opened = 0;
 }
 
 static void
-softsyn_hw_control (int dev, unsigned char *event_rec)
+softsyn_hw_control(int dev, unsigned char *event_rec)
 {
-  int             voice, cmd;
-  unsigned short  p1, p2;
-  unsigned int    plong;
+	int             voice, cmd;
+	unsigned short  p1, p2;
+	unsigned int    plong;
 
-  cmd = event_rec[2];
-  voice = event_rec[3];
-  p1 = *(unsigned short *) &event_rec[4];
-  p2 = *(unsigned short *) &event_rec[6];
-  plong = *(unsigned int *) &event_rec[4];
+	cmd = event_rec[2];
+	voice = event_rec[3];
+	p1 = *(unsigned short *) &event_rec[4];
+	p2 = *(unsigned short *) &event_rec[6];
+	plong = *(unsigned int *) &event_rec[4];
 
-  switch (cmd)
-    {
+	switch (cmd)
+	  {
 
-    case _GUS_NUMVOICES:
-      set_max_voices (p1);
-      break;
+	  case _GUS_NUMVOICES:
+		  set_max_voices(p1);
+		  break;
 
 
-    default:;
-    }
+	  default:;
+	  }
 }
 
 static int
-softsyn_load_patch (int dev, int format, const char *addr,
-		    int offs, int count, int pmgr_flag)
+softsyn_load_patch(int dev, int format, const char *addr,
+		   int offs, int count, int pmgr_flag)
 {
-  struct patch_info *patch = NULL;
-
-  int             i, p, instr;
-  long            sizeof_patch;
-  int             memlen, adj;
-  unsigned short  data;
-  short          *wave = NULL;
-
-  sizeof_patch = (long) &patch->data[0] - (long) patch;		/* Header size */
-
-  if (format != GUS_PATCH)
-    {
-      printk ("SoftOSS: Invalid patch format (key) 0x%x\n", format);
-      return -EINVAL;
-    }
-
-  if (count < sizeof_patch)
-    {
-      printk ("SoftOSS: Patch header too short\n");
-      return -EINVAL;
-    }
-
-  count -= sizeof_patch;
-
-  if (devc->nrsamples >= MAX_SAMPLE)
-    {
-      printk ("SoftOSS: Sample table full\n");
-      return -ENOSPC;
-    }
-
-  /*
-   * Copy the header from user space but ignore the first bytes which have
-   * been transferred already.
-   */
-
-  patch = vmalloc (sizeof (*patch));
-
-  if (patch == NULL)
-    {
-      printk ("SoftOSS: Out of memory\n");
-      return -ENOSPC;
-    }
-
-  copy_from_user (&((char *) patch)[offs], &(addr)[offs], sizeof_patch - offs);
-
-  if (patch->mode & WAVE_ROM)
-    {
-      vfree (patch);
-      return -EINVAL;
-    }
-
-  instr = patch->instr_no;
-
-  if (instr < 0 || instr > MAX_PATCH)
-    {
-      printk ("SoftOSS: Invalid patch number %d\n", instr);
-      vfree (patch);
-      return -EINVAL;
-    }
-
-  if (count < patch->len)
-    {
-      printk ("SoftOSS: Patch record too short (%d<%d)\n", count, (int) patch->len);
-      patch->len = count;
-    }
-
-  if (patch->len <= 0 || patch->len > (devc->ram_size - devc->ram_used))
-    {
-      printk ("SoftOSS: Invalid sample length %d\n", (int) patch->len);
-      vfree (patch);
-      return -EINVAL;
-    }
-
-  if (patch->mode & WAVE_LOOPING)
-    {
-      if (patch->loop_start < 0 || patch->loop_start >= patch->len)
-	{
-	  printk ("SoftOSS: Invalid loop start %d\n", patch->loop_start);
-	  vfree (patch);
-	  return -EINVAL;
-	}
-
-      if (patch->loop_end < patch->loop_start || patch->loop_end > patch->len)
-	{
-	  printk ("SoftOSS: Invalid loop start or end point (%d, %d)\n", patch->loop_start, patch->loop_end);
-	  vfree (patch);
-	  return -EINVAL;
-	}
-    }
+	struct patch_info *patch = NULL;
 
+	int             i, p, instr;
+	long            sizeof_patch;
+	int             memlen, adj;
+	unsigned short  data;
+	short          *wave = NULL;
+
+	sizeof_patch = (long) &patch->data[0] - (long) patch;	/* Header size */
+
+	if (format != GUS_PATCH)
+	  {
+		  printk("SoftOSS: Invalid patch format (key) 0x%x\n", format);
+		  return -EINVAL;
+	  }
+	if (count < sizeof_patch)
+	  {
+		  printk("SoftOSS: Patch header too short\n");
+		  return -EINVAL;
+	  }
+	count -= sizeof_patch;
+
+	if (devc->nrsamples >= MAX_SAMPLE)
+	  {
+		  printk("SoftOSS: Sample table full\n");
+		  return -ENOSPC;
+	  }
+	/*
+	 * Copy the header from user space but ignore the first bytes which have
+	 * been transferred already.
+	 */
+
+	patch = vmalloc(sizeof(*patch));
+
+	if (patch == NULL)
+	  {
+		  printk("SoftOSS: Out of memory\n");
+		  return -ENOSPC;
+	  }
+	copy_from_user(&((char *) patch)[offs], &(addr)[offs], sizeof_patch - offs);
+
+	if (patch->mode & WAVE_ROM)
+	  {
+		  vfree(patch);
+		  return -EINVAL;
+	  }
+	instr = patch->instr_no;
+
+	if (instr < 0 || instr > MAX_PATCH)
+	  {
+		  printk("SoftOSS: Invalid patch number %d\n", instr);
+		  vfree(patch);
+		  return -EINVAL;
+	  }
+	if (count < patch->len)
+	  {
+		  printk("SoftOSS: Patch record too short (%d<%d)\n", count, (int) patch->len);
+		  patch->len = count;
+	  }
+	if (patch->len <= 0 || patch->len > (devc->ram_size - devc->ram_used))
+	  {
+		  printk("SoftOSS: Invalid sample length %d\n", (int) patch->len);
+		  vfree(patch);
+		  return -EINVAL;
+	  }
+	if (patch->mode & WAVE_LOOPING)
+	  {
+		  if (patch->loop_start < 0 || patch->loop_start >= patch->len)
+		    {
+			    printk("SoftOSS: Invalid loop start %d\n", patch->loop_start);
+			    vfree(patch);
+			    return -EINVAL;
+		    }
+		  if (patch->loop_end < patch->loop_start || patch->loop_end > patch->len)
+		    {
+			    printk("SoftOSS: Invalid loop start or end point (%d, %d)\n", patch->loop_start, patch->loop_end);
+			    vfree(patch);
+			    return -EINVAL;
+		    }
+	  }
 /* 
  * Next load the wave data to memory
  */
 
-  memlen = patch->len;
-  adj = 1;
+	memlen = patch->len;
+	adj = 1;
 
-  if (!(patch->mode & WAVE_16_BITS))
-    memlen *= 2;
-  else
-    adj = 2;
-
-  wave = vmalloc (memlen);
-
-  if (wave == NULL)
-    {
-      printk ("SoftOSS: Can't allocate %d bytes of mem for a sample\n", memlen);
-      vfree (patch);
-      return -ENOSPC;
-    }
-
-  p = 0;
-  for (i = 0; i < memlen / 2; i++)	/* Handle words */
-    {
-      unsigned char   tmp;
-
-      data = 0;
-
-      if (patch->mode & WAVE_16_BITS)
-	{
-	  get_user (*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));	/* Get lsb */
-	  data = tmp;
-	  get_user (*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));	/* Get msb */
-	  if (patch->mode & WAVE_UNSIGNED)
-	    tmp ^= 0x80;	/* Convert to signed */
-	  data |= (tmp << 8);
-	}
-      else
-	{
-	  get_user (*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));
-	  if (patch->mode & WAVE_UNSIGNED)
-	    tmp ^= 0x80;	/* Convert to signed */
-	  data = (tmp << 8);	/* Convert to 16 bits */
-	}
+	if (!(patch->mode & WAVE_16_BITS))
+		memlen *= 2;
+	else
+		adj = 2;
+
+	wave = vmalloc(memlen);
+
+	if (wave == NULL)
+	  {
+		  printk("SoftOSS: Can't allocate %d bytes of mem for a sample\n", memlen);
+		  vfree(patch);
+		  return -ENOSPC;
+	  }
+	p = 0;
+	for (i = 0; i < memlen / 2; i++)	/* Handle words */
+	  {
+		  unsigned char   tmp;
+
+		  data = 0;
+
+		  if (patch->mode & WAVE_16_BITS)
+		    {
+			    get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));		/* Get lsb */
+			    data = tmp;
+			    get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));		/* Get msb */
+			    if (patch->mode & WAVE_UNSIGNED)
+				    tmp ^= 0x80;	/* Convert to signed */
+			    data |= (tmp << 8);
+		  } else
+		    {
+			    get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));
+			    if (patch->mode & WAVE_UNSIGNED)
+				    tmp ^= 0x80;	/* Convert to signed */
+			    data = (tmp << 8);	/* Convert to 16 bits */
+		    }
 
-      wave[i] = (short) data;
-    }
+		  wave[i] = (short) data;
+	  }
 
-  devc->ram_used += patch->len;
+	devc->ram_used += patch->len;
 /*
  * Convert pointers to 16 bit indexes
  */
-  patch->len /= adj;
-  patch->loop_start /= adj;
-  patch->loop_end /= adj;
+	patch->len /= adj;
+	patch->loop_start /= adj;
+	patch->loop_end /= adj;
 
 /*
  * Finally link the loaded patch to the chain
  */
 
-  patch->key = devc->programs[instr];
-  devc->programs[instr] = devc->nrsamples;
-  devc->wave[devc->nrsamples] = (short *) wave;
-  devc->samples[devc->nrsamples++] = patch;
+	patch->key = devc->programs[instr];
+	devc->programs[instr] = devc->nrsamples;
+	devc->wave[devc->nrsamples] = (short *) wave;
+	devc->samples[devc->nrsamples++] = patch;
 
-  return 0;
+	return 0;
 }
 
 static void
-softsyn_panning (int dev, int voice, int pan)
+softsyn_panning(int dev, int voice, int pan)
 {
-  if (voice < 0 || voice > devc->maxvoice)
-    return;
+	if (voice < 0 || voice > devc->maxvoice)
+		return;
 
-  if (pan < -128)
-    pan = -128;
-  if (pan > 127)
-    pan = 127;
+	if (pan < -128)
+		pan = -128;
+	if (pan > 127)
+		pan = 127;
 
-  softoss_voices[voice].panning = pan;
-  if (voice_active[voice])
-    update_volume (voice);
+	softoss_voices[voice].panning = pan;
+	if (voice_active[voice])
+		update_volume(voice);
 }
 
 static void
-softsyn_volume_method (int dev, int mode)
+softsyn_volume_method(int dev, int mode)
 {
 }
 
 static void
-softsyn_aftertouch (int dev, int voice, int pressure)
+softsyn_aftertouch(int dev, int voice, int pressure)
 {
-  if (voice < 0 || voice > devc->maxvoice)
-    return;
+	if (voice < 0 || voice > devc->maxvoice)
+		return;
 
-  if (voice_active[voice])
-    update_volume (voice);
+	if (voice_active[voice])
+		update_volume(voice);
 }
 
 static void
-softsyn_controller (int dev, int voice, int ctrl_num, int value)
+softsyn_controller(int dev, int voice, int ctrl_num, int value)
 {
-  unsigned long   flags;
+	unsigned long   flags;
 
-  if (voice < 0 || voice > devc->maxvoice)
-    return;
-  save_flags (flags);
-  cli ();
+	if (voice < 0 || voice > devc->maxvoice)
+		return;
+	save_flags(flags);
+	cli();
 
-  switch (ctrl_num)
-    {
-    case CTRL_PITCH_BENDER:
-      softoss_voices[voice].bender = value;
+	switch (ctrl_num)
+	  {
+	  case CTRL_PITCH_BENDER:
+		  softoss_voices[voice].bender = value;
 
-      if (voice_active[voice])
-	compute_step (voice);	/* Update pitch */
-      break;
+		  if (voice_active[voice])
+			  compute_step(voice);	/* Update pitch */
+		  break;
 
 
-    case CTRL_PITCH_BENDER_RANGE:
-      softoss_voices[voice].bender_range = value;
-      break;
-    case CTL_EXPRESSION:
-      value /= 128;
-    case CTRL_EXPRESSION:
-      softoss_voices[voice].expression_vol = value;
-      if (voice_active[voice])
-	update_volume (voice);
-      break;
+	  case CTRL_PITCH_BENDER_RANGE:
+		  softoss_voices[voice].bender_range = value;
+		  break;
+	  case CTL_EXPRESSION:
+		  value /= 128;
+	  case CTRL_EXPRESSION:
+		  softoss_voices[voice].expression_vol = value;
+		  if (voice_active[voice])
+			  update_volume(voice);
+		  break;
 
-    case CTL_PAN:
-      softsyn_panning (dev, voice, (value * 2) - 128);
-      break;
+	  case CTL_PAN:
+		  softsyn_panning(dev, voice, (value * 2) - 128);
+		  break;
 
-    case CTL_MAIN_VOLUME:
-      value = (value * 100) / 16383;
+	  case CTL_MAIN_VOLUME:
+		  value = (value * 100) / 16383;
 
-    case CTRL_MAIN_VOLUME:
-      softoss_voices[voice].main_vol = value;
-      if (voice_active[voice])
-	update_volume (voice);
-      break;
+	  case CTRL_MAIN_VOLUME:
+		  softoss_voices[voice].main_vol = value;
+		  if (voice_active[voice])
+			  update_volume(voice);
+		  break;
 
-    default:
-      break;
-    }
+	  default:
+		  break;
+	  }
 
-  restore_flags (flags);
+	restore_flags(flags);
 }
 
 static void
-softsyn_bender (int dev, int voice, int value)
+softsyn_bender(int dev, int voice, int value)
 {
-  if (voice < 0 || voice > devc->maxvoice)
-    return;
+	if (voice < 0 || voice > devc->maxvoice)
+		return;
 
-  softoss_voices[voice].bender = value - 8192;
-  if (voice_active[voice])
-    compute_step (voice);	/* Update pitch */
+	softoss_voices[voice].bender = value - 8192;
+	if (voice_active[voice])
+		compute_step(voice);	/* Update pitch */
 }
 
 static int
-softsyn_alloc_voice (int dev, int chn, int note, struct voice_alloc_info *alloc)
+softsyn_alloc_voice(int dev, int chn, int note, struct voice_alloc_info *alloc)
 {
-  int             i, p, best = -1, best_time = 0x7fffffff;
+	int             i, p, best = -1, best_time = 0x7fffffff;
 
-  p = alloc->ptr;
-  /*
-     * First look for a completely stopped voice
-   */
-
-  for (i = 0; i < alloc->max_voice; i++)
-    {
-      if (alloc->map[p] == 0)
-	{
-	  alloc->ptr = p;
-	  voice_active[p] = 0;
-	  return p;
-	}
-      if (alloc->alloc_times[p] < best_time)
-	{
-	  best = p;
-	  best_time = alloc->alloc_times[p];
-	}
-      p = (p + 1) % alloc->max_voice;
-    }
-
-  /*
-     * Then look for a releasing voice
-   */
-
-  for (i = 0; i < alloc->max_voice; i++)
-    {
-      if (alloc->map[p] == 0xffff)
-	{
-	  alloc->ptr = p;
-	  voice_active[p] = 0;
-	  return p;
-	}
-      p = (p + 1) % alloc->max_voice;
-    }
-
-  if (best >= 0)
-    p = best;
-
-  alloc->ptr = p;
-  voice_active[p] = 0;
-  return p;
-}
-
-static void
-softsyn_setup_voice (int dev, int voice, int chn)
-{
-  unsigned long   flags;
-
-  struct channel_info *info =
-  &synth_devs[dev]->chn_info[chn];
-
-  save_flags (flags);
-  cli ();
-  /* init_voice(devc, voice); */
-  softsyn_set_instr (dev, voice, info->pgm_num);
-
-  softoss_voices[voice].expression_vol =
-    info->controllers[CTL_EXPRESSION];	/* Just MSB */
-  softoss_voices[voice].main_vol =
-    (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128;
-  softsyn_panning (dev, voice, (info->controllers[CTL_PAN] * 2) - 128);
-  softoss_voices[voice].bender = 0;	/* info->bender_value; */
-  softoss_voices[voice].bender_range = info->bender_range;
-
-  if (chn == 9)
-    softoss_voices[voice].percussive_voice = 1;
-  restore_flags (flags);
-}
-
-static void
-softsyn_reset (int devno)
-{
-  int             i;
-  unsigned long   flags;
-
-  save_flags (flags);
-  cli ();
-
-  for (i = 0; i < devc->maxvoice; i++)
-    init_voice (devc, i);
-  restore_flags (flags);
+	p = alloc->ptr;
+	/*
+	   * First look for a completely stopped voice
+	 */
+
+	for (i = 0; i < alloc->max_voice; i++)
+	  {
+		  if (alloc->map[p] == 0)
+		    {
+			    alloc->ptr = p;
+			    voice_active[p] = 0;
+			    return p;
+		    }
+		  if (alloc->alloc_times[p] < best_time)
+		    {
+			    best = p;
+			    best_time = alloc->alloc_times[p];
+		    }
+		  p = (p + 1) % alloc->max_voice;
+	  }
+
+	/*
+	   * Then look for a releasing voice
+	 */
+
+	for (i = 0; i < alloc->max_voice; i++)
+	  {
+		  if (alloc->map[p] == 0xffff)
+		    {
+			    alloc->ptr = p;
+			    voice_active[p] = 0;
+			    return p;
+		    }
+		  p = (p + 1) % alloc->max_voice;
+	  }
+
+	if (best >= 0)
+		p = best;
+
+	alloc->ptr = p;
+	voice_active[p] = 0;
+	return p;
+}
+
+static void
+softsyn_setup_voice(int dev, int voice, int chn)
+{
+	unsigned long   flags;
+
+	struct channel_info *info =
+	&synth_devs[dev]->chn_info[chn];
+
+	save_flags(flags);
+	cli();
+	/* init_voice(devc, voice); */
+	softsyn_set_instr(dev, voice, info->pgm_num);
+
+	softoss_voices[voice].expression_vol =
+	    info->controllers[CTL_EXPRESSION];	/* Just MSB */
+	softoss_voices[voice].main_vol =
+	    (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128;
+	softsyn_panning(dev, voice, (info->controllers[CTL_PAN] * 2) - 128);
+	softoss_voices[voice].bender = 0;	/* info->bender_value; */
+	softoss_voices[voice].bender_range = info->bender_range;
+
+	if (chn == 9)
+		softoss_voices[voice].percussive_voice = 1;
+	restore_flags(flags);
+}
+
+static void
+softsyn_reset(int devno)
+{
+	int             i;
+	unsigned long   flags;
+
+	save_flags(flags);
+	cli();
+
+	for (i = 0; i < devc->maxvoice; i++)
+		init_voice(devc, i);
+	restore_flags(flags);
 }
 
 static struct synth_operations softsyn_operations =
 {
-  "SoftOSS",
-  &softsyn_info,
-  0,
-  SYNTH_TYPE_SAMPLE,
-  0,
-  softsyn_open,
-  softsyn_close,
-  softsyn_ioctl,
-  softsyn_kill_note,
-  softsyn_start_note,
-  softsyn_set_instr,
-  softsyn_reset,
-  softsyn_hw_control,
-  softsyn_load_patch,
-  softsyn_aftertouch,
-  softsyn_controller,
-  softsyn_panning,
-  softsyn_volume_method,
-  softsyn_bender,
-  softsyn_alloc_voice,
-  softsyn_setup_voice
+	"SoftOSS",
+	&softsyn_info,
+	0,
+	SYNTH_TYPE_SAMPLE,
+	0,
+	softsyn_open,
+	softsyn_close,
+	softsyn_ioctl,
+	softsyn_kill_note,
+	softsyn_start_note,
+	softsyn_set_instr,
+	softsyn_reset,
+	softsyn_hw_control,
+	softsyn_load_patch,
+	softsyn_aftertouch,
+	softsyn_controller,
+	softsyn_panning,
+	softsyn_volume_method,
+	softsyn_bender,
+	softsyn_alloc_voice,
+	softsyn_setup_voice
 };
 
 /*
@@ -1493,101 +1455,126 @@
  */
 
 static unsigned int
-soft_tmr_start (int dev, unsigned int usecs)
+soft_tmr_start(int dev, unsigned int usecs)
 {
-  tmr_running = 1;
-  start_engine (devc);
-  return devc->usecs_per_frag;
+	tmr_running = 1;
+	start_engine(devc);
+	return devc->usecs_per_frag;
 }
 
 static void
-soft_tmr_disable (int dev)
+soft_tmr_disable(int dev)
 {
-  stop_engine (devc);
-  tmr_running = 0;
+	stop_engine(devc);
+	tmr_running = 0;
 }
 
 static void
-soft_tmr_restart (int dev)
+soft_tmr_restart(int dev)
 {
-  tmr_running = 1;
+	tmr_running = 1;
 }
 
 static struct sound_lowlev_timer soft_tmr =
 {
-  0,
-  9999,
-  soft_tmr_start,
-  soft_tmr_disable,
-  soft_tmr_restart
+	0,
+	9999,
+	soft_tmr_start,
+	soft_tmr_disable,
+	soft_tmr_restart
 };
 
 int
-probe_softsyn (struct address_info *hw_config)
+probe_softsyn(struct address_info *hw_config)
 {
-  int             i;
+	int             i;
 
-  if (softsynth_loaded)
-    return 0;
+	if (softsynth_loaded)
+		return 0;
 
-  devc->ram_size = 8 * 1024 * 1024;
-  devc->ram_used = 0;
-  devc->nrsamples = 0;
-  for (i = 0; i < MAX_PATCH; i++)
-    {
-      devc->programs[i] = NO_SAMPLE;
-      devc->wave[i] = NULL;
-    }
-
-  devc->maxvoice = DEFAULT_VOICES;
-
-  devc->audiodev = 0;
-  devc->audio_opened = 0;
-  devc->channels = 2;
-  devc->bits = 16;
-  devc->max_playahead = 32;
+	devc->ram_size = 8 * 1024 * 1024;
+	devc->ram_used = 0;
+	devc->nrsamples = 0;
+	for (i = 0; i < MAX_PATCH; i++)
+	  {
+		  devc->programs[i] = NO_SAMPLE;
+		  devc->wave[i] = NULL;
+	  }
+
+	devc->maxvoice = DEFAULT_VOICES;
+
+	devc->audiodev = 0;
+	devc->audio_opened = 0;
+	devc->channels = 2;
+	devc->bits = 16;
+	devc->max_playahead = 32;
 
 #ifdef SOFTOSS_RATE
-  devc->speed = SOFTOSS_RATE;
+	devc->speed = SOFTOSS_RATE;
 #else
-  devc->speed = 32000;
+	devc->speed = 32000;
 #endif
 
 #ifdef SOFTOSS_VOICES
-  devc->default_max_voices = SOFTOSS_VOICES;
+	devc->default_max_voices = SOFTOSS_VOICES;
 #else
-  devc->default_max_voices = 32;
+	devc->default_max_voices = 32;
 #endif
 
-  softsynth_loaded = 1;
-  return 1;
+	softsynth_loaded = 1;
+	return 1;
 }
 
 void
-attach_softsyn_card (struct address_info *hw_config)
+attach_softsyn_card(struct address_info *hw_config)
 {
 
-  voice_alloc = &softsyn_operations.alloc;
-  synth_devs[num_synths++] = &softsyn_operations;
-  sequencer_init ();
-  sound_timer_init (&soft_tmr, "SoftOSS");
-  devc->synthdev = num_synths;
-  softsynthp = softsynth_hook;
+	voice_alloc = &softsyn_operations.alloc;
+	synth_devs[devc->synthdev = num_synths++] = &softsyn_operations;
+	sequencer_init();
+	sound_timer_init(&soft_tmr, "SoftOSS");
+	devc->timerdev = num_sound_timers;
+	softsynthp = softsynth_hook;
 
 #ifndef POLLED_MODE
 #endif
 }
 
 void
-unload_softsyn (struct address_info *hw_config)
+unload_softsyn(struct address_info *hw_config)
 {
-  if (!softsynth_loaded)
-    return;
+	if (!softsynth_loaded)
+		return;
 #ifndef POLLED_MODE
 #endif
 
-  softsynthp = NULL;
-  reset_samples (devc);
+	softsynthp = NULL;
+	softsynth_loaded = 0;
+	reset_samples(devc);
+}
+
+#ifdef MODULE
+
+static struct address_info config;
+
+int
+init_module(void)
+{
+	printk("SoftOSS driver Copyright (C) by Hannu Savolainen 1993-1997\n");
+	if (!probe_softsyn(&config))
+		return -ENODEV;
+	attach_softsyn_card(&config);
+	SOUND_LOCK;
+	return 0;
 }
 
+void
+cleanup_module(void)
+{
+	unload_softsyn(&config);
+	sound_unload_synthdev(devc->synthdev);
+	sound_unload_timerdev(devc->timerdev);
+	SOUND_LOCK_END;
+}
+#endif
 #endif

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