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
- Lines: 2724
- Date:
Sat Nov 29 10:33:21 1997
- Orig file:
v2.1.66/linux/drivers/sound/softoss.c
- Orig date:
Wed Nov 12 13:34:27 1997
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