[PATCH] sound updates

From: Christoph Hellwig (hch@caldera.de)
Date: Mon Sep 25 2000 - 14:23:24 EST


Hi Linus,
I've attached twosound-related patches:
 - the first one moves all remaining sound drivers to the
   module_init/module_exit stuff. It's not really critical,
   but makes another subsystem clean of the old init stuff.
 - the second patch removes the softoss software synthesizer.
   It does only work with the OSS/Free style sounddrivers and
   has some ugly hooks in the sequencer core.
   Alan has accepted this change.

Christoph

-- 
Always remember that you are unique.  Just like everyone else.

diff -uNr linux.orig/drivers/char/mem.c linux/drivers/char/mem.c --- linux.orig/drivers/char/mem.c Sat Sep 23 09:04:14 2000 +++ linux/drivers/char/mem.c Mon Sep 25 20:42:29 2000 @@ -28,12 +28,6 @@ #ifdef CONFIG_I2C extern int i2c_init_all(void); #endif -#ifdef CONFIG_SOUND -void soundcore_init(void); -#ifdef CONFIG_SOUND_OSS -void soundcard_init(void); -#endif -#endif #ifdef CONFIG_SPARCAUDIO extern int sparcaudio_init(void); #endif diff -uNr linux.orig/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c --- linux.orig/drivers/sound/cmpci.c Sat Sep 23 09:03:09 2000 +++ linux/drivers/sound/cmpci.c Mon Sep 25 19:54:26 2000 @@ -2287,8 +2287,6 @@ MODULE_PARM(spdif_loop, "i"); MODULE_PARM(four_ch, "i"); MODULE_PARM(rear_out, "i"); - -int __init init_module(void) #else #ifdef CONFIG_SOUND_CMPCI_SPDIFLOOP static int spdif_loop = 1; @@ -2305,9 +2303,9 @@ #else static int rear_out = 0; #endif - -int __init init_cmpci(void) #endif + +static int __init init_cmpci(void) { struct cm_state *s; struct pci_dev *pcidev = NULL; @@ -2499,12 +2497,10 @@ /* --------------------------------------------------------------------- */ -#ifdef MODULE - MODULE_AUTHOR("ChenLi Tien, cltien@home.com"); MODULE_DESCRIPTION("CMPCI Audio Driver"); -void cleanup_module(void) +static void __exit cleanup_cmpci(void) { struct cm_state *s; @@ -2538,4 +2534,5 @@ printk(KERN_INFO "cmpci: unloading\n"); } -#endif /* MODULE */ +module_init(init_cmpci); +module_exit(cleanup_cmpci); diff -uNr linux.orig/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c --- linux.orig/drivers/sound/msnd_pinnacle.c Sat Sep 23 09:03:09 2000 +++ linux/drivers/sound/msnd_pinnacle.c Mon Sep 25 19:54:26 2000 @@ -1610,10 +1610,6 @@ static int fifosize __initdata = DEFFIFOSIZE; static int calibrate_signal __initdata; -/* If we're a module, this is just init_module */ - -int init_module(void) - #else /* not a module */ static int write_ndelay __initdata = -1; @@ -1692,14 +1688,10 @@ #endif static int calibrate_signal __initdata = CONFIG_MSND_CALSIGNAL; +#endif /* MODULE */ -#ifdef MSND_CLASSIC -int __init msnd_classic_init(void) -#else -int __init msnd_pinnacle_init(void) -#endif /* MSND_CLASSIC */ -#endif /* MODULE */ +static int __init msnd_init(void) { int err; #ifndef MSND_CLASSIC @@ -1875,11 +1867,12 @@ return 0; } -#ifdef MODULE -void cleanup_module(void) +static void __exit msdn_cleanup(void) { unload_multisound(); msnd_fifo_free(&dev.DAPF); msnd_fifo_free(&dev.DARF); } -#endif + +module_init(msnd_init); +module_exit(msdn_cleanup); diff -uNr linux.orig/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c --- linux.orig/drivers/sound/sound_core.c Sat Sep 23 09:03:09 2000 +++ linux/drivers/sound/sound_core.c Mon Sep 25 19:54:26 2000 @@ -36,6 +36,7 @@ #include <linux/config.h> #include <linux/module.h> +#include <linux/init.h> #include <linux/malloc.h> #include <linux/types.h> #include <linux/kernel.h> @@ -62,9 +63,6 @@ #ifdef CONFIG_SOUND_MSNDPIN extern int msnd_pinnacle_init(void); #endif -#ifdef CONFIG_SOUND_CMPCI -extern int init_cmpci(void); -#endif /* * Low level list operator. Scan the ordered list, find a hole and @@ -545,12 +543,11 @@ extern int mod_firmware_load(const char *, char **); EXPORT_SYMBOL(mod_firmware_load); -#ifdef MODULE MODULE_DESCRIPTION("Core sound module"); MODULE_AUTHOR("Alan Cox"); -void cleanup_module(void) +static void __exit cleanup_soundcore(void) { /* We have nothing to really do here - we know the lists must be empty */ @@ -558,10 +555,7 @@ devfs_unregister (devfs_handle); } -int init_module(void) -#else -int soundcore_init(void) -#endif +static int __init init_soundcore(void) { if(devfs_register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) { @@ -569,20 +563,9 @@ return -EBUSY; } devfs_handle = devfs_mk_dir (NULL, "sound", NULL); - /* - * Now init non OSS drivers - */ -#ifdef CONFIG_SOUND_CMPCI - init_cmpci(); -#endif -#ifdef CONFIG_SOUND_MSNDCLAS - msnd_classic_init(); -#endif -#ifdef CONFIG_SOUND_MSNDPIN - msnd_pinnacle_init(); -#endif -#ifdef CONFIG_SOUND_VWSND - init_vwsnd(); -#endif + return 0; } + +module_init(init_soundcore); +module_exit(cleanup_soundcore); diff -uNr linux.orig/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- linux.orig/drivers/sound/soundcard.c Sat Sep 23 09:04:24 2000 +++ linux/drivers/sound/soundcard.c Mon Sep 25 20:04:17 2000 @@ -25,6 +25,7 @@ #include <linux/config.h> #include "sound_config.h" +#include <linux/init.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/signal.h> @@ -51,8 +52,6 @@ #define valid_dma(n) ((n) >= 0 && (n) < MAX_DMA_CHANNELS && (n) != 4) #endif -static int chrdev_registered = 0; - /* * Table for permanently allocated memory (used when unloading the module) */ @@ -583,34 +582,6 @@ } } -#ifdef MODULE -static void -#else -void -#endif -soundcard_init(void) -{ - /* drag in sound_syms.o */ - { - extern char sound_syms_symbol; - sound_syms_symbol = 0; - } - -#ifndef MODULE - create_special_devices(); - chrdev_registered = 1; -#endif - - soundcard_register_devfs(1); /* register after we know # of devices */ -} - -#ifdef MODULE - -static void destroy_special_devices(void) -{ - unregister_sound_special(1); - unregister_sound_special(8); -} static int dmabuf = 0; static int dmabug = 0; @@ -618,14 +589,21 @@ MODULE_PARM(dmabuf, "i"); MODULE_PARM(dmabug, "i"); -int init_module(void) +static int __init oss_init(void) { int err; + + /* drag in sound_syms.o */ + { + extern char sound_syms_symbol; + sound_syms_symbol = 0; + } #ifdef CONFIG_PCI if(dmabug) isa_dma_bridge_buggy = dmabug; #endif + err = create_special_devices(); if (err) { printk(KERN_ERR "sound: driver already loaded/included in kernel\n"); @@ -635,8 +613,7 @@ /* Protecting the innocent */ sound_dmap_flag = (dmabuf > 0 ? 1 : 0); - chrdev_registered = 1; - soundcard_init(); + soundcard_register_devfs(1); if (sound_nblocks >= 1024) printk(KERN_ERR "Sound warning: Deallocation table was too small.\n"); @@ -644,7 +621,7 @@ return 0; } -void cleanup_module(void) +static void __exit oss_cleanup(void) { int i; @@ -652,8 +629,9 @@ return; soundcard_register_devfs (0); - if (chrdev_registered) - destroy_special_devices(); + + unregister_sound_special(1); + unregister_sound_special(8); sound_stop_timer(); @@ -669,7 +647,10 @@ vfree(sound_mem_blocks[i]); } -#endif + +module_init(oss_init); +module_exit(oss_cleanup); + int sound_alloc_dma(int chn, char *deviceID) { diff -uNr linux.orig/drivers/sound/vwsnd.c linux/drivers/sound/vwsnd.c --- linux.orig/drivers/sound/vwsnd.c Sat Sep 23 09:03:10 2000 +++ linux/drivers/sound/vwsnd.c Mon Sep 25 19:54:26 2000 @@ -138,6 +138,8 @@ */ #include <linux/module.h> +#include <linux/init.h> + #include <linux/stddef.h> #include <linux/spinlock.h> #include <linux/smp_lock.h> @@ -3452,12 +3454,10 @@ CO_IRQ(CO_APIC_LI_AUDIO) /* irq */ }; -#ifdef MODULE - MODULE_DESCRIPTION("SGI Visual Workstation sound module"); MODULE_AUTHOR("Bob Miller <kbob@sgi.com>"); -extern int init_module(void) +static int __init init_vwsnd(void) { int err; @@ -3472,23 +3472,15 @@ return 0; } -extern void cleanup_module(void) +static void __exit cleanup_vwsnd(void) { DBGX("sound::vwsnd::cleanup_module()\n"); unload_vwsnd(&the_hw_config); } -#else - -extern void init_vwsnd(void) -{ - DBGX("sound::vwsnd::init_vwsnd()\n"); - if (probe_vwsnd(&the_hw_config)) - (void) attach_vwsnd(&the_hw_config); -} - -#endif /* !MODULE */ +module_init(init_vwsnd); +module_exit(cleanup_vwsnd); /* * Local variables:

diff -uNr linux.orig/drivers/sound/Config.in linux/drivers/sound/Config.in --- linux.orig/drivers/sound/Config.in Tue Sep 5 20:32:17 2000 +++ linux/drivers/sound/Config.in Mon Sep 25 15:11:35 2000 @@ -127,12 +127,6 @@ fi fi - dep_tristate ' SoftOSS software wave table engine' CONFIG_SOUND_SOFTOSS $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_SOFTOSS" = "y" ]; then - int 'Sampling rate for SoftOSS 8000 to 48000' CONFIG_SOFTOSS_RATE 22050 - int 'Max # of concurrent voices for SoftOSS 4 to 32' CONFIG_SOFTOSS_VOICES 32 - fi - dep_tristate ' 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SOUND_SB $CONFIG_SOUND_OSS dep_tristate ' AWE32 synth' CONFIG_SOUND_AWE32_SYNTH $CONFIG_SOUND_OSS dep_tristate ' Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards' CONFIG_SOUND_WAVEFRONT $CONFIG_SOUND_OSS m diff -uNr linux.orig/drivers/sound/Makefile linux/drivers/sound/Makefile --- linux.orig/drivers/sound/Makefile Tue Sep 5 20:32:17 2000 +++ linux/drivers/sound/Makefile Mon Sep 25 15:07:25 2000 @@ -43,7 +43,6 @@ obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o obj-$(CONFIG_SOUND_OPL3SA1) += opl3sa.o ad1848.o uart401.o -obj-$(CONFIG_SOUND_SOFTOSS) += softoss2.o obj-$(CONFIG_SOUND_SSCAPE) += sscape.o ad1848.o mpu401.o obj-$(CONFIG_SOUND_MAD16) += mad16.o ad1848.o sb_lib.o uart401.o obj-$(CONFIG_SOUND_CS4232) += cs4232.o uart401.o @@ -104,7 +103,7 @@ # Declare multi-part drivers. -list-multi := sound.o gus.o pas2.o sb.o sb_lib.o softoss2.o vidc_mod.o \ +list-multi := sound.o gus.o pas2.o sb.o sb_lib.o vidc_mod.o \ soundcore.o wavefront.o sound-objs := \ @@ -119,7 +118,6 @@ pas2-objs := pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o sb-objs := sb_card.o sb_lib-objs := sb_common.o sb_audio.o sb_midi.o sb_mixer.o sb_ess.o -softoss2-objs := softoss.o softoss_rs.o vidc_mod-objs := vidc.o vidc_fill.o wavefront-objs := wavfront.o wf_midi.o yss225.o @@ -180,9 +178,6 @@ sb_lib.o: $(sb_lib-objs) $(LD) -r -o $@ $(sb_lib-objs) - -softoss2.o: $(softoss2-objs) - $(LD) -r -o $@ $(softoss2-objs) vidc_mod.o: $(vidc_mod-objs) $(LD) -r -o $@ $(vidc_mod-objs) diff -uNr linux.orig/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c --- linux.orig/drivers/sound/dev_table.c Sun Sep 17 19:29:12 2000 +++ linux/drivers/sound/dev_table.c Mon Sep 25 15:09:13 2000 @@ -16,8 +16,6 @@ #define _DEV_TABLE_C_ #include "sound_config.h" -int softoss_dev = 0; - int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, int driver_size, int flags, unsigned int format_mask, void *devc, int dma1, int dma2) diff -uNr linux.orig/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c --- linux.orig/drivers/sound/sequencer.c Tue Sep 5 20:32:19 2000 +++ linux/drivers/sound/sequencer.c Mon Sep 25 15:10:33 2000 @@ -18,9 +18,6 @@ #define SEQUENCER_C #include "sound_config.h" -#include "softoss.h" - -int (*softsynthp) (int cmd, int parm1, int parm2, unsigned long parm3) = NULL; #include "midi_ctrl.h" @@ -170,10 +167,7 @@ if (data == 0xfe) /* Ignore active sensing */ return; - if (softsynthp != NULL) - tstamp = softsynthp(SSYN_GETTIME, 0, 0, 0); - else - tstamp = jiffies - seq_time; + tstamp = jiffies - seq_time; if (tstamp != prev_input_time) { @@ -195,8 +189,6 @@ if (seq_mode == SEQ_2) this_time = tmr->get_time(tmr_no); - else if (softsynthp != NULL) - this_time = softsynthp(SSYN_GETTIME, 0, 0, 0); else this_time = jiffies - seq_time; @@ -659,10 +651,7 @@ prev_event_time = time; seq_playing = 1; - if (softsynthp != NULL) - softsynthp(SSYN_REQUEST, time, 0, 0); - else - request_sound_timer(time); + request_sound_timer(time); if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) wake_up(&seq_sleeper); @@ -671,13 +660,7 @@ break; case TMR_START: - if (softsynthp != NULL) - { - softsynthp(SSYN_START, 0, 0, 0); - seq_time = 0; - } - else - seq_time = jiffies; + seq_time = jiffies; prev_input_time = 0; prev_event_time = 0; break; @@ -785,10 +768,7 @@ time = *delay; prev_event_time = time; - if (softsynthp != NULL) - softsynthp(SSYN_REQUEST, time, 0, 0); - else - request_sound_timer(time); + request_sound_timer(time); if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) wake_up(&seq_sleeper); @@ -809,14 +789,9 @@ case SEQ_SYNCTIMER: /* * Reset timer */ - if (softsynthp != NULL) - seq_time = 0; - else - seq_time = jiffies; + seq_time = jiffies; prev_input_time = 0; prev_event_time = 0; - if (softsynthp != NULL) - softsynthp(SSYN_START, 0, 0, 0); break; case SEQ_MIDIPUTC: /* @@ -838,10 +813,7 @@ */ seq_playing = 1; - if (softsynthp != NULL) - softsynthp(SSYN_REQUEST, -1, 0, 0); - else - request_sound_timer(-1); + request_sound_timer(-1); return 2; } else @@ -1085,15 +1057,10 @@ } } - if (softsynthp != NULL) - seq_time = 0; - else - seq_time = jiffies; + seq_time = jiffies; prev_input_time = 0; prev_event_time = 0; - if (softsynthp != NULL) - softsynthp(SSYN_START, 0, 0, 0); if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE)) { @@ -1280,10 +1247,7 @@ int chn; unsigned long flags; - if (softsynthp != NULL) - softsynthp(SSYN_STOP, 0, 0, 0); - else - sound_stop_timer(); + sound_stop_timer(); seq_time = jiffies; prev_input_time = 0; @@ -1449,10 +1413,7 @@ case SNDCTL_SEQ_GETTIME: if (seq_mode == SEQ_2) return tmr->ioctl(tmr_no, cmd, arg); - if (softsynthp != NULL) - val = softsynthp(SSYN_GETTIME, 0, 0, 0); - else - val = jiffies - seq_time; + val = jiffies - seq_time; break; case SNDCTL_SEQ_CTRLRATE: diff -uNr linux.orig/drivers/sound/sequencer_syms.c linux/drivers/sound/sequencer_syms.c --- linux.orig/drivers/sound/sequencer_syms.c Tue Sep 5 19:27:24 2000 +++ linux/drivers/sound/sequencer_syms.c Mon Sep 25 15:11:04 2000 @@ -23,10 +23,6 @@ EXPORT_SYMBOL(sound_timer_syncinterval); EXPORT_SYMBOL(reprogram_timer); -#include "softoss.h" - -EXPORT_SYMBOL(softsynthp); - /* Tuning */ #define _SEQUENCER_C_ diff -uNr linux.orig/drivers/sound/softoss.c linux/drivers/sound/softoss.c --- linux.orig/drivers/sound/softoss.c Sat Sep 23 09:04:24 2000 +++ linux/drivers/sound/softoss.c Thu Jan 1 01:00:00 1970 @@ -1,1535 +0,0 @@ -/* - * sound/softoss.c - * - * Software based MIDI synthsesizer driver. - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * Christoph Hellwig : adapted to module_init/module_exit - */ - -#include <linux/config.h> -#include <linux/init.h> -#include <linux/module.h> - -/* - * When POLLED_MODE is defined, the resampling loop is run using a timer - * callback routine. Normally the resampling loop is executed inside - * audio buffer interrupt handler which doesn't work with single mode DMA. - */ -#define SOFTSYN_MAIN -#undef POLLED_MODE -#define HANDLE_LFO - -#define ENVELOPE_SCALE 8 -#define NO_SAMPLE 0xffff - -#include "sound_config.h" -#include "softoss.h" -#include <linux/ultrasound.h> - -int softsynth_disabled = 0; - -static volatile int intr_pending = 0; - -#ifdef POLLED_MODE - -static struct timer_list poll_timer = { - NULL, NULL, 0, 0, softsyn_poll -}; - -#else -#endif - -#ifdef HANDLE_LFO -/* - * LFO table. Playback at 128 Hz gives 1 Hz LFO frequency. - */ -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 -}; - -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 -}; - -#endif - -static unsigned long last_resample_jiffies; -static unsigned long resample_counter; - -extern int *sound_osp; - -static volatile int is_running = 0; -static int softsynth_loaded = 0; - -static struct synth_info softsyn_info = { - "SoftOSS", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH -}; - -static struct softsyn_devc sdev_info = { - 0 -}; - -softsyn_devc *devc = &sdev_info; /* used in softoss_rs.c */ - -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 volatile int tmr_running = 0; -static int voice_limit = 24; - - -static void set_max_voices(int nr) -{ - int i; - - if (nr < 4) - nr = 4; - - if (nr > voice_limit) - nr = voice_limit; - - 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; - } -} - -static void update_vibrato(int voice) -{ - voice_info *v = &softoss_voices[voice]; - -#ifdef HANDLE_LFO - int x; - - 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; - - compute_step(voice); -#else - v->vibrato_level = 0; -#endif -} - -#ifdef HANDLE_LFO -static void update_tremolo(int voice) -{ - 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; - - v->tremolo_level = (x * v->tremolo_depth) >> 20; -} -#endif - -static void start_vibrato(int voice) -{ - voice_info *v = &softoss_voices[voice]; - int rate; - - if (!v->vibrato_depth) - return; - - rate = v->vibrato_rate * 6 * 128; - v->vibrato_step = (rate * devc->control_rate) / devc->speed; - - devc->vibratomap |= (1 << voice); /* Enable vibrato */ -} - -static void start_tremolo(int voice) -{ - voice_info *v = &softoss_voices[voice]; - int rate; - - if (!v->tremolo_depth) - return; - - rate = v->tremolo_rate * 6 * 128; - v->tremolo_step = (rate * devc->control_rate) / devc->speed; - - devc->tremolomap |= (1 << voice); /* Enable tremolo */ -} - -static void update_volume(int voice) -{ - voice_info *v = &softoss_voices[voice]; - unsigned int vol; - - /* - * Compute plain volume - */ - - 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); - } -#endif - /* - * Envelope - */ - - 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; - restore_flags(flags); -} - -static void step_envelope_lfo(int voice) -{ - voice_info *v = &softoss_voices[voice]; - - /* - * Update pitch (vibrato) LFO - */ - - 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; - } - 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; -} - -void softsyn_control_loop(void) -{ - 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(KERN_WARNING "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(KERN_WARNING "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(KERN_WARNING "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(KERN_WARNING "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; - } - } - - /* - * 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 */ - - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - dmap->qlen++; - dmap->user_counter += dmap->fragment_size; - - 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); -} - -static void delayed_resample(int dummy) -{ - struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out; - int n = 0; - - if (is_running) - return; - - 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) -{ - delayed_resample(0); - - if (devc->engine_state != ES_STOPPED) - { - poll_timer.expires = jiffies+1; - add_timer(&poll_timer); - } -} - -#else -static void softsyn_callback(int dev, int parm) -{ - delayed_resample(0); -} -#endif - -static void start_engine(softsyn_devc * devc) -{ - struct dma_buffparms *dmap; - int trig, n; - mm_segment_t fs; - - if (!devc->audio_opened) - if (softsyn_open(devc->synthdev, 0) < 0) - return; - - if (devc->audiodev >= num_audiodevs) - return; - - dmap = audio_devs[devc->audiodev]->dmap_out; - - devc->usecs = 0; - devc->next_event_usecs = ~0; - devc->control_rate = 64; - devc->control_counter = 0; - - if (devc->engine_state == ES_STOPPED) - { - n = trig = 0; - fs = get_fs(); - set_fs(get_ds()); - dma_ioctl(devc->audiodev, SNDCTL_DSP_SETTRIGGER, (caddr_t)&trig); -#ifdef POLLED_MODE - poll_timer.expires = jiffies+1; - add_timer(&poll_timer); - /* Start polling */ -#else - dmap->audio_callback = softsyn_callback; - dmap->qhead = dmap->qtail = dmap->qlen = 0; -#endif - while (dmap->qlen < devc->max_playahead && n++ < 2) - do_resample(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(KERN_ERR "SoftOSS: Trigger failed\n"); - set_fs(fs); - } -} - -static void stop_engine(softsyn_devc * devc) -{ -} - -static void 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); -} - -/* - * Softsync hook serves mode1 (timing) calls made by sequencer.c - */ - -static int 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(KERN_WARNING "SoftOSS: Unknown request %d\n", cmd); - } - return 0; -} - -static int softsyn_ioctl(int dev, unsigned int cmd, caddr_t arg) -{ - switch (cmd) - { - case SNDCTL_SYNTH_INFO: - softsyn_info.nr_voices = devc->maxvoice; - if (copy_to_user(arg, &softsyn_info, sizeof(softsyn_info))) - return -EFAULT; - return 0; - - case SNDCTL_SEQ_RESETSAMPLES: - stop_engine(devc); - reset_samples(devc); - return 0; - - case SNDCTL_SYNTH_MEMAVL: - return devc->ram_size - devc->ram_used; - - default: - return -EINVAL; - } -} - -static int 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; -} - -static int softsyn_set_instr(int dev, int voice, int instr) -{ - if (voice < 0 || voice > devc->maxvoice) - return 0; - - if (instr < 0 || instr > MAX_PATCH) - { - printk(KERN_ERR "SoftOSS: Invalid instrument number %d\n", instr); - return 0; - } - softoss_voices[voice].instr = instr; - return 0; -} - -static int 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(KERN_WARNING "SoftOSS: Undefined MIDI instrument %d\n", instr); - restore_flags(flags); - return 0; - } - instr = devc->programs[instr]; - - if (instr < 0 || instr >= devc->nrsamples) - { - printk(KERN_WARNING "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(KERN_WARNING "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 */ - restore_flags(flags); - return 0; -} - -static int softsyn_open(int synthdev, int mode) -{ - int err; - extern int softoss_dev; - int frags = 0x7fff0007; /* fragment size of 128 bytes */ - mm_segment_t fs; - - if (devc->audio_opened) /* Already opened */ - return 0; - - softsynth_disabled = 0; - devc->finfo.f_mode = FMODE_WRITE; - devc->finfo.f_flags = 0; - - 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 (!(audio_devs[devc->audiodev]->format_mask & AFMT_S16_LE)) - { -/* printk(KERN_ERR "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); - - - DDB(printk("SoftOSS: Using audio dev %d, speed %d, bits %d, channels %d\n", devc->audiodev, devc->speed, devc->bits, devc->channels)); - fs = get_fs(); - set_fs(get_ds()); - dma_ioctl(devc->audiodev, SNDCTL_DSP_SETFRAGMENT, (caddr_t) & frags); - dma_ioctl(devc->audiodev, SNDCTL_DSP_GETBLKSIZE, (caddr_t) & devc->fragsize); - set_fs(fs); - - if (devc->bits != 16 || devc->channels != 2) - { - audio_release((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo); -/* printk("SoftOSS: A 16 bit stereo sound card is required\n");*/ - return -EINVAL; - } - 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)); - - init_engine(devc); - devc->audio_opened = 1; - devc->sequencer_mode = mode; - return 0; -} - -static void softsyn_close(int synthdev) -{ - mm_segment_t fs; - - devc->engine_state = ES_STOPPED; -#ifdef POLLED_MODE - del_timer(&poll_timer); -#endif - fs = get_fs(); - set_fs(get_ds()); - dma_ioctl(devc->audiodev, SNDCTL_DSP_RESET, 0); - set_fs(fs); - 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) -{ - 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]; - - switch (cmd) - { - - case _GUS_NUMVOICES: - set_max_voices(p1); - break; - - default:; - } -} - -static int 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(KERN_ERR "SoftOSS: Invalid patch format (key) 0x%x\n", format);*/ - return -EINVAL; - } - if (count < sizeof_patch) - { -/* printk(KERN_ERR "SoftOSS: Patch header too short\n");*/ - return -EINVAL; - } - count -= sizeof_patch; - - if (devc->nrsamples >= MAX_SAMPLE) - { -/* printk(KERN_ERR "SoftOSS: Sample table full\n");*/ - return -ENOBUFS; - } - - /* - * Copy the header from user space but ignore the first bytes which have - * been transferred already. - */ - - patch = vmalloc(sizeof(*patch)); - - if (patch == NULL) - { -/* printk(KERN_ERR "SoftOSS: Out of memory\n");*/ - return -ENOMEM; - } - if(copy_from_user(&((char *) patch)[offs], &(addr)[offs], sizeof_patch - offs)) - { - vfree(patch); - return -EFAULT; - } - - if (patch->mode & WAVE_ROM) - { - vfree(patch); - return -EINVAL; - } - instr = patch->instr_no; - - if (instr < 0 || instr > MAX_PATCH) - { -/* printk(KERN_ERR "SoftOSS: Invalid patch number %d\n", instr);*/ - vfree(patch); - return -EINVAL; - } - if (count < patch->len) - { -/* printk(KERN_ERR "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(KERN_ERR "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(KERN_ERR "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(KERN_ERR "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; - - if (!(patch->mode & WAVE_16_BITS)) - memlen *= 2; - else - adj = 2; - - wave = vmalloc(memlen); - - if (wave == NULL) - { -/* printk(KERN_ERR "SoftOSS: Can't allocate %d bytes of mem for a sample\n", memlen);*/ - vfree(patch); - return -ENOMEM; - } - 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; - } - - devc->ram_used += patch->len; - - /* - * Convert pointers to 16 bit indexes - */ - 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; - - return 0; -} - -static void softsyn_panning(int dev, int voice, int pan) -{ - if (voice < 0 || voice > devc->maxvoice) - return; - - if (pan < -128) - pan = -128; - if (pan > 127) - pan = 127; - - softoss_voices[voice].panning = pan; - if (voice_active[voice]) - update_volume(voice); -} - -static void softsyn_volume_method(int dev, int mode) -{ -} - -static void softsyn_aftertouch(int dev, int voice, int pressure) -{ - if (voice < 0 || voice > devc->maxvoice) - return; - - if (voice_active[voice]) - update_volume(voice); -} - -static void softsyn_controller(int dev, int voice, int ctrl_num, int value) -{ - unsigned long flags; - - if (voice < 0 || voice > devc->maxvoice) - return; - save_flags(flags); - cli(); - - switch (ctrl_num) - { - case CTRL_PITCH_BENDER: - softoss_voices[voice].bender = value; - 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 CTL_PAN: - softsyn_panning(dev, voice, (value * 2) - 128); - break; - - 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; - - default: - break; - } - restore_flags(flags); -} - -static void softsyn_bender(int dev, int voice, int value) -{ - if (voice < 0 || voice > devc->maxvoice) - return; - - 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) -{ - 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); -} - -static struct synth_operations softsyn_operations = -{ - owner: THIS_MODULE, - id: "SoftOSS", - info: &softsyn_info, - midi_dev: 0, - synth_type: SYNTH_TYPE_SAMPLE, - synth_subtype: 0, - open: softsyn_open, - close: softsyn_close, - ioctl: softsyn_ioctl, - kill_note: softsyn_kill_note, - start_note: softsyn_start_note, - set_instr: softsyn_set_instr, - reset: softsyn_reset, - hw_control: softsyn_hw_control, - load_patch: softsyn_load_patch, - aftertouch: softsyn_aftertouch, - controller: softsyn_controller, - panning: softsyn_panning, - volume_method: softsyn_volume_method, - bender: softsyn_bender, - alloc_voice: softsyn_alloc_voice, - setup_voice: softsyn_setup_voice -}; - -/* - * Timer stuff (for /dev/music). - */ - -static unsigned int soft_tmr_start(int dev, unsigned int usecs) -{ - tmr_running = 1; - start_engine(devc); - return devc->usecs_per_frag; -} - -static void soft_tmr_disable(int dev) -{ - stop_engine(devc); - tmr_running = 0; -} - -static void soft_tmr_restart(int dev) -{ - tmr_running = 1; -} - -static struct sound_lowlev_timer soft_tmr = -{ - 0, - 9999, - soft_tmr_start, - soft_tmr_disable, - soft_tmr_restart -}; - -static int __init probe_softsyn(struct address_info *hw_config) -{ - int i; - - 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; - -#ifdef CONFIG_SOFTOSS_RATE - devc->speed = CONFIG_SOFTOSS_RATE; -#else - devc->speed = 32000; -#endif - -#ifdef CONFIG_SOFTOSS_VOICES - devc->default_max_voices = CONFIG_SOFTOSS_VOICES; -#else - devc->default_max_voices = 32; -#endif - softsynth_loaded = 1; - return 1; -} - -static void __init attach_softsyn_card(struct address_info *hw_config) -{ - 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 -} - -static void __exit unload_softsyn(struct address_info *hw_config) -{ - if (!softsynth_loaded) - return; - softsynthp = NULL; - softsynth_loaded = 0; - reset_samples(devc); -} - -static struct address_info cfg; - -static int __init init_softoss(void) -{ - printk(KERN_INFO "SoftOSS driver Copyright (C) by Hannu Savolainen 1993-1997\n"); - if (!probe_softsyn(&cfg)) - return -ENODEV; - attach_softsyn_card(&cfg); - - return 0; -} - -static void __exit cleanup_softoss(void) -{ - unload_softsyn(&cfg); - sound_unload_synthdev(devc->synthdev); - sound_unload_timerdev(devc->timerdev); -} - -module_init(init_softoss); -module_exit(cleanup_softoss); diff -uNr linux.orig/drivers/sound/softoss.h linux/drivers/sound/softoss.h --- linux.orig/drivers/sound/softoss.h Thu Feb 19 23:46:15 1998 +++ linux/drivers/sound/softoss.h Thu Jan 1 01:00:00 1970 @@ -1,161 +0,0 @@ -/* - * softoss.h - Definitions for Software MIDI Synthesizer. - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ - - -/* - * Sequencer mode1 timer calls made by sequencer.c - */ -extern int (*softsynthp) (int cmd, int parm1, int parm2, unsigned long parm3); - -#define SSYN_START 1 -#define SSYN_REQUEST 2 /* parm1 = time */ -#define SSYN_STOP 3 -#define SSYN_GETTIME 4 /* Returns number of ticks since reset */ - -#define MAX_PATCH 256 -#define MAX_SAMPLE 512 -#define MAX_VOICE 32 -#define DEFAULT_VOICES 16 - -typedef struct voice_info -{ -/* - * Don't change anything in the beginning of this struct. These fields are used - * by the resampling loop which may have been written in assembly for some - * architectures. Any change may make the resampling code incompatible - */ - int instr; - short *wave; - struct patch_info *sample; - - unsigned int ptr; int step; /* Pointer to the wave data and pointer increment */ - - int mode; - int startloop, startbackloop, endloop, looplen; - - unsigned int leftvol, rightvol; -/***** Don't change anything above this */ - - volatile unsigned long orig_freq, current_freq; - volatile int bender, bender_range, panning; - volatile int main_vol, expression_vol, patch_vol, velocity; - -/* Envelope parameters */ - - int envelope_phase; - volatile int envelope_vol; - volatile int envelope_volstep; - int envelope_time; /* Number of remaining envelope steps */ - unsigned int envelope_target; - int percussive_voice; - int sustain_mode; /* 0=off, 1=sustain on, 2=sustain on+key released */ - -/* Vibrato */ - int vibrato_rate; - int vibrato_depth; - int vibrato_phase; - int vibrato_step; - int vibrato_level; - -/* Tremolo */ - int tremolo_rate; - int tremolo_depth; - int tremolo_phase; - int tremolo_step; - int tremolo_level; -} voice_info; - -extern voice_info softoss_voices[MAX_VOICE]; /* Voice spesific info */ - -typedef struct softsyn_devc -{ -/* - * Don't change anything in the beginning of this struct. These fields are used - * by the resampling loop which may have been written in assembly for some - * architectures. Any change may make the resampling code incompatible - */ - int maxvoice; /* # of voices to be processed */ - int afterscale; - int delay_size; - int control_rate, control_counter; -/***** Don't change anything above this */ - - int ram_size; - int ram_used; - - int synthdev; - int timerdev; - int sequencer_mode; -/* - * Audio parameters - */ - - int audiodev; - int audio_opened; - int speed; - int channels; - int bits; - int default_max_voices; - int max_playahead; - struct file finfo; - int fragsize; - int samples_per_fragment; - -/* - * Sample storage - */ - int nrsamples; - struct patch_info *samples[MAX_SAMPLE]; - short *wave[MAX_SAMPLE]; - -/* - * Programs - */ - int programs[MAX_PATCH]; - -/* - * Timer parameters - */ - volatile unsigned long usecs; - volatile unsigned long usecs_per_frag; - volatile unsigned long next_event_usecs; - -/* - * Engine state - */ - - volatile int engine_state; -#define ES_STOPPED 0 -#define ES_STARTED 1 - - /* Voice spesific bitmaps */ - volatile int tremolomap; - volatile int vibratomap; - -} softsyn_devc; - -void softsynth_resample_loop(short *buf, int loops); -extern void softsyn_control_loop(void); - -#define DELAY_SIZE 4096 - -#ifdef SOFTSYN_MAIN - short voice_active[MAX_VOICE] = {0}; - voice_info softoss_voices[MAX_VOICE] = {{0}}; /* Voice spesific info */ - int left_delay[DELAY_SIZE]={0}, right_delay[DELAY_SIZE]={0}; - int delayp=0; -#else - extern softsyn_devc *devc; - - extern int left_delay[DELAY_SIZE], right_delay[DELAY_SIZE]; - extern int delayp; - extern short voice_active[MAX_VOICE]; -#endif diff -uNr linux.orig/drivers/sound/softoss_rs.c linux/drivers/sound/softoss_rs.c --- linux.orig/drivers/sound/softoss_rs.c Tue Sep 5 19:27:37 2000 +++ linux/drivers/sound/softoss_rs.c Thu Jan 1 01:00:00 1970 @@ -1,127 +0,0 @@ - -/* - * sound/softoss_rs.c - * - * Software based MIDI synthsesizer driver, the actual mixing loop. - * Keep the loop as simple as possible to make it easier to rewrite this - * routine in assembly. - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ -#include "sound_config.h" -#include "softoss.h" - -void softsynth_resample_loop(short *buf, int loops) -{ - int iloop, voice; - volatile voice_info *v; - -#ifdef OSS_BIG_ENDIAN - unsigned char *cbuf = (unsigned char *) buf; - -#endif - - for (iloop = 0; iloop < loops; iloop++) - { /* Mix one sample */ - int accum, left = 0, right = 0; - int ix, position; - - for (voice = 0; voice < devc->maxvoice; voice++) - { - if (voice_active[voice]) - { /* Compute voice */ - v = &softoss_voices[voice]; -#ifdef SOFTOSS_TEST - ix = iloop << 3; - position = v->ptr; -#else - ix = (position = v->ptr) >> 9; -#endif - /* Interpolation (resolution of 512 steps) */ - { - int fract = v->ptr & 0x1ff; /* 9 bits */ - - /* This method works with less arithmetic operations */ - register int v1 = v->wave[ix]; - accum = v1 + ((((v->wave[ix + 1] - v1)) * (fract)) >> 9); - } - - left += (accum * v->leftvol); - right += (accum * v->rightvol); - - /* Update sample pointer */ - position += v->step; - if (position <= v->endloop) - v->ptr = position; - else if (v->mode & WAVE_LOOPING) - { - if (v->mode & WAVE_BIDIR_LOOP) - { v->mode ^= WAVE_LOOP_BACK; /* Turn around */ - v->step *= -1; - } - else - { - position -= v->looplen; - v->ptr = position; - } - } - /* else leave the voice looping the current sample */ - - if (v->mode & WAVE_LOOP_BACK && position < v->startloop) - { - if (v->mode & WAVE_BIDIR_LOOP) - { v->mode ^= WAVE_LOOP_BACK; /* Turn around */ - v->step *= -1; - } - else - { - position += v->looplen; - v->ptr = position; - } - } - } /* Compute voice */ - } -#if 1 /* Delay */ - left += left_delay[delayp]; - right += right_delay[delayp]; - - left_delay[delayp] = right >> 2; - right_delay[delayp] = left >> 2; - delayp = (delayp + 1) % devc->delay_size; -#endif - -#define AFTERSCALE devc->afterscale; - - left >>= AFTERSCALE; - right >>= AFTERSCALE; - - if (left > 32767) - left = 32767; - if (left < -32768) - left = -32768; - if (right > 32767) - right = 32767; - if (right < -32768) - right = -32768; - -#ifdef OSS_BIG_ENDIAN - *cbuf++ = left & 0xff; - *cbuf++ = (left >> 8) & 0xff; - *cbuf++ = right & 0xff; - *cbuf++ = (right >> 8) & 0xff; -#else - *buf++ = left; - *buf++ = right; -#endif - if (devc->control_counter++ >= devc->control_rate) - { - devc->control_counter = 0; - softsyn_control_loop(); - } - } /* Mix one sample */ -} diff -uNr linux.orig/drivers/sound/sound_syms.c linux/drivers/sound/sound_syms.c --- linux.orig/drivers/sound/sound_syms.c Tue Sep 5 20:32:19 2000 +++ linux/drivers/sound/sound_syms.c Mon Sep 25 15:11:15 2000 @@ -49,8 +49,5 @@ EXPORT_SYMBOL(conf_printf); EXPORT_SYMBOL(conf_printf2); -extern int softoss_dev; -EXPORT_SYMBOL(softoss_dev); - MODULE_DESCRIPTION("OSS Sound subsystem"); MODULE_AUTHOR("Hannu Savolainen, et al."); diff -uNr linux.orig/drivers/sound/vidc.c linux/drivers/sound/vidc.c --- linux.orig/drivers/sound/vidc.c Sat Sep 23 09:04:24 2000 +++ linux/drivers/sound/vidc.c Mon Sep 25 15:08:12 2000 @@ -83,7 +83,6 @@ static void (*old_mksound)(unsigned int hz, unsigned int ticks); extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); extern void vidc_update_filler(int bits, int channels); -extern int softoss_dev; static void vidc_mksound(unsigned int hz, unsigned int ticks) @@ -475,9 +474,6 @@ vidc_adev = adev; vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8)); -#if defined(CONFIG_SOUND_SOFTOSS) || defined(CONFIG_SOUND_SOFTOSS_MODULE) - softoss_dev = adev; -#endif return; irq_failed: - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Sep 30 2000 - 21:00:16 EST