diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/sound/synth/emux | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/sound/synth/emux')
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/Makefile | 12 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/emux.c | 192 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/emux_effect.c | 310 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/emux_hwdep.c | 153 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/emux_nrpn.c | 396 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/emux_oss.c | 517 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/emux_proc.c | 132 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/emux_seq.c | 403 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/emux_synth.c | 984 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/emux_voice.h | 96 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/synth/emux/soundfont.c | 1496 |
11 files changed, 0 insertions, 4691 deletions
diff --git a/ANDROID_3.4.5/sound/synth/emux/Makefile b/ANDROID_3.4.5/sound/synth/emux/Makefile deleted file mode 100644 index 328594e6..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \ - emux_effect.o emux_proc.o emux_hwdep.o soundfont.o \ - $(if $(CONFIG_SND_SEQUENCER_OSS),emux_oss.o) - -# Toplevel Module Dependencies -obj-$(CONFIG_SND_SBAWE_SEQ) += snd-emux-synth.o -obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-emux-synth.o diff --git a/ANDROID_3.4.5/sound/synth/emux/emux.c b/ANDROID_3.4.5/sound/synth/emux/emux.c deleted file mode 100644 index 93522072..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/emux.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de> - * - * Routines for control of EMU WaveTable chip - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/wait.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <sound/core.h> -#include <sound/emux_synth.h> -#include <linux/init.h> -#include <linux/module.h> -#include "emux_voice.h" - -MODULE_AUTHOR("Takashi Iwai"); -MODULE_DESCRIPTION("Routines for control of EMU WaveTable chip"); -MODULE_LICENSE("GPL"); - -/* - * create a new hardware dependent device for Emu8000/Emu10k1 - */ -int snd_emux_new(struct snd_emux **remu) -{ - struct snd_emux *emu; - - *remu = NULL; - emu = kzalloc(sizeof(*emu), GFP_KERNEL); - if (emu == NULL) - return -ENOMEM; - - spin_lock_init(&emu->voice_lock); - mutex_init(&emu->register_mutex); - - emu->client = -1; -#ifdef CONFIG_SND_SEQUENCER_OSS - emu->oss_synth = NULL; -#endif - emu->max_voices = 0; - emu->use_time = 0; - - init_timer(&emu->tlist); - emu->tlist.function = snd_emux_timer_callback; - emu->tlist.data = (unsigned long)emu; - emu->timer_active = 0; - - *remu = emu; - return 0; -} - -EXPORT_SYMBOL(snd_emux_new); - -/* - */ -static int sf_sample_new(void *private_data, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr, - const void __user *buf, long count) -{ - struct snd_emux *emu = private_data; - return emu->ops.sample_new(emu, sp, hdr, buf, count); - -} - -static int sf_sample_free(void *private_data, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr) -{ - struct snd_emux *emu = private_data; - return emu->ops.sample_free(emu, sp, hdr); - -} - -static void sf_sample_reset(void *private_data) -{ - struct snd_emux *emu = private_data; - emu->ops.sample_reset(emu); -} - -int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, char *name) -{ - int err; - struct snd_sf_callback sf_cb; - - if (snd_BUG_ON(!emu->hw || emu->max_voices <= 0)) - return -EINVAL; - if (snd_BUG_ON(!card || !name)) - return -EINVAL; - - emu->card = card; - emu->name = kstrdup(name, GFP_KERNEL); - emu->voices = kcalloc(emu->max_voices, sizeof(struct snd_emux_voice), - GFP_KERNEL); - if (emu->voices == NULL) - return -ENOMEM; - - /* create soundfont list */ - memset(&sf_cb, 0, sizeof(sf_cb)); - sf_cb.private_data = emu; - if (emu->ops.sample_new) - sf_cb.sample_new = sf_sample_new; - if (emu->ops.sample_free) - sf_cb.sample_free = sf_sample_free; - if (emu->ops.sample_reset) - sf_cb.sample_reset = sf_sample_reset; - emu->sflist = snd_sf_new(&sf_cb, emu->memhdr); - if (emu->sflist == NULL) - return -ENOMEM; - - if ((err = snd_emux_init_hwdep(emu)) < 0) - return err; - - snd_emux_init_voices(emu); - - snd_emux_init_seq(emu, card, index); -#ifdef CONFIG_SND_SEQUENCER_OSS - snd_emux_init_seq_oss(emu); -#endif - snd_emux_init_virmidi(emu, card); - -#ifdef CONFIG_PROC_FS - snd_emux_proc_init(emu, card, index); -#endif - return 0; -} - -EXPORT_SYMBOL(snd_emux_register); - -/* - */ -int snd_emux_free(struct snd_emux *emu) -{ - unsigned long flags; - - if (! emu) - return -EINVAL; - - spin_lock_irqsave(&emu->voice_lock, flags); - if (emu->timer_active) - del_timer(&emu->tlist); - spin_unlock_irqrestore(&emu->voice_lock, flags); - -#ifdef CONFIG_PROC_FS - snd_emux_proc_free(emu); -#endif - snd_emux_delete_virmidi(emu); -#ifdef CONFIG_SND_SEQUENCER_OSS - snd_emux_detach_seq_oss(emu); -#endif - snd_emux_detach_seq(emu); - - snd_emux_delete_hwdep(emu); - - if (emu->sflist) - snd_sf_free(emu->sflist); - - kfree(emu->voices); - kfree(emu->name); - kfree(emu); - return 0; -} - -EXPORT_SYMBOL(snd_emux_free); - - -/* - * INIT part - */ - -static int __init alsa_emux_init(void) -{ - return 0; -} - -static void __exit alsa_emux_exit(void) -{ -} - -module_init(alsa_emux_init) -module_exit(alsa_emux_exit) diff --git a/ANDROID_3.4.5/sound/synth/emux/emux_effect.c b/ANDROID_3.4.5/sound/synth/emux/emux_effect.c deleted file mode 100644 index a447218b..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/emux_effect.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Midi synth routines for the Emu8k/Emu10k1 - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de> - * - * Contains code based on awe_wave.c by Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "emux_voice.h" -#include <linux/slab.h> - -#ifdef SNDRV_EMUX_USE_RAW_EFFECT -/* - * effects table - */ - -#define xoffsetof(type,tag) ((long)(&((type)NULL)->tag) - (long)(NULL)) - -#define parm_offset(tag) xoffsetof(struct soundfont_voice_parm *, tag) - -#define PARM_IS_BYTE (1 << 0) -#define PARM_IS_WORD (1 << 1) -#define PARM_IS_ALIGNED (3 << 2) -#define PARM_IS_ALIGN_HI (1 << 2) -#define PARM_IS_ALIGN_LO (2 << 2) -#define PARM_IS_SIGNED (1 << 4) - -#define PARM_WORD (PARM_IS_WORD) -#define PARM_BYTE_LO (PARM_IS_BYTE|PARM_IS_ALIGN_LO) -#define PARM_BYTE_HI (PARM_IS_BYTE|PARM_IS_ALIGN_HI) -#define PARM_BYTE (PARM_IS_BYTE) -#define PARM_SIGN_LO (PARM_IS_BYTE|PARM_IS_ALIGN_LO|PARM_IS_SIGNED) -#define PARM_SIGN_HI (PARM_IS_BYTE|PARM_IS_ALIGN_HI|PARM_IS_SIGNED) - -static struct emux_parm_defs { - int type; /* byte or word */ - int low, high; /* value range */ - long offset; /* offset in parameter record (-1 = not written) */ - int update; /* flgas for real-time update */ -} parm_defs[EMUX_NUM_EFFECTS] = { - {PARM_WORD, 0, 0x8000, parm_offset(moddelay), 0}, /* env1 delay */ - {PARM_BYTE_LO, 1, 0x80, parm_offset(modatkhld), 0}, /* env1 attack */ - {PARM_BYTE_HI, 0, 0x7e, parm_offset(modatkhld), 0}, /* env1 hold */ - {PARM_BYTE_LO, 1, 0x7f, parm_offset(moddcysus), 0}, /* env1 decay */ - {PARM_BYTE_LO, 1, 0x7f, parm_offset(modrelease), 0}, /* env1 release */ - {PARM_BYTE_HI, 0, 0x7f, parm_offset(moddcysus), 0}, /* env1 sustain */ - {PARM_BYTE_HI, 0, 0xff, parm_offset(pefe), 0}, /* env1 pitch */ - {PARM_BYTE_LO, 0, 0xff, parm_offset(pefe), 0}, /* env1 fc */ - - {PARM_WORD, 0, 0x8000, parm_offset(voldelay), 0}, /* env2 delay */ - {PARM_BYTE_LO, 1, 0x80, parm_offset(volatkhld), 0}, /* env2 attack */ - {PARM_BYTE_HI, 0, 0x7e, parm_offset(volatkhld), 0}, /* env2 hold */ - {PARM_BYTE_LO, 1, 0x7f, parm_offset(voldcysus), 0}, /* env2 decay */ - {PARM_BYTE_LO, 1, 0x7f, parm_offset(volrelease), 0}, /* env2 release */ - {PARM_BYTE_HI, 0, 0x7f, parm_offset(voldcysus), 0}, /* env2 sustain */ - - {PARM_WORD, 0, 0x8000, parm_offset(lfo1delay), 0}, /* lfo1 delay */ - {PARM_BYTE_LO, 0, 0xff, parm_offset(tremfrq), SNDRV_EMUX_UPDATE_TREMFREQ}, /* lfo1 freq */ - {PARM_SIGN_HI, -128, 127, parm_offset(tremfrq), SNDRV_EMUX_UPDATE_TREMFREQ}, /* lfo1 vol */ - {PARM_SIGN_HI, -128, 127, parm_offset(fmmod), SNDRV_EMUX_UPDATE_FMMOD}, /* lfo1 pitch */ - {PARM_BYTE_LO, 0, 0xff, parm_offset(fmmod), SNDRV_EMUX_UPDATE_FMMOD}, /* lfo1 cutoff */ - - {PARM_WORD, 0, 0x8000, parm_offset(lfo2delay), 0}, /* lfo2 delay */ - {PARM_BYTE_LO, 0, 0xff, parm_offset(fm2frq2), SNDRV_EMUX_UPDATE_FM2FRQ2}, /* lfo2 freq */ - {PARM_SIGN_HI, -128, 127, parm_offset(fm2frq2), SNDRV_EMUX_UPDATE_FM2FRQ2}, /* lfo2 pitch */ - - {PARM_WORD, 0, 0xffff, -1, SNDRV_EMUX_UPDATE_PITCH}, /* initial pitch */ - {PARM_BYTE, 0, 0xff, parm_offset(chorus), 0}, /* chorus */ - {PARM_BYTE, 0, 0xff, parm_offset(reverb), 0}, /* reverb */ - {PARM_BYTE, 0, 0xff, parm_offset(cutoff), SNDRV_EMUX_UPDATE_VOLUME}, /* cutoff */ - {PARM_BYTE, 0, 15, parm_offset(filterQ), SNDRV_EMUX_UPDATE_Q}, /* resonance */ - - {PARM_WORD, 0, 0xffff, -1, 0}, /* sample start */ - {PARM_WORD, 0, 0xffff, -1, 0}, /* loop start */ - {PARM_WORD, 0, 0xffff, -1, 0}, /* loop end */ - {PARM_WORD, 0, 0xffff, -1, 0}, /* coarse sample start */ - {PARM_WORD, 0, 0xffff, -1, 0}, /* coarse loop start */ - {PARM_WORD, 0, 0xffff, -1, 0}, /* coarse loop end */ - {PARM_BYTE, 0, 0xff, -1, SNDRV_EMUX_UPDATE_VOLUME}, /* initial attenuation */ -}; - -/* set byte effect value */ -static void -effect_set_byte(unsigned char *valp, struct snd_midi_channel *chan, int type) -{ - short effect; - struct snd_emux_effect_table *fx = chan->private; - - effect = fx->val[type]; - if (fx->flag[type] == EMUX_FX_FLAG_ADD) { - if (parm_defs[type].type & PARM_IS_SIGNED) - effect += *(char*)valp; - else - effect += *valp; - } - if (effect < parm_defs[type].low) - effect = parm_defs[type].low; - else if (effect > parm_defs[type].high) - effect = parm_defs[type].high; - *valp = (unsigned char)effect; -} - -/* set word effect value */ -static void -effect_set_word(unsigned short *valp, struct snd_midi_channel *chan, int type) -{ - int effect; - struct snd_emux_effect_table *fx = chan->private; - - effect = *(unsigned short*)&fx->val[type]; - if (fx->flag[type] == EMUX_FX_FLAG_ADD) - effect += *valp; - if (effect < parm_defs[type].low) - effect = parm_defs[type].low; - else if (effect > parm_defs[type].high) - effect = parm_defs[type].high; - *valp = (unsigned short)effect; -} - -/* address offset */ -static int -effect_get_offset(struct snd_midi_channel *chan, int lo, int hi, int mode) -{ - int addr = 0; - struct snd_emux_effect_table *fx = chan->private; - - if (fx->flag[hi]) - addr = (short)fx->val[hi]; - addr = addr << 15; - if (fx->flag[lo]) - addr += (short)fx->val[lo]; - if (!(mode & SNDRV_SFNT_SAMPLE_8BITS)) - addr /= 2; - return addr; -} - -#ifdef CONFIG_SND_SEQUENCER_OSS -/* change effects - for OSS sequencer compatibility */ -void -snd_emux_send_effect_oss(struct snd_emux_port *port, - struct snd_midi_channel *chan, int type, int val) -{ - int mode; - - if (type & 0x40) - mode = EMUX_FX_FLAG_OFF; - else if (type & 0x80) - mode = EMUX_FX_FLAG_ADD; - else - mode = EMUX_FX_FLAG_SET; - type &= 0x3f; - - snd_emux_send_effect(port, chan, type, val, mode); -} -#endif - -/* Modify the effect value. - * if update is necessary, call emu8000_control - */ -void -snd_emux_send_effect(struct snd_emux_port *port, struct snd_midi_channel *chan, - int type, int val, int mode) -{ - int i; - int offset; - unsigned char *srcp, *origp; - struct snd_emux *emu; - struct snd_emux_effect_table *fx; - unsigned long flags; - - emu = port->emu; - fx = chan->private; - if (emu == NULL || fx == NULL) - return; - if (type < 0 || type >= EMUX_NUM_EFFECTS) - return; - - fx->val[type] = val; - fx->flag[type] = mode; - - /* do we need to modify the register in realtime ? */ - if (! parm_defs[type].update || (offset = parm_defs[type].offset) < 0) - return; - -#ifdef SNDRV_LITTLE_ENDIAN - if (parm_defs[type].type & PARM_IS_ALIGN_HI) - offset++; -#else - if (parm_defs[type].type & PARM_IS_ALIGN_LO) - offset++; -#endif - /* modify the register values */ - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < emu->max_voices; i++) { - struct snd_emux_voice *vp = &emu->voices[i]; - if (!STATE_IS_PLAYING(vp->state) || vp->chan != chan) - continue; - srcp = (unsigned char*)&vp->reg.parm + offset; - origp = (unsigned char*)&vp->zone->v.parm + offset; - if (parm_defs[i].type & PARM_IS_BYTE) { - *srcp = *origp; - effect_set_byte(srcp, chan, type); - } else { - *(unsigned short*)srcp = *(unsigned short*)origp; - effect_set_word((unsigned short*)srcp, chan, type); - } - } - spin_unlock_irqrestore(&emu->voice_lock, flags); - - /* activate them */ - snd_emux_update_channel(port, chan, parm_defs[type].update); -} - - -/* copy wavetable registers to voice table */ -void -snd_emux_setup_effect(struct snd_emux_voice *vp) -{ - struct snd_midi_channel *chan = vp->chan; - struct snd_emux_effect_table *fx; - unsigned char *srcp; - int i; - - if (! (fx = chan->private)) - return; - - /* modify the register values via effect table */ - for (i = 0; i < EMUX_FX_END; i++) { - int offset; - if (! fx->flag[i] || (offset = parm_defs[i].offset) < 0) - continue; -#ifdef SNDRV_LITTLE_ENDIAN - if (parm_defs[i].type & PARM_IS_ALIGN_HI) - offset++; -#else - if (parm_defs[i].type & PARM_IS_ALIGN_LO) - offset++; -#endif - srcp = (unsigned char*)&vp->reg.parm + offset; - if (parm_defs[i].type & PARM_IS_BYTE) - effect_set_byte(srcp, chan, i); - else - effect_set_word((unsigned short*)srcp, chan, i); - } - - /* correct sample and loop points */ - vp->reg.start += effect_get_offset(chan, EMUX_FX_SAMPLE_START, - EMUX_FX_COARSE_SAMPLE_START, - vp->reg.sample_mode); - - vp->reg.loopstart += effect_get_offset(chan, EMUX_FX_LOOP_START, - EMUX_FX_COARSE_LOOP_START, - vp->reg.sample_mode); - - vp->reg.loopend += effect_get_offset(chan, EMUX_FX_LOOP_END, - EMUX_FX_COARSE_LOOP_END, - vp->reg.sample_mode); -} - -/* - * effect table - */ -void -snd_emux_create_effect(struct snd_emux_port *p) -{ - int i; - p->effect = kcalloc(p->chset.max_channels, - sizeof(struct snd_emux_effect_table), GFP_KERNEL); - if (p->effect) { - for (i = 0; i < p->chset.max_channels; i++) - p->chset.channels[i].private = p->effect + i; - } else { - for (i = 0; i < p->chset.max_channels; i++) - p->chset.channels[i].private = NULL; - } -} - -void -snd_emux_delete_effect(struct snd_emux_port *p) -{ - kfree(p->effect); - p->effect = NULL; -} - -void -snd_emux_clear_effect(struct snd_emux_port *p) -{ - if (p->effect) { - memset(p->effect, 0, sizeof(struct snd_emux_effect_table) * - p->chset.max_channels); - } -} - -#endif /* SNDRV_EMUX_USE_RAW_EFFECT */ diff --git a/ANDROID_3.4.5/sound/synth/emux/emux_hwdep.c b/ANDROID_3.4.5/sound/synth/emux/emux_hwdep.c deleted file mode 100644 index 5ae1eae9..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/emux_hwdep.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Interface for hwdep device - * - * Copyright (C) 2004 Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <sound/core.h> -#include <sound/hwdep.h> -#include <asm/uaccess.h> -#include "emux_voice.h" - - -#define TMP_CLIENT_ID 0x1001 - -/* - * load patch - */ -static int -snd_emux_hwdep_load_patch(struct snd_emux *emu, void __user *arg) -{ - int err; - struct soundfont_patch_info patch; - - if (copy_from_user(&patch, arg, sizeof(patch))) - return -EFAULT; - - if (patch.type >= SNDRV_SFNT_LOAD_INFO && - patch.type <= SNDRV_SFNT_PROBE_DATA) { - err = snd_soundfont_load(emu->sflist, arg, patch.len + sizeof(patch), TMP_CLIENT_ID); - if (err < 0) - return err; - } else { - if (emu->ops.load_fx) - return emu->ops.load_fx(emu, patch.type, patch.optarg, arg, patch.len + sizeof(patch)); - else - return -EINVAL; - } - return 0; -} - -/* - * set misc mode - */ -static int -snd_emux_hwdep_misc_mode(struct snd_emux *emu, void __user *arg) -{ - struct snd_emux_misc_mode info; - int i; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - if (info.mode < 0 || info.mode >= EMUX_MD_END) - return -EINVAL; - - if (info.port < 0) { - for (i = 0; i < emu->num_ports; i++) - emu->portptrs[i]->ctrls[info.mode] = info.value; - } else { - if (info.port < emu->num_ports) - emu->portptrs[info.port]->ctrls[info.mode] = info.value; - } - return 0; -} - - -/* - * ioctl - */ -static int -snd_emux_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct snd_emux *emu = hw->private_data; - - switch (cmd) { - case SNDRV_EMUX_IOCTL_VERSION: - return put_user(SNDRV_EMUX_VERSION, (unsigned int __user *)arg); - case SNDRV_EMUX_IOCTL_LOAD_PATCH: - return snd_emux_hwdep_load_patch(emu, (void __user *)arg); - case SNDRV_EMUX_IOCTL_RESET_SAMPLES: - snd_soundfont_remove_samples(emu->sflist); - break; - case SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES: - snd_soundfont_remove_unlocked(emu->sflist); - break; - case SNDRV_EMUX_IOCTL_MEM_AVAIL: - if (emu->memhdr) { - int size = snd_util_mem_avail(emu->memhdr); - return put_user(size, (unsigned int __user *)arg); - } - break; - case SNDRV_EMUX_IOCTL_MISC_MODE: - return snd_emux_hwdep_misc_mode(emu, (void __user *)arg); - } - - return 0; -} - - -/* - * register hwdep device - */ - -int -snd_emux_init_hwdep(struct snd_emux *emu) -{ - struct snd_hwdep *hw; - int err; - - if ((err = snd_hwdep_new(emu->card, SNDRV_EMUX_HWDEP_NAME, emu->hwdep_idx, &hw)) < 0) - return err; - emu->hwdep = hw; - strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME); - hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE; - hw->ops.ioctl = snd_emux_hwdep_ioctl; - /* The ioctl parameter types are compatible between 32- and - * 64-bit architectures, so use the same function. */ - hw->ops.ioctl_compat = snd_emux_hwdep_ioctl; - hw->exclusive = 1; - hw->private_data = emu; - if ((err = snd_card_register(emu->card)) < 0) - return err; - - return 0; -} - - -/* - * unregister - */ -void -snd_emux_delete_hwdep(struct snd_emux *emu) -{ - if (emu->hwdep) { - snd_device_free(emu->card, emu->hwdep); - emu->hwdep = NULL; - } -} diff --git a/ANDROID_3.4.5/sound/synth/emux/emux_nrpn.c b/ANDROID_3.4.5/sound/synth/emux/emux_nrpn.c deleted file mode 100644 index 00fc005e..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/emux_nrpn.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * NRPN / SYSEX callbacks for Emu8k/Emu10k1 - * - * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "emux_voice.h" -#include <sound/asoundef.h> - -/* - * conversion from NRPN/control parameters to Emu8000 raw parameters - */ - -/* NRPN / CC -> Emu8000 parameter converter */ -struct nrpn_conv_table { - int control; - int effect; - int (*convert)(int val); -}; - -/* effect sensitivity */ - -#define FX_CUTOFF 0 -#define FX_RESONANCE 1 -#define FX_ATTACK 2 -#define FX_RELEASE 3 -#define FX_VIBRATE 4 -#define FX_VIBDEPTH 5 -#define FX_VIBDELAY 6 -#define FX_NUMS 7 - -/* - * convert NRPN/control values - */ - -static int send_converted_effect(struct nrpn_conv_table *table, int num_tables, - struct snd_emux_port *port, - struct snd_midi_channel *chan, - int type, int val, int mode) -{ - int i, cval; - for (i = 0; i < num_tables; i++) { - if (table[i].control == type) { - cval = table[i].convert(val); - snd_emux_send_effect(port, chan, table[i].effect, - cval, mode); - return 1; - } - } - return 0; -} - -#define DEF_FX_CUTOFF 170 -#define DEF_FX_RESONANCE 6 -#define DEF_FX_ATTACK 50 -#define DEF_FX_RELEASE 50 -#define DEF_FX_VIBRATE 30 -#define DEF_FX_VIBDEPTH 4 -#define DEF_FX_VIBDELAY 1500 - -/* effect sensitivities for GS NRPN: - * adjusted for chaos 8MB soundfonts - */ -static int gs_sense[] = -{ - DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE, - DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY -}; - -/* effect sensitivies for XG controls: - * adjusted for chaos 8MB soundfonts - */ -static int xg_sense[] = -{ - DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE, - DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY -}; - - -/* - * AWE32 NRPN effects - */ - -static int fx_delay(int val); -static int fx_attack(int val); -static int fx_hold(int val); -static int fx_decay(int val); -static int fx_the_value(int val); -static int fx_twice_value(int val); -static int fx_conv_pitch(int val); -static int fx_conv_Q(int val); - -/* function for each NRPN */ /* [range] units */ -#define fx_env1_delay fx_delay /* [0,5900] 4msec */ -#define fx_env1_attack fx_attack /* [0,5940] 1msec */ -#define fx_env1_hold fx_hold /* [0,8191] 1msec */ -#define fx_env1_decay fx_decay /* [0,5940] 4msec */ -#define fx_env1_release fx_decay /* [0,5940] 4msec */ -#define fx_env1_sustain fx_the_value /* [0,127] 0.75dB */ -#define fx_env1_pitch fx_the_value /* [-127,127] 9.375cents */ -#define fx_env1_cutoff fx_the_value /* [-127,127] 56.25cents */ - -#define fx_env2_delay fx_delay /* [0,5900] 4msec */ -#define fx_env2_attack fx_attack /* [0,5940] 1msec */ -#define fx_env2_hold fx_hold /* [0,8191] 1msec */ -#define fx_env2_decay fx_decay /* [0,5940] 4msec */ -#define fx_env2_release fx_decay /* [0,5940] 4msec */ -#define fx_env2_sustain fx_the_value /* [0,127] 0.75dB */ - -#define fx_lfo1_delay fx_delay /* [0,5900] 4msec */ -#define fx_lfo1_freq fx_twice_value /* [0,127] 84mHz */ -#define fx_lfo1_volume fx_twice_value /* [0,127] 0.1875dB */ -#define fx_lfo1_pitch fx_the_value /* [-127,127] 9.375cents */ -#define fx_lfo1_cutoff fx_twice_value /* [-64,63] 56.25cents */ - -#define fx_lfo2_delay fx_delay /* [0,5900] 4msec */ -#define fx_lfo2_freq fx_twice_value /* [0,127] 84mHz */ -#define fx_lfo2_pitch fx_the_value /* [-127,127] 9.375cents */ - -#define fx_init_pitch fx_conv_pitch /* [-8192,8192] cents */ -#define fx_chorus fx_the_value /* [0,255] -- */ -#define fx_reverb fx_the_value /* [0,255] -- */ -#define fx_cutoff fx_twice_value /* [0,127] 62Hz */ -#define fx_filterQ fx_conv_Q /* [0,127] -- */ - -static int fx_delay(int val) -{ - return (unsigned short)snd_sf_calc_parm_delay(val); -} - -static int fx_attack(int val) -{ - return (unsigned short)snd_sf_calc_parm_attack(val); -} - -static int fx_hold(int val) -{ - return (unsigned short)snd_sf_calc_parm_hold(val); -} - -static int fx_decay(int val) -{ - return (unsigned short)snd_sf_calc_parm_decay(val); -} - -static int fx_the_value(int val) -{ - return (unsigned short)(val & 0xff); -} - -static int fx_twice_value(int val) -{ - return (unsigned short)((val * 2) & 0xff); -} - -static int fx_conv_pitch(int val) -{ - return (short)(val * 4096 / 1200); -} - -static int fx_conv_Q(int val) -{ - return (unsigned short)((val / 8) & 0xff); -} - - -static struct nrpn_conv_table awe_effects[] = -{ - { 0, EMUX_FX_LFO1_DELAY, fx_lfo1_delay}, - { 1, EMUX_FX_LFO1_FREQ, fx_lfo1_freq}, - { 2, EMUX_FX_LFO2_DELAY, fx_lfo2_delay}, - { 3, EMUX_FX_LFO2_FREQ, fx_lfo2_freq}, - - { 4, EMUX_FX_ENV1_DELAY, fx_env1_delay}, - { 5, EMUX_FX_ENV1_ATTACK,fx_env1_attack}, - { 6, EMUX_FX_ENV1_HOLD, fx_env1_hold}, - { 7, EMUX_FX_ENV1_DECAY, fx_env1_decay}, - { 8, EMUX_FX_ENV1_SUSTAIN, fx_env1_sustain}, - { 9, EMUX_FX_ENV1_RELEASE, fx_env1_release}, - - {10, EMUX_FX_ENV2_DELAY, fx_env2_delay}, - {11, EMUX_FX_ENV2_ATTACK, fx_env2_attack}, - {12, EMUX_FX_ENV2_HOLD, fx_env2_hold}, - {13, EMUX_FX_ENV2_DECAY, fx_env2_decay}, - {14, EMUX_FX_ENV2_SUSTAIN, fx_env2_sustain}, - {15, EMUX_FX_ENV2_RELEASE, fx_env2_release}, - - {16, EMUX_FX_INIT_PITCH, fx_init_pitch}, - {17, EMUX_FX_LFO1_PITCH, fx_lfo1_pitch}, - {18, EMUX_FX_LFO2_PITCH, fx_lfo2_pitch}, - {19, EMUX_FX_ENV1_PITCH, fx_env1_pitch}, - {20, EMUX_FX_LFO1_VOLUME, fx_lfo1_volume}, - {21, EMUX_FX_CUTOFF, fx_cutoff}, - {22, EMUX_FX_FILTERQ, fx_filterQ}, - {23, EMUX_FX_LFO1_CUTOFF, fx_lfo1_cutoff}, - {24, EMUX_FX_ENV1_CUTOFF, fx_env1_cutoff}, - {25, EMUX_FX_CHORUS, fx_chorus}, - {26, EMUX_FX_REVERB, fx_reverb}, -}; - - -/* - * GS(SC88) NRPN effects; still experimental - */ - -/* cutoff: quarter semitone step, max=255 */ -static int gs_cutoff(int val) -{ - return (val - 64) * gs_sense[FX_CUTOFF] / 50; -} - -/* resonance: 0 to 15(max) */ -static int gs_filterQ(int val) -{ - return (val - 64) * gs_sense[FX_RESONANCE] / 50; -} - -/* attack: */ -static int gs_attack(int val) -{ - return -(val - 64) * gs_sense[FX_ATTACK] / 50; -} - -/* decay: */ -static int gs_decay(int val) -{ - return -(val - 64) * gs_sense[FX_RELEASE] / 50; -} - -/* release: */ -static int gs_release(int val) -{ - return -(val - 64) * gs_sense[FX_RELEASE] / 50; -} - -/* vibrato freq: 0.042Hz step, max=255 */ -static int gs_vib_rate(int val) -{ - return (val - 64) * gs_sense[FX_VIBRATE] / 50; -} - -/* vibrato depth: max=127, 1 octave */ -static int gs_vib_depth(int val) -{ - return (val - 64) * gs_sense[FX_VIBDEPTH] / 50; -} - -/* vibrato delay: -0.725msec step */ -static int gs_vib_delay(int val) -{ - return -(val - 64) * gs_sense[FX_VIBDELAY] / 50; -} - -static struct nrpn_conv_table gs_effects[] = -{ - {32, EMUX_FX_CUTOFF, gs_cutoff}, - {33, EMUX_FX_FILTERQ, gs_filterQ}, - {99, EMUX_FX_ENV2_ATTACK, gs_attack}, - {100, EMUX_FX_ENV2_DECAY, gs_decay}, - {102, EMUX_FX_ENV2_RELEASE, gs_release}, - {8, EMUX_FX_LFO1_FREQ, gs_vib_rate}, - {9, EMUX_FX_LFO1_VOLUME, gs_vib_depth}, - {10, EMUX_FX_LFO1_DELAY, gs_vib_delay}, -}; - - -/* - * NRPN events - */ -void -snd_emux_nrpn(void *p, struct snd_midi_channel *chan, - struct snd_midi_channel_set *chset) -{ - struct snd_emux_port *port; - - port = p; - if (snd_BUG_ON(!port || !chan)) - return; - - if (chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] == 127 && - chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB] <= 26) { - int val; - /* Win/DOS AWE32 specific NRPNs */ - /* both MSB/LSB necessary */ - val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) | - chan->control[MIDI_CTL_LSB_DATA_ENTRY]; - val -= 8192; - send_converted_effect - (awe_effects, ARRAY_SIZE(awe_effects), - port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB], - val, EMUX_FX_FLAG_SET); - return; - } - - if (port->chset.midi_mode == SNDRV_MIDI_MODE_GS && - chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] == 1) { - int val; - /* GS specific NRPNs */ - /* only MSB is valid */ - val = chan->control[MIDI_CTL_MSB_DATA_ENTRY]; - send_converted_effect - (gs_effects, ARRAY_SIZE(gs_effects), - port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB], - val, EMUX_FX_FLAG_ADD); - return; - } -} - - -/* - * XG control effects; still experimental - */ - -/* cutoff: quarter semitone step, max=255 */ -static int xg_cutoff(int val) -{ - return (val - 64) * xg_sense[FX_CUTOFF] / 64; -} - -/* resonance: 0(open) to 15(most nasal) */ -static int xg_filterQ(int val) -{ - return (val - 64) * xg_sense[FX_RESONANCE] / 64; -} - -/* attack: */ -static int xg_attack(int val) -{ - return -(val - 64) * xg_sense[FX_ATTACK] / 64; -} - -/* release: */ -static int xg_release(int val) -{ - return -(val - 64) * xg_sense[FX_RELEASE] / 64; -} - -static struct nrpn_conv_table xg_effects[] = -{ - {71, EMUX_FX_CUTOFF, xg_cutoff}, - {74, EMUX_FX_FILTERQ, xg_filterQ}, - {72, EMUX_FX_ENV2_RELEASE, xg_release}, - {73, EMUX_FX_ENV2_ATTACK, xg_attack}, -}; - -int -snd_emux_xg_control(struct snd_emux_port *port, struct snd_midi_channel *chan, - int param) -{ - return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects), - port, chan, param, - chan->control[param], - EMUX_FX_FLAG_ADD); -} - -/* - * receive sysex - */ -void -snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed, - struct snd_midi_channel_set *chset) -{ - struct snd_emux_port *port; - struct snd_emux *emu; - - port = p; - if (snd_BUG_ON(!port || !chset)) - return; - emu = port->emu; - - switch (parsed) { - case SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME: - snd_emux_update_port(port, SNDRV_EMUX_UPDATE_VOLUME); - break; - default: - if (emu->ops.sysex) - emu->ops.sysex(emu, buf, len, parsed, chset); - break; - } -} - diff --git a/ANDROID_3.4.5/sound/synth/emux/emux_oss.c b/ANDROID_3.4.5/sound/synth/emux/emux_oss.c deleted file mode 100644 index 319754cf..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/emux_oss.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Interface for OSS sequencer emulation - * - * Copyright (C) 1999 Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Changes - * 19990227 Steve Ratcliffe Made separate file and merged in latest - * midi emulation. - */ - - -#ifdef CONFIG_SND_SEQUENCER_OSS - -#include <linux/export.h> -#include <asm/uaccess.h> -#include <sound/core.h> -#include "emux_voice.h" -#include <sound/asoundef.h> - -static int snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure); -static int snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg); -static int snd_emux_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, - unsigned long ioarg); -static int snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, - const char __user *buf, int offs, int count); -static int snd_emux_reset_seq_oss(struct snd_seq_oss_arg *arg); -static int snd_emux_event_oss_input(struct snd_seq_event *ev, int direct, - void *private, int atomic, int hop); -static void reset_port_mode(struct snd_emux_port *port, int midi_mode); -static void emuspec_control(struct snd_emux *emu, struct snd_emux_port *port, - int cmd, unsigned char *event, int atomic, int hop); -static void gusspec_control(struct snd_emux *emu, struct snd_emux_port *port, - int cmd, unsigned char *event, int atomic, int hop); -static void fake_event(struct snd_emux *emu, struct snd_emux_port *port, - int ch, int param, int val, int atomic, int hop); - -/* operators */ -static struct snd_seq_oss_callback oss_callback = { - .owner = THIS_MODULE, - .open = snd_emux_open_seq_oss, - .close = snd_emux_close_seq_oss, - .ioctl = snd_emux_ioctl_seq_oss, - .load_patch = snd_emux_load_patch_seq_oss, - .reset = snd_emux_reset_seq_oss, -}; - - -/* - * register OSS synth - */ - -void -snd_emux_init_seq_oss(struct snd_emux *emu) -{ - struct snd_seq_oss_reg *arg; - struct snd_seq_device *dev; - - if (snd_seq_device_new(emu->card, 0, SNDRV_SEQ_DEV_ID_OSS, - sizeof(struct snd_seq_oss_reg), &dev) < 0) - return; - - emu->oss_synth = dev; - strcpy(dev->name, emu->name); - arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); - arg->type = SYNTH_TYPE_SAMPLE; - arg->subtype = SAMPLE_TYPE_AWE32; - arg->nvoices = emu->max_voices; - arg->oper = oss_callback; - arg->private_data = emu; - - /* register to OSS synth table */ - snd_device_register(emu->card, dev); -} - - -/* - * unregister - */ -void -snd_emux_detach_seq_oss(struct snd_emux *emu) -{ - if (emu->oss_synth) { - snd_device_free(emu->card, emu->oss_synth); - emu->oss_synth = NULL; - } -} - - -/* use port number as a unique soundfont client number */ -#define SF_CLIENT_NO(p) ((p) + 0x1000) - -/* - * open port for OSS sequencer - */ -static int -snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) -{ - struct snd_emux *emu; - struct snd_emux_port *p; - struct snd_seq_port_callback callback; - char tmpname[64]; - - emu = closure; - if (snd_BUG_ON(!arg || !emu)) - return -ENXIO; - - mutex_lock(&emu->register_mutex); - - if (!snd_emux_inc_count(emu)) { - mutex_unlock(&emu->register_mutex); - return -EFAULT; - } - - memset(&callback, 0, sizeof(callback)); - callback.owner = THIS_MODULE; - callback.event_input = snd_emux_event_oss_input; - - sprintf(tmpname, "%s OSS Port", emu->name); - p = snd_emux_create_port(emu, tmpname, 32, - 1, &callback); - if (p == NULL) { - snd_printk(KERN_ERR "can't create port\n"); - snd_emux_dec_count(emu); - mutex_unlock(&emu->register_mutex); - return -ENOMEM; - } - - /* fill the argument data */ - arg->private_data = p; - arg->addr.client = p->chset.client; - arg->addr.port = p->chset.port; - p->oss_arg = arg; - - reset_port_mode(p, arg->seq_mode); - - snd_emux_reset_port(p); - - mutex_unlock(&emu->register_mutex); - return 0; -} - - -#define DEFAULT_DRUM_FLAGS ((1<<9) | (1<<25)) - -/* - * reset port mode - */ -static void -reset_port_mode(struct snd_emux_port *port, int midi_mode) -{ - if (midi_mode) { - port->port_mode = SNDRV_EMUX_PORT_MODE_OSS_MIDI; - port->drum_flags = DEFAULT_DRUM_FLAGS; - port->volume_atten = 0; - port->oss_arg->event_passing = SNDRV_SEQ_OSS_PROCESS_KEYPRESS; - } else { - port->port_mode = SNDRV_EMUX_PORT_MODE_OSS_SYNTH; - port->drum_flags = 0; - port->volume_atten = 32; - port->oss_arg->event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS; - } -} - - -/* - * close port - */ -static int -snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg) -{ - struct snd_emux *emu; - struct snd_emux_port *p; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - p = arg->private_data; - if (snd_BUG_ON(!p)) - return -ENXIO; - - emu = p->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - - mutex_lock(&emu->register_mutex); - snd_emux_sounds_off_all(p); - snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port)); - snd_seq_event_port_detach(p->chset.client, p->chset.port); - snd_emux_dec_count(emu); - - mutex_unlock(&emu->register_mutex); - return 0; -} - - -/* - * load patch - */ -static int -snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, - const char __user *buf, int offs, int count) -{ - struct snd_emux *emu; - struct snd_emux_port *p; - int rc; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - p = arg->private_data; - if (snd_BUG_ON(!p)) - return -ENXIO; - - emu = p->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - - if (format == GUS_PATCH) - rc = snd_soundfont_load_guspatch(emu->sflist, buf, count, - SF_CLIENT_NO(p->chset.port)); - else if (format == SNDRV_OSS_SOUNDFONT_PATCH) { - struct soundfont_patch_info patch; - if (count < (int)sizeof(patch)) - rc = -EINVAL; - if (copy_from_user(&patch, buf, sizeof(patch))) - rc = -EFAULT; - if (patch.type >= SNDRV_SFNT_LOAD_INFO && - patch.type <= SNDRV_SFNT_PROBE_DATA) - rc = snd_soundfont_load(emu->sflist, buf, count, SF_CLIENT_NO(p->chset.port)); - else { - if (emu->ops.load_fx) - rc = emu->ops.load_fx(emu, patch.type, patch.optarg, buf, count); - else - rc = -EINVAL; - } - } else - rc = 0; - return rc; -} - - -/* - * ioctl - */ -static int -snd_emux_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned long ioarg) -{ - struct snd_emux_port *p; - struct snd_emux *emu; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - p = arg->private_data; - if (snd_BUG_ON(!p)) - return -ENXIO; - - emu = p->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - - switch (cmd) { - case SNDCTL_SEQ_RESETSAMPLES: - snd_soundfont_remove_samples(emu->sflist); - return 0; - - case SNDCTL_SYNTH_MEMAVL: - if (emu->memhdr) - return snd_util_mem_avail(emu->memhdr); - return 0; - } - - return 0; -} - - -/* - * reset device - */ -static int -snd_emux_reset_seq_oss(struct snd_seq_oss_arg *arg) -{ - struct snd_emux_port *p; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - p = arg->private_data; - if (snd_BUG_ON(!p)) - return -ENXIO; - snd_emux_reset_port(p); - return 0; -} - - -/* - * receive raw events: only SEQ_PRIVATE is accepted. - */ -static int -snd_emux_event_oss_input(struct snd_seq_event *ev, int direct, void *private_data, - int atomic, int hop) -{ - struct snd_emux *emu; - struct snd_emux_port *p; - unsigned char cmd, *data; - - p = private_data; - if (snd_BUG_ON(!p)) - return -EINVAL; - emu = p->emu; - if (snd_BUG_ON(!emu)) - return -EINVAL; - if (ev->type != SNDRV_SEQ_EVENT_OSS) - return snd_emux_event_input(ev, direct, private_data, atomic, hop); - - data = ev->data.raw8.d; - /* only SEQ_PRIVATE is accepted */ - if (data[0] != 0xfe) - return 0; - cmd = data[2] & _EMUX_OSS_MODE_VALUE_MASK; - if (data[2] & _EMUX_OSS_MODE_FLAG) - emuspec_control(emu, p, cmd, data, atomic, hop); - else - gusspec_control(emu, p, cmd, data, atomic, hop); - return 0; -} - - -/* - * OSS/AWE driver specific h/w controls - */ -static void -emuspec_control(struct snd_emux *emu, struct snd_emux_port *port, int cmd, - unsigned char *event, int atomic, int hop) -{ - int voice; - unsigned short p1; - short p2; - int i; - struct snd_midi_channel *chan; - - voice = event[3]; - if (voice < 0 || voice >= port->chset.max_channels) - chan = NULL; - else - chan = &port->chset.channels[voice]; - - p1 = *(unsigned short *) &event[4]; - p2 = *(short *) &event[6]; - - switch (cmd) { -#if 0 /* don't do this atomically */ - case _EMUX_OSS_REMOVE_LAST_SAMPLES: - snd_soundfont_remove_unlocked(emu->sflist); - break; -#endif - case _EMUX_OSS_SEND_EFFECT: - if (chan) - snd_emux_send_effect_oss(port, chan, p1, p2); - break; - - case _EMUX_OSS_TERMINATE_ALL: - snd_emux_terminate_all(emu); - break; - - case _EMUX_OSS_TERMINATE_CHANNEL: - /*snd_emux_mute_channel(emu, chan);*/ - break; - case _EMUX_OSS_RESET_CHANNEL: - /*snd_emux_channel_init(chset, chan);*/ - break; - - case _EMUX_OSS_RELEASE_ALL: - fake_event(emu, port, voice, MIDI_CTL_ALL_NOTES_OFF, 0, atomic, hop); - break; - case _EMUX_OSS_NOTEOFF_ALL: - fake_event(emu, port, voice, MIDI_CTL_ALL_SOUNDS_OFF, 0, atomic, hop); - break; - - case _EMUX_OSS_INITIAL_VOLUME: - if (p2) { - port->volume_atten = (short)p1; - snd_emux_update_port(port, SNDRV_EMUX_UPDATE_VOLUME); - } - break; - - case _EMUX_OSS_CHN_PRESSURE: - if (chan) { - chan->midi_pressure = p1; - snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_FMMOD|SNDRV_EMUX_UPDATE_FM2FRQ2); - } - break; - - case _EMUX_OSS_CHANNEL_MODE: - reset_port_mode(port, p1); - snd_emux_reset_port(port); - break; - - case _EMUX_OSS_DRUM_CHANNELS: - port->drum_flags = *(unsigned int*)&event[4]; - for (i = 0; i < port->chset.max_channels; i++) { - chan = &port->chset.channels[i]; - chan->drum_channel = ((port->drum_flags >> i) & 1) ? 1 : 0; - } - break; - - case _EMUX_OSS_MISC_MODE: - if (p1 < EMUX_MD_END) - port->ctrls[p1] = p2; - break; - case _EMUX_OSS_DEBUG_MODE: - break; - - default: - if (emu->ops.oss_ioctl) - emu->ops.oss_ioctl(emu, cmd, p1, p2); - break; - } -} - -/* - * GUS specific h/w controls - */ - -#include <linux/ultrasound.h> - -static void -gusspec_control(struct snd_emux *emu, struct snd_emux_port *port, int cmd, - unsigned char *event, int atomic, int hop) -{ - int voice; - unsigned short p1; - short p2; - int plong; - struct snd_midi_channel *chan; - - if (port->port_mode != SNDRV_EMUX_PORT_MODE_OSS_SYNTH) - return; - if (cmd == _GUS_NUMVOICES) - return; - voice = event[3]; - if (voice < 0 || voice >= port->chset.max_channels) - return; - - chan = &port->chset.channels[voice]; - - p1 = *(unsigned short *) &event[4]; - p2 = *(short *) &event[6]; - plong = *(int*) &event[4]; - - switch (cmd) { - case _GUS_VOICESAMPLE: - chan->midi_program = p1; - return; - - case _GUS_VOICEBALA: - /* 0 to 15 --> 0 to 127 */ - chan->control[MIDI_CTL_MSB_PAN] = (int)p1 << 3; - snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN); - return; - - case _GUS_VOICEVOL: - case _GUS_VOICEVOL2: - /* not supported yet */ - return; - - case _GUS_RAMPRANGE: - case _GUS_RAMPRATE: - case _GUS_RAMPMODE: - case _GUS_RAMPON: - case _GUS_RAMPOFF: - /* volume ramping not supported */ - return; - - case _GUS_VOLUME_SCALE: - return; - - case _GUS_VOICE_POS: -#ifdef SNDRV_EMUX_USE_RAW_EFFECT - snd_emux_send_effect(port, chan, EMUX_FX_SAMPLE_START, - (short)(plong & 0x7fff), - EMUX_FX_FLAG_SET); - snd_emux_send_effect(port, chan, EMUX_FX_COARSE_SAMPLE_START, - (plong >> 15) & 0xffff, - EMUX_FX_FLAG_SET); -#endif - return; - } -} - - -/* - * send an event to midi emulation - */ -static void -fake_event(struct snd_emux *emu, struct snd_emux_port *port, int ch, int param, int val, int atomic, int hop) -{ - struct snd_seq_event ev; - memset(&ev, 0, sizeof(ev)); - ev.type = SNDRV_SEQ_EVENT_CONTROLLER; - ev.data.control.channel = ch; - ev.data.control.param = param; - ev.data.control.value = val; - snd_emux_event_input(&ev, 0, port, atomic, hop); -} - -#endif /* CONFIG_SND_SEQUENCER_OSS */ diff --git a/ANDROID_3.4.5/sound/synth/emux/emux_proc.c b/ANDROID_3.4.5/sound/synth/emux/emux_proc.c deleted file mode 100644 index 58a32a10..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/emux_proc.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de> - * - * Proc interface for Emu8k/Emu10k1 WaveTable synth - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/wait.h> -#include <sound/core.h> -#include <sound/emux_synth.h> -#include <sound/info.h> -#include "emux_voice.h" - -#ifdef CONFIG_PROC_FS - -static void -snd_emux_proc_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buf) -{ - struct snd_emux *emu; - int i; - - emu = entry->private_data; - mutex_lock(&emu->register_mutex); - if (emu->name) - snd_iprintf(buf, "Device: %s\n", emu->name); - snd_iprintf(buf, "Ports: %d\n", emu->num_ports); - snd_iprintf(buf, "Addresses:"); - for (i = 0; i < emu->num_ports; i++) - snd_iprintf(buf, " %d:%d", emu->client, emu->ports[i]); - snd_iprintf(buf, "\n"); - snd_iprintf(buf, "Use Counter: %d\n", emu->used); - snd_iprintf(buf, "Max Voices: %d\n", emu->max_voices); - snd_iprintf(buf, "Allocated Voices: %d\n", emu->num_voices); - if (emu->memhdr) { - snd_iprintf(buf, "Memory Size: %d\n", emu->memhdr->size); - snd_iprintf(buf, "Memory Available: %d\n", snd_util_mem_avail(emu->memhdr)); - snd_iprintf(buf, "Allocated Blocks: %d\n", emu->memhdr->nblocks); - } else { - snd_iprintf(buf, "Memory Size: 0\n"); - } - if (emu->sflist) { - mutex_lock(&emu->sflist->presets_mutex); - snd_iprintf(buf, "SoundFonts: %d\n", emu->sflist->fonts_size); - snd_iprintf(buf, "Instruments: %d\n", emu->sflist->zone_counter); - snd_iprintf(buf, "Samples: %d\n", emu->sflist->sample_counter); - snd_iprintf(buf, "Locked Instruments: %d\n", emu->sflist->zone_locked); - snd_iprintf(buf, "Locked Samples: %d\n", emu->sflist->sample_locked); - mutex_unlock(&emu->sflist->presets_mutex); - } -#if 0 /* debug */ - if (emu->voices[0].state != SNDRV_EMUX_ST_OFF && emu->voices[0].ch >= 0) { - struct snd_emux_voice *vp = &emu->voices[0]; - snd_iprintf(buf, "voice 0: on\n"); - snd_iprintf(buf, "mod delay=%x, atkhld=%x, dcysus=%x, rel=%x\n", - vp->reg.parm.moddelay, - vp->reg.parm.modatkhld, - vp->reg.parm.moddcysus, - vp->reg.parm.modrelease); - snd_iprintf(buf, "vol delay=%x, atkhld=%x, dcysus=%x, rel=%x\n", - vp->reg.parm.voldelay, - vp->reg.parm.volatkhld, - vp->reg.parm.voldcysus, - vp->reg.parm.volrelease); - snd_iprintf(buf, "lfo1 delay=%x, lfo2 delay=%x, pefe=%x\n", - vp->reg.parm.lfo1delay, - vp->reg.parm.lfo2delay, - vp->reg.parm.pefe); - snd_iprintf(buf, "fmmod=%x, tremfrq=%x, fm2frq2=%x\n", - vp->reg.parm.fmmod, - vp->reg.parm.tremfrq, - vp->reg.parm.fm2frq2); - snd_iprintf(buf, "cutoff=%x, filterQ=%x, chorus=%x, reverb=%x\n", - vp->reg.parm.cutoff, - vp->reg.parm.filterQ, - vp->reg.parm.chorus, - vp->reg.parm.reverb); - snd_iprintf(buf, "avol=%x, acutoff=%x, apitch=%x\n", - vp->avol, vp->acutoff, vp->apitch); - snd_iprintf(buf, "apan=%x, aaux=%x, ptarget=%x, vtarget=%x, ftarget=%x\n", - vp->apan, vp->aaux, - vp->ptarget, - vp->vtarget, - vp->ftarget); - snd_iprintf(buf, "start=%x, end=%x, loopstart=%x, loopend=%x\n", - vp->reg.start, vp->reg.end, vp->reg.loopstart, vp->reg.loopend); - snd_iprintf(buf, "sample_mode=%x, rate=%x\n", vp->reg.sample_mode, vp->reg.rate_offset); - } -#endif - mutex_unlock(&emu->register_mutex); -} - - -void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device) -{ - struct snd_info_entry *entry; - char name[64]; - - sprintf(name, "wavetableD%d", device); - entry = snd_info_create_card_entry(card, name, card->proc_root); - if (entry == NULL) - return; - - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = emu; - entry->c.text.read = snd_emux_proc_info_read; - if (snd_info_register(entry) < 0) - snd_info_free_entry(entry); - else - emu->proc = entry; -} - -void snd_emux_proc_free(struct snd_emux *emu) -{ - snd_info_free_entry(emu->proc); - emu->proc = NULL; -} - -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/synth/emux/emux_seq.c b/ANDROID_3.4.5/sound/synth/emux/emux_seq.c deleted file mode 100644 index 7778b8e1..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/emux_seq.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Midi Sequencer interface routines. - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "emux_voice.h" -#include <linux/slab.h> -#include <linux/module.h> - -/* Prototypes for static functions */ -static void free_port(void *private); -static void snd_emux_init_port(struct snd_emux_port *p); -static int snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info); -static int snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info); - -/* - * MIDI emulation operators - */ -static struct snd_midi_op emux_ops = { - snd_emux_note_on, - snd_emux_note_off, - snd_emux_key_press, - snd_emux_terminate_note, - snd_emux_control, - snd_emux_nrpn, - snd_emux_sysex, -}; - - -/* - * number of MIDI channels - */ -#define MIDI_CHANNELS 16 - -/* - * type flags for MIDI sequencer port - */ -#define DEFAULT_MIDI_TYPE (SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |\ - SNDRV_SEQ_PORT_TYPE_MIDI_GM |\ - SNDRV_SEQ_PORT_TYPE_MIDI_GS |\ - SNDRV_SEQ_PORT_TYPE_MIDI_XG |\ - SNDRV_SEQ_PORT_TYPE_HARDWARE |\ - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) - -/* - * Initialise the EMUX Synth by creating a client and registering - * a series of ports. - * Each of the ports will contain the 16 midi channels. Applications - * can connect to these ports to play midi data. - */ -int -snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index) -{ - int i; - struct snd_seq_port_callback pinfo; - char tmpname[64]; - - emu->client = snd_seq_create_kernel_client(card, index, - "%s WaveTable", emu->name); - if (emu->client < 0) { - snd_printk(KERN_ERR "can't create client\n"); - return -ENODEV; - } - - if (emu->num_ports < 0) { - snd_printk(KERN_WARNING "seqports must be greater than zero\n"); - emu->num_ports = 1; - } else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) { - snd_printk(KERN_WARNING "too many ports." - "limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS); - emu->num_ports = SNDRV_EMUX_MAX_PORTS; - } - - memset(&pinfo, 0, sizeof(pinfo)); - pinfo.owner = THIS_MODULE; - pinfo.use = snd_emux_use; - pinfo.unuse = snd_emux_unuse; - pinfo.event_input = snd_emux_event_input; - - for (i = 0; i < emu->num_ports; i++) { - struct snd_emux_port *p; - - sprintf(tmpname, "%s Port %d", emu->name, i); - p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS, - 0, &pinfo); - if (p == NULL) { - snd_printk(KERN_ERR "can't create port\n"); - return -ENOMEM; - } - - p->port_mode = SNDRV_EMUX_PORT_MODE_MIDI; - snd_emux_init_port(p); - emu->ports[i] = p->chset.port; - emu->portptrs[i] = p; - } - - return 0; -} - - -/* - * Detach from the ports that were set up for this synthesizer and - * destroy the kernel client. - */ -void -snd_emux_detach_seq(struct snd_emux *emu) -{ - if (emu->voices) - snd_emux_terminate_all(emu); - - mutex_lock(&emu->register_mutex); - if (emu->client >= 0) { - snd_seq_delete_kernel_client(emu->client); - emu->client = -1; - } - mutex_unlock(&emu->register_mutex); -} - - -/* - * create a sequencer port and channel_set - */ - -struct snd_emux_port * -snd_emux_create_port(struct snd_emux *emu, char *name, - int max_channels, int oss_port, - struct snd_seq_port_callback *callback) -{ - struct snd_emux_port *p; - int i, type, cap; - - /* Allocate structures for this channel */ - if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) { - snd_printk(KERN_ERR "no memory\n"); - return NULL; - } - p->chset.channels = kcalloc(max_channels, sizeof(struct snd_midi_channel), GFP_KERNEL); - if (p->chset.channels == NULL) { - snd_printk(KERN_ERR "no memory\n"); - kfree(p); - return NULL; - } - for (i = 0; i < max_channels; i++) - p->chset.channels[i].number = i; - p->chset.private_data = p; - p->chset.max_channels = max_channels; - p->emu = emu; - p->chset.client = emu->client; -#ifdef SNDRV_EMUX_USE_RAW_EFFECT - snd_emux_create_effect(p); -#endif - callback->private_free = free_port; - callback->private_data = p; - - cap = SNDRV_SEQ_PORT_CAP_WRITE; - if (oss_port) { - type = SNDRV_SEQ_PORT_TYPE_SPECIFIC; - } else { - type = DEFAULT_MIDI_TYPE; - cap |= SNDRV_SEQ_PORT_CAP_SUBS_WRITE; - } - - p->chset.port = snd_seq_event_port_attach(emu->client, callback, - cap, type, max_channels, - emu->max_voices, name); - - return p; -} - - -/* - * release memory block for port - */ -static void -free_port(void *private_data) -{ - struct snd_emux_port *p; - - p = private_data; - if (p) { -#ifdef SNDRV_EMUX_USE_RAW_EFFECT - snd_emux_delete_effect(p); -#endif - kfree(p->chset.channels); - kfree(p); - } -} - - -#define DEFAULT_DRUM_FLAGS (1<<9) - -/* - * initialize the port specific parameters - */ -static void -snd_emux_init_port(struct snd_emux_port *p) -{ - p->drum_flags = DEFAULT_DRUM_FLAGS; - p->volume_atten = 0; - - snd_emux_reset_port(p); -} - - -/* - * reset port - */ -void -snd_emux_reset_port(struct snd_emux_port *port) -{ - int i; - - /* stop all sounds */ - snd_emux_sounds_off_all(port); - - snd_midi_channel_set_clear(&port->chset); - -#ifdef SNDRV_EMUX_USE_RAW_EFFECT - snd_emux_clear_effect(port); -#endif - - /* set port specific control parameters */ - port->ctrls[EMUX_MD_DEF_BANK] = 0; - port->ctrls[EMUX_MD_DEF_DRUM] = 0; - port->ctrls[EMUX_MD_REALTIME_PAN] = 1; - - for (i = 0; i < port->chset.max_channels; i++) { - struct snd_midi_channel *chan = port->chset.channels + i; - chan->drum_channel = ((port->drum_flags >> i) & 1) ? 1 : 0; - } -} - - -/* - * input sequencer event - */ -int -snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data, - int atomic, int hop) -{ - struct snd_emux_port *port; - - port = private_data; - if (snd_BUG_ON(!port || !ev)) - return -EINVAL; - - snd_midi_process_event(&emux_ops, ev, &port->chset); - - return 0; -} - - -/* - * increment usage count - */ -int -snd_emux_inc_count(struct snd_emux *emu) -{ - emu->used++; - if (!try_module_get(emu->ops.owner)) - goto __error; - if (!try_module_get(emu->card->module)) { - module_put(emu->ops.owner); - __error: - emu->used--; - return 0; - } - return 1; -} - - -/* - * decrease usage count - */ -void -snd_emux_dec_count(struct snd_emux *emu) -{ - module_put(emu->card->module); - emu->used--; - if (emu->used <= 0) - snd_emux_terminate_all(emu); - module_put(emu->ops.owner); -} - - -/* - * Routine that is called upon a first use of a particular port - */ -static int -snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info) -{ - struct snd_emux_port *p; - struct snd_emux *emu; - - p = private_data; - if (snd_BUG_ON(!p)) - return -EINVAL; - emu = p->emu; - if (snd_BUG_ON(!emu)) - return -EINVAL; - - mutex_lock(&emu->register_mutex); - snd_emux_init_port(p); - snd_emux_inc_count(emu); - mutex_unlock(&emu->register_mutex); - return 0; -} - -/* - * Routine that is called upon the last unuse() of a particular port. - */ -static int -snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info) -{ - struct snd_emux_port *p; - struct snd_emux *emu; - - p = private_data; - if (snd_BUG_ON(!p)) - return -EINVAL; - emu = p->emu; - if (snd_BUG_ON(!emu)) - return -EINVAL; - - mutex_lock(&emu->register_mutex); - snd_emux_sounds_off_all(p); - snd_emux_dec_count(emu); - mutex_unlock(&emu->register_mutex); - return 0; -} - - -/* - * attach virtual rawmidi devices - */ -int snd_emux_init_virmidi(struct snd_emux *emu, struct snd_card *card) -{ - int i; - - emu->vmidi = NULL; - if (emu->midi_ports <= 0) - return 0; - - emu->vmidi = kcalloc(emu->midi_ports, sizeof(struct snd_rawmidi *), GFP_KERNEL); - if (emu->vmidi == NULL) - return -ENOMEM; - - for (i = 0; i < emu->midi_ports; i++) { - struct snd_rawmidi *rmidi; - struct snd_virmidi_dev *rdev; - if (snd_virmidi_new(card, emu->midi_devidx + i, &rmidi) < 0) - goto __error; - rdev = rmidi->private_data; - sprintf(rmidi->name, "%s Synth MIDI", emu->name); - rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH; - rdev->client = emu->client; - rdev->port = emu->ports[i]; - if (snd_device_register(card, rmidi) < 0) { - snd_device_free(card, rmidi); - goto __error; - } - emu->vmidi[i] = rmidi; - /* snd_printk(KERN_DEBUG "virmidi %d ok\n", i); */ - } - return 0; - -__error: - /* snd_printk(KERN_DEBUG "error init..\n"); */ - snd_emux_delete_virmidi(emu); - return -ENOMEM; -} - -int snd_emux_delete_virmidi(struct snd_emux *emu) -{ - int i; - - if (emu->vmidi == NULL) - return 0; - - for (i = 0; i < emu->midi_ports; i++) { - if (emu->vmidi[i]) - snd_device_free(emu->card, emu->vmidi[i]); - } - kfree(emu->vmidi); - emu->vmidi = NULL; - return 0; -} diff --git a/ANDROID_3.4.5/sound/synth/emux/emux_synth.c b/ANDROID_3.4.5/sound/synth/emux/emux_synth.c deleted file mode 100644 index 9a38de45..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/emux_synth.c +++ /dev/null @@ -1,984 +0,0 @@ -/* - * Midi synth routines for the Emu8k/Emu10k1 - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de> - * - * Contains code based on awe_wave.c by Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/export.h> -#include "emux_voice.h" -#include <sound/asoundef.h> - -/* - * Prototypes - */ - -/* - * Ensure a value is between two points - * macro evaluates its args more than once, so changed to upper-case. - */ -#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0) -#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0) - -static int get_zone(struct snd_emux *emu, struct snd_emux_port *port, - int *notep, int vel, struct snd_midi_channel *chan, - struct snd_sf_zone **table); -static int get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan); -static void terminate_note1(struct snd_emux *emu, int note, - struct snd_midi_channel *chan, int free); -static void exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, - int exclass); -static void terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free); -static void update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update); -static void setup_voice(struct snd_emux_voice *vp); -static int calc_pan(struct snd_emux_voice *vp); -static int calc_volume(struct snd_emux_voice *vp); -static int calc_pitch(struct snd_emux_voice *vp); - - -/* - * Start a note. - */ -void -snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) -{ - struct snd_emux *emu; - int i, key, nvoices; - struct snd_emux_voice *vp; - struct snd_sf_zone *table[SNDRV_EMUX_MAX_MULTI_VOICES]; - unsigned long flags; - struct snd_emux_port *port; - - port = p; - if (snd_BUG_ON(!port || !chan)) - return; - - emu = port->emu; - if (snd_BUG_ON(!emu || !emu->ops.get_voice || !emu->ops.trigger)) - return; - - key = note; /* remember the original note */ - nvoices = get_zone(emu, port, ¬e, vel, chan, table); - if (! nvoices) - return; - - /* exclusive note off */ - for (i = 0; i < nvoices; i++) { - struct snd_sf_zone *zp = table[i]; - if (zp && zp->v.exclusiveClass) - exclusive_note_off(emu, port, zp->v.exclusiveClass); - } - -#if 0 // seems not necessary - /* Turn off the same note on the same channel. */ - terminate_note1(emu, key, chan, 0); -#endif - - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < nvoices; i++) { - - /* set up each voice parameter */ - /* at this stage, we don't trigger the voice yet. */ - - if (table[i] == NULL) - continue; - - vp = emu->ops.get_voice(emu, port); - if (vp == NULL || vp->ch < 0) - continue; - if (STATE_IS_PLAYING(vp->state)) - emu->ops.terminate(vp); - - vp->time = emu->use_time++; - vp->chan = chan; - vp->port = port; - vp->key = key; - vp->note = note; - vp->velocity = vel; - vp->zone = table[i]; - if (vp->zone->sample) - vp->block = vp->zone->sample->block; - else - vp->block = NULL; - - setup_voice(vp); - - vp->state = SNDRV_EMUX_ST_STANDBY; - if (emu->ops.prepare) { - vp->state = SNDRV_EMUX_ST_OFF; - if (emu->ops.prepare(vp) >= 0) - vp->state = SNDRV_EMUX_ST_STANDBY; - } - } - - /* start envelope now */ - for (i = 0; i < emu->max_voices; i++) { - vp = &emu->voices[i]; - if (vp->state == SNDRV_EMUX_ST_STANDBY && - vp->chan == chan) { - emu->ops.trigger(vp); - vp->state = SNDRV_EMUX_ST_ON; - vp->ontime = jiffies; /* remember the trigger timing */ - } - } - spin_unlock_irqrestore(&emu->voice_lock, flags); - -#ifdef SNDRV_EMUX_USE_RAW_EFFECT - if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) { - /* clear voice position for the next note on this channel */ - struct snd_emux_effect_table *fx = chan->private; - if (fx) { - fx->flag[EMUX_FX_SAMPLE_START] = 0; - fx->flag[EMUX_FX_COARSE_SAMPLE_START] = 0; - } - } -#endif -} - -/* - * Release a note in response to a midi note off. - */ -void -snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) -{ - int ch; - struct snd_emux *emu; - struct snd_emux_voice *vp; - unsigned long flags; - struct snd_emux_port *port; - - port = p; - if (snd_BUG_ON(!port || !chan)) - return; - - emu = port->emu; - if (snd_BUG_ON(!emu || !emu->ops.release)) - return; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (ch = 0; ch < emu->max_voices; ch++) { - vp = &emu->voices[ch]; - if (STATE_IS_PLAYING(vp->state) && - vp->chan == chan && vp->key == note) { - vp->state = SNDRV_EMUX_ST_RELEASED; - if (vp->ontime == jiffies) { - /* if note-off is sent too shortly after - * note-on, emuX engine cannot produce the sound - * correctly. so we'll release this note - * a bit later via timer callback. - */ - vp->state = SNDRV_EMUX_ST_PENDING; - if (! emu->timer_active) { - emu->tlist.expires = jiffies + 1; - add_timer(&emu->tlist); - emu->timer_active = 1; - } - } else - /* ok now release the note */ - emu->ops.release(vp); - } - } - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - -/* - * timer callback - * - * release the pending note-offs - */ -void snd_emux_timer_callback(unsigned long data) -{ - struct snd_emux *emu = (struct snd_emux *) data; - struct snd_emux_voice *vp; - unsigned long flags; - int ch, do_again = 0; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (ch = 0; ch < emu->max_voices; ch++) { - vp = &emu->voices[ch]; - if (vp->state == SNDRV_EMUX_ST_PENDING) { - if (vp->ontime == jiffies) - do_again++; /* release this at the next interrupt */ - else { - emu->ops.release(vp); - vp->state = SNDRV_EMUX_ST_RELEASED; - } - } - } - if (do_again) { - emu->tlist.expires = jiffies + 1; - add_timer(&emu->tlist); - emu->timer_active = 1; - } else - emu->timer_active = 0; - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - -/* - * key pressure change - */ -void -snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan) -{ - int ch; - struct snd_emux *emu; - struct snd_emux_voice *vp; - unsigned long flags; - struct snd_emux_port *port; - - port = p; - if (snd_BUG_ON(!port || !chan)) - return; - - emu = port->emu; - if (snd_BUG_ON(!emu || !emu->ops.update)) - return; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (ch = 0; ch < emu->max_voices; ch++) { - vp = &emu->voices[ch]; - if (vp->state == SNDRV_EMUX_ST_ON && - vp->chan == chan && vp->key == note) { - vp->velocity = vel; - update_voice(emu, vp, SNDRV_EMUX_UPDATE_VOLUME); - } - } - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - - -/* - * Modulate the voices which belong to the channel - */ -void -snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *chan, int update) -{ - struct snd_emux *emu; - struct snd_emux_voice *vp; - int i; - unsigned long flags; - - if (! update) - return; - - emu = port->emu; - if (snd_BUG_ON(!emu || !emu->ops.update)) - return; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < emu->max_voices; i++) { - vp = &emu->voices[i]; - if (vp->chan == chan) - update_voice(emu, vp, update); - } - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - -/* - * Modulate all the voices which belong to the port. - */ -void -snd_emux_update_port(struct snd_emux_port *port, int update) -{ - struct snd_emux *emu; - struct snd_emux_voice *vp; - int i; - unsigned long flags; - - if (! update) - return; - - emu = port->emu; - if (snd_BUG_ON(!emu || !emu->ops.update)) - return; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < emu->max_voices; i++) { - vp = &emu->voices[i]; - if (vp->port == port) - update_voice(emu, vp, update); - } - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - - -/* - * Deal with a controller type event. This includes all types of - * control events, not just the midi controllers - */ -void -snd_emux_control(void *p, int type, struct snd_midi_channel *chan) -{ - struct snd_emux_port *port; - - port = p; - if (snd_BUG_ON(!port || !chan)) - return; - - switch (type) { - case MIDI_CTL_MSB_MAIN_VOLUME: - case MIDI_CTL_MSB_EXPRESSION: - snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_VOLUME); - break; - - case MIDI_CTL_MSB_PAN: - snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN); - break; - - case MIDI_CTL_SOFT_PEDAL: -#ifdef SNDRV_EMUX_USE_RAW_EFFECT - /* FIXME: this is an emulation */ - if (chan->control[type] >= 64) - snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, -160, - EMUX_FX_FLAG_ADD); - else - snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, 0, - EMUX_FX_FLAG_OFF); -#endif - break; - - case MIDI_CTL_PITCHBEND: - snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PITCH); - break; - - case MIDI_CTL_MSB_MODWHEEL: - case MIDI_CTL_CHAN_PRESSURE: - snd_emux_update_channel(port, chan, - SNDRV_EMUX_UPDATE_FMMOD | - SNDRV_EMUX_UPDATE_FM2FRQ2); - break; - - } - - if (port->chset.midi_mode == SNDRV_MIDI_MODE_XG) { - snd_emux_xg_control(port, chan, type); - } -} - - -/* - * terminate note - if free flag is true, free the terminated voice - */ -static void -terminate_note1(struct snd_emux *emu, int note, struct snd_midi_channel *chan, int free) -{ - int i; - struct snd_emux_voice *vp; - unsigned long flags; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < emu->max_voices; i++) { - vp = &emu->voices[i]; - if (STATE_IS_PLAYING(vp->state) && vp->chan == chan && - vp->key == note) - terminate_voice(emu, vp, free); - } - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - - -/* - * terminate note - exported for midi emulation - */ -void -snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan) -{ - struct snd_emux *emu; - struct snd_emux_port *port; - - port = p; - if (snd_BUG_ON(!port || !chan)) - return; - - emu = port->emu; - if (snd_BUG_ON(!emu || !emu->ops.terminate)) - return; - - terminate_note1(emu, note, chan, 1); -} - - -/* - * Terminate all the notes - */ -void -snd_emux_terminate_all(struct snd_emux *emu) -{ - int i; - struct snd_emux_voice *vp; - unsigned long flags; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < emu->max_voices; i++) { - vp = &emu->voices[i]; - if (STATE_IS_PLAYING(vp->state)) - terminate_voice(emu, vp, 0); - if (vp->state == SNDRV_EMUX_ST_OFF) { - if (emu->ops.free_voice) - emu->ops.free_voice(vp); - if (emu->ops.reset) - emu->ops.reset(emu, i); - } - vp->time = 0; - } - /* initialize allocation time */ - emu->use_time = 0; - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - -EXPORT_SYMBOL(snd_emux_terminate_all); - -/* - * Terminate all voices associated with the given port - */ -void -snd_emux_sounds_off_all(struct snd_emux_port *port) -{ - int i; - struct snd_emux *emu; - struct snd_emux_voice *vp; - unsigned long flags; - - if (snd_BUG_ON(!port)) - return; - emu = port->emu; - if (snd_BUG_ON(!emu || !emu->ops.terminate)) - return; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < emu->max_voices; i++) { - vp = &emu->voices[i]; - if (STATE_IS_PLAYING(vp->state) && - vp->port == port) - terminate_voice(emu, vp, 0); - if (vp->state == SNDRV_EMUX_ST_OFF) { - if (emu->ops.free_voice) - emu->ops.free_voice(vp); - if (emu->ops.reset) - emu->ops.reset(emu, i); - } - } - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - - -/* - * Terminate all voices that have the same exclusive class. This - * is mainly for drums. - */ -static void -exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, int exclass) -{ - struct snd_emux_voice *vp; - int i; - unsigned long flags; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < emu->max_voices; i++) { - vp = &emu->voices[i]; - if (STATE_IS_PLAYING(vp->state) && vp->port == port && - vp->reg.exclusiveClass == exclass) { - terminate_voice(emu, vp, 0); - } - } - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - -/* - * terminate a voice - * if free flag is true, call free_voice after termination - */ -static void -terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free) -{ - emu->ops.terminate(vp); - vp->time = emu->use_time++; - vp->chan = NULL; - vp->port = NULL; - vp->zone = NULL; - vp->block = NULL; - vp->state = SNDRV_EMUX_ST_OFF; - if (free && emu->ops.free_voice) - emu->ops.free_voice(vp); -} - - -/* - * Modulate the voice - */ -static void -update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update) -{ - if (!STATE_IS_PLAYING(vp->state)) - return; - - if (vp->chan == NULL || vp->port == NULL) - return; - if (update & SNDRV_EMUX_UPDATE_VOLUME) - calc_volume(vp); - if (update & SNDRV_EMUX_UPDATE_PITCH) - calc_pitch(vp); - if (update & SNDRV_EMUX_UPDATE_PAN) { - if (! calc_pan(vp) && (update == SNDRV_EMUX_UPDATE_PAN)) - return; - } - emu->ops.update(vp, update); -} - - -#if 0 // not used -/* table for volume target calculation */ -static unsigned short voltarget[16] = { - 0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58, - 0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90 -}; -#endif - -#define LO_BYTE(v) ((v) & 0xff) -#define HI_BYTE(v) (((v) >> 8) & 0xff) - -/* - * Sets up the voice structure by calculating some values that - * will be needed later. - */ -static void -setup_voice(struct snd_emux_voice *vp) -{ - struct soundfont_voice_parm *parm; - int pitch; - - /* copy the original register values */ - vp->reg = vp->zone->v; - -#ifdef SNDRV_EMUX_USE_RAW_EFFECT - snd_emux_setup_effect(vp); -#endif - - /* reset status */ - vp->apan = -1; - vp->avol = -1; - vp->apitch = -1; - - calc_volume(vp); - calc_pitch(vp); - calc_pan(vp); - - parm = &vp->reg.parm; - - /* compute filter target and correct modulation parameters */ - if (LO_BYTE(parm->modatkhld) >= 0x80 && parm->moddelay >= 0x8000) { - parm->moddelay = 0xbfff; - pitch = (HI_BYTE(parm->pefe) << 4) + vp->apitch; - if (pitch > 0xffff) - pitch = 0xffff; - /* calculate filter target */ - vp->ftarget = parm->cutoff + LO_BYTE(parm->pefe); - LIMITVALUE(vp->ftarget, 0, 255); - vp->ftarget <<= 8; - } else { - vp->ftarget = parm->cutoff; - vp->ftarget <<= 8; - pitch = vp->apitch; - } - - /* compute pitch target */ - if (pitch != 0xffff) { - vp->ptarget = 1 << (pitch >> 12); - if (pitch & 0x800) vp->ptarget += (vp->ptarget*0x102e)/0x2710; - if (pitch & 0x400) vp->ptarget += (vp->ptarget*0x764)/0x2710; - if (pitch & 0x200) vp->ptarget += (vp->ptarget*0x389)/0x2710; - vp->ptarget += (vp->ptarget >> 1); - if (vp->ptarget > 0xffff) vp->ptarget = 0xffff; - } else - vp->ptarget = 0xffff; - - if (LO_BYTE(parm->modatkhld) >= 0x80) { - parm->modatkhld &= ~0xff; - parm->modatkhld |= 0x7f; - } - - /* compute volume target and correct volume parameters */ - vp->vtarget = 0; -#if 0 /* FIXME: this leads to some clicks.. */ - if (LO_BYTE(parm->volatkhld) >= 0x80 && parm->voldelay >= 0x8000) { - parm->voldelay = 0xbfff; - vp->vtarget = voltarget[vp->avol % 0x10] >> (vp->avol >> 4); - } -#endif - - if (LO_BYTE(parm->volatkhld) >= 0x80) { - parm->volatkhld &= ~0xff; - parm->volatkhld |= 0x7f; - } -} - -/* - * calculate pitch parameter - */ -static unsigned char pan_volumes[256] = { -0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a, -0x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52, -0x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75, -0x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92, -0x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab, -0xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0, -0xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1, -0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf, -0xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9, -0xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1, -0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7, -0xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb, -0xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd, -0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -}; - -static int -calc_pan(struct snd_emux_voice *vp) -{ - struct snd_midi_channel *chan = vp->chan; - int pan; - - /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */ - if (vp->reg.fixpan > 0) /* 0-127 */ - pan = 255 - (int)vp->reg.fixpan * 2; - else { - pan = chan->control[MIDI_CTL_MSB_PAN] - 64; - if (vp->reg.pan >= 0) /* 0-127 */ - pan += vp->reg.pan - 64; - pan = 127 - (int)pan * 2; - } - LIMITVALUE(pan, 0, 255); - - if (vp->emu->linear_panning) { - /* assuming linear volume */ - if (pan != vp->apan) { - vp->apan = pan; - if (pan == 0) - vp->aaux = 0xff; - else - vp->aaux = (-pan) & 0xff; - return 1; - } else - return 0; - } else { - /* using volume table */ - if (vp->apan != (int)pan_volumes[pan]) { - vp->apan = pan_volumes[pan]; - vp->aaux = pan_volumes[255 - pan]; - return 1; - } - return 0; - } -} - - -/* - * calculate volume attenuation - * - * Voice volume is controlled by volume attenuation parameter. - * So volume becomes maximum when avol is 0 (no attenuation), and - * minimum when 255 (-96dB or silence). - */ - -/* tables for volume->attenuation calculation */ -static unsigned char voltab1[128] = { - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, - 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, - 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, - 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, - 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, - 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static unsigned char voltab2[128] = { - 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a, - 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21, - 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a, - 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15, - 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, - 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, - 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, - 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static unsigned char expressiontab[128] = { - 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42, - 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30, - 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, - 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e, - 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18, - 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13, - 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f, - 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, - 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, - 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, - 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, - 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* - * Magic to calculate the volume (actually attenuation) from all the - * voice and channels parameters. - */ -static int -calc_volume(struct snd_emux_voice *vp) -{ - int vol; - int main_vol, expression_vol, master_vol; - struct snd_midi_channel *chan = vp->chan; - struct snd_emux_port *port = vp->port; - - expression_vol = chan->control[MIDI_CTL_MSB_EXPRESSION]; - LIMITMAX(vp->velocity, 127); - LIMITVALUE(expression_vol, 0, 127); - if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) { - /* 0 - 127 */ - main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME]; - vol = (vp->velocity * main_vol * expression_vol) / (127*127); - vol = vol * vp->reg.amplitude / 127; - - LIMITVALUE(vol, 0, 127); - - /* calc to attenuation */ - vol = snd_sf_vol_table[vol]; - - } else { - main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME] * vp->reg.amplitude / 127; - LIMITVALUE(main_vol, 0, 127); - - vol = voltab1[main_vol] + voltab2[vp->velocity]; - vol = (vol * 8) / 3; - vol += vp->reg.attenuation; - vol += ((0x100 - vol) * expressiontab[expression_vol])/128; - } - - master_vol = port->chset.gs_master_volume; - LIMITVALUE(master_vol, 0, 127); - vol += snd_sf_vol_table[master_vol]; - vol += port->volume_atten; - -#ifdef SNDRV_EMUX_USE_RAW_EFFECT - if (chan->private) { - struct snd_emux_effect_table *fx = chan->private; - vol += fx->val[EMUX_FX_ATTEN]; - } -#endif - - LIMITVALUE(vol, 0, 255); - if (vp->avol == vol) - return 0; /* value unchanged */ - - vp->avol = vol; - if (!SF_IS_DRUM_BANK(get_bank(port, chan)) - && LO_BYTE(vp->reg.parm.volatkhld) < 0x7d) { - int atten; - if (vp->velocity < 70) - atten = 70; - else - atten = vp->velocity; - vp->acutoff = (atten * vp->reg.parm.cutoff + 0xa0) >> 7; - } else { - vp->acutoff = vp->reg.parm.cutoff; - } - - return 1; /* value changed */ -} - -/* - * calculate pitch offset - * - * 0xE000 is no pitch offset at 44100Hz sample. - * Every 4096 is one octave. - */ - -static int -calc_pitch(struct snd_emux_voice *vp) -{ - struct snd_midi_channel *chan = vp->chan; - int offset; - - /* calculate offset */ - if (vp->reg.fixkey >= 0) { - offset = (vp->reg.fixkey - vp->reg.root) * 4096 / 12; - } else { - offset = (vp->note - vp->reg.root) * 4096 / 12; - } - offset = (offset * vp->reg.scaleTuning) / 100; - offset += vp->reg.tune * 4096 / 1200; - if (chan->midi_pitchbend != 0) { - /* (128 * 8192: 1 semitone) ==> (4096: 12 semitones) */ - offset += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 3072; - } - - /* tuning via RPN: - * coarse = -8192 to 8192 (100 cent per 128) - * fine = -8192 to 8192 (max=100cent) - */ - /* 4096 = 1200 cents in emu8000 parameter */ - offset += chan->gm_rpn_coarse_tuning * 4096 / (12 * 128); - offset += chan->gm_rpn_fine_tuning / 24; - -#ifdef SNDRV_EMUX_USE_RAW_EFFECT - /* add initial pitch correction */ - if (chan->private) { - struct snd_emux_effect_table *fx = chan->private; - if (fx->flag[EMUX_FX_INIT_PITCH]) - offset += fx->val[EMUX_FX_INIT_PITCH]; - } -#endif - - /* 0xe000: root pitch */ - offset += 0xe000 + vp->reg.rate_offset; - offset += vp->emu->pitch_shift; - LIMITVALUE(offset, 0, 0xffff); - if (offset == vp->apitch) - return 0; /* unchanged */ - vp->apitch = offset; - return 1; /* value changed */ -} - -/* - * Get the bank number assigned to the channel - */ -static int -get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan) -{ - int val; - - switch (port->chset.midi_mode) { - case SNDRV_MIDI_MODE_XG: - val = chan->control[MIDI_CTL_MSB_BANK]; - if (val == 127) - return 128; /* return drum bank */ - return chan->control[MIDI_CTL_LSB_BANK]; - - case SNDRV_MIDI_MODE_GS: - if (chan->drum_channel) - return 128; - /* ignore LSB (bank map) */ - return chan->control[MIDI_CTL_MSB_BANK]; - - default: - if (chan->drum_channel) - return 128; - return chan->control[MIDI_CTL_MSB_BANK]; - } -} - - -/* Look for the zones matching with the given note and velocity. - * The resultant zones are stored on table. - */ -static int -get_zone(struct snd_emux *emu, struct snd_emux_port *port, - int *notep, int vel, struct snd_midi_channel *chan, - struct snd_sf_zone **table) -{ - int preset, bank, def_preset, def_bank; - - bank = get_bank(port, chan); - preset = chan->midi_program; - - if (SF_IS_DRUM_BANK(bank)) { - def_preset = port->ctrls[EMUX_MD_DEF_DRUM]; - def_bank = bank; - } else { - def_preset = preset; - def_bank = port->ctrls[EMUX_MD_DEF_BANK]; - } - - return snd_soundfont_search_zone(emu->sflist, notep, vel, preset, bank, - def_preset, def_bank, - table, SNDRV_EMUX_MAX_MULTI_VOICES); -} - -/* - */ -void -snd_emux_init_voices(struct snd_emux *emu) -{ - struct snd_emux_voice *vp; - int i; - unsigned long flags; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (i = 0; i < emu->max_voices; i++) { - vp = &emu->voices[i]; - vp->ch = -1; /* not used */ - vp->state = SNDRV_EMUX_ST_OFF; - vp->chan = NULL; - vp->port = NULL; - vp->time = 0; - vp->emu = emu; - vp->hw = emu->hw; - } - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - -/* - */ -void snd_emux_lock_voice(struct snd_emux *emu, int voice) -{ - unsigned long flags; - - spin_lock_irqsave(&emu->voice_lock, flags); - if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF) - emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED; - else - snd_printk(KERN_WARNING - "invalid voice for lock %d (state = %x)\n", - voice, emu->voices[voice].state); - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - -EXPORT_SYMBOL(snd_emux_lock_voice); - -/* - */ -void snd_emux_unlock_voice(struct snd_emux *emu, int voice) -{ - unsigned long flags; - - spin_lock_irqsave(&emu->voice_lock, flags); - if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED) - emu->voices[voice].state = SNDRV_EMUX_ST_OFF; - else - snd_printk(KERN_WARNING - "invalid voice for unlock %d (state = %x)\n", - voice, emu->voices[voice].state); - spin_unlock_irqrestore(&emu->voice_lock, flags); -} - -EXPORT_SYMBOL(snd_emux_unlock_voice); diff --git a/ANDROID_3.4.5/sound/synth/emux/emux_voice.h b/ANDROID_3.4.5/sound/synth/emux/emux_voice.h deleted file mode 100644 index 09711f84..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/emux_voice.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef __EMUX_VOICE_H -#define __EMUX_VOICE_H - -/* - * A structure to keep track of each hardware voice - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/wait.h> -#include <linux/sched.h> -#include <sound/core.h> -#include <sound/emux_synth.h> - -/* Prototypes for emux_seq.c */ -int snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index); -void snd_emux_detach_seq(struct snd_emux *emu); -struct snd_emux_port *snd_emux_create_port(struct snd_emux *emu, char *name, - int max_channels, int type, - struct snd_seq_port_callback *callback); -void snd_emux_reset_port(struct snd_emux_port *port); -int snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private, - int atomic, int hop); -int snd_emux_inc_count(struct snd_emux *emu); -void snd_emux_dec_count(struct snd_emux *emu); -int snd_emux_init_virmidi(struct snd_emux *emu, struct snd_card *card); -int snd_emux_delete_virmidi(struct snd_emux *emu); - -/* Prototypes for emux_synth.c */ -void snd_emux_init_voices(struct snd_emux *emu); - -void snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan); -void snd_emux_control(void *p, int type, struct snd_midi_channel *chan); - -void snd_emux_sounds_off_all(struct snd_emux_port *port); -void snd_emux_update_channel(struct snd_emux_port *port, - struct snd_midi_channel *chan, int update); -void snd_emux_update_port(struct snd_emux_port *port, int update); - -void snd_emux_timer_callback(unsigned long data); - -/* emux_effect.c */ -#ifdef SNDRV_EMUX_USE_RAW_EFFECT -void snd_emux_create_effect(struct snd_emux_port *p); -void snd_emux_delete_effect(struct snd_emux_port *p); -void snd_emux_clear_effect(struct snd_emux_port *p); -void snd_emux_setup_effect(struct snd_emux_voice *vp); -void snd_emux_send_effect_oss(struct snd_emux_port *port, - struct snd_midi_channel *chan, int type, int val); -void snd_emux_send_effect(struct snd_emux_port *port, - struct snd_midi_channel *chan, int type, int val, int mode); -#endif - -/* emux_nrpn.c */ -void snd_emux_sysex(void *private_data, unsigned char *buf, int len, - int parsed, struct snd_midi_channel_set *chset); -int snd_emux_xg_control(struct snd_emux_port *port, - struct snd_midi_channel *chan, int param); -void snd_emux_nrpn(void *private_data, struct snd_midi_channel *chan, - struct snd_midi_channel_set *chset); - -/* emux_oss.c */ -void snd_emux_init_seq_oss(struct snd_emux *emu); -void snd_emux_detach_seq_oss(struct snd_emux *emu); - -/* emux_proc.c */ -#ifdef CONFIG_PROC_FS -void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device); -void snd_emux_proc_free(struct snd_emux *emu); -#endif - -#define STATE_IS_PLAYING(s) ((s) & SNDRV_EMUX_ST_ON) - -/* emux_hwdep.c */ -int snd_emux_init_hwdep(struct snd_emux *emu); -void snd_emux_delete_hwdep(struct snd_emux *emu); - -#endif diff --git a/ANDROID_3.4.5/sound/synth/emux/soundfont.c b/ANDROID_3.4.5/sound/synth/emux/soundfont.c deleted file mode 100644 index 1137b85c..00000000 --- a/ANDROID_3.4.5/sound/synth/emux/soundfont.c +++ /dev/null @@ -1,1496 +0,0 @@ -/* - * Soundfont generic routines. - * It is intended that these should be used by any driver that is willing - * to accept soundfont patches. - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * Deal with reading in of a soundfont. Code follows the OSS way - * of doing things so that the old sfxload utility can be used. - * Everything may change when there is an alsa way of doing things. - */ -#include <asm/uaccess.h> -#include <linux/slab.h> -#include <linux/export.h> -#include <sound/core.h> -#include <sound/soundfont.h> -#include <sound/seq_oss_legacy.h> - -/* Prototypes for static functions */ - -static int open_patch(struct snd_sf_list *sflist, const char __user *data, - int count, int client); -static struct snd_soundfont *newsf(struct snd_sf_list *sflist, int type, char *name); -static int is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name); -static int close_patch(struct snd_sf_list *sflist); -static int probe_data(struct snd_sf_list *sflist, int sample_id); -static void set_zone_counter(struct snd_sf_list *sflist, - struct snd_soundfont *sf, struct snd_sf_zone *zp); -static struct snd_sf_zone *sf_zone_new(struct snd_sf_list *sflist, - struct snd_soundfont *sf); -static void set_sample_counter(struct snd_sf_list *sflist, - struct snd_soundfont *sf, struct snd_sf_sample *sp); -static struct snd_sf_sample *sf_sample_new(struct snd_sf_list *sflist, - struct snd_soundfont *sf); -static void sf_sample_delete(struct snd_sf_list *sflist, - struct snd_soundfont *sf, struct snd_sf_sample *sp); -static int load_map(struct snd_sf_list *sflist, const void __user *data, int count); -static int load_info(struct snd_sf_list *sflist, const void __user *data, long count); -static int remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf, - int bank, int instr); -static void init_voice_info(struct soundfont_voice_info *avp); -static void init_voice_parm(struct soundfont_voice_parm *pp); -static struct snd_sf_sample *set_sample(struct snd_soundfont *sf, - struct soundfont_voice_info *avp); -static struct snd_sf_sample *find_sample(struct snd_soundfont *sf, int sample_id); -static int load_data(struct snd_sf_list *sflist, const void __user *data, long count); -static void rebuild_presets(struct snd_sf_list *sflist); -static void add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur); -static void delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp); -static struct snd_sf_zone *search_first_zone(struct snd_sf_list *sflist, - int bank, int preset, int key); -static int search_zones(struct snd_sf_list *sflist, int *notep, int vel, - int preset, int bank, struct snd_sf_zone **table, - int max_layers, int level); -static int get_index(int bank, int instr, int key); -static void snd_sf_init(struct snd_sf_list *sflist); -static void snd_sf_clear(struct snd_sf_list *sflist); - -/* - * lock access to sflist - */ -static void -lock_preset(struct snd_sf_list *sflist) -{ - unsigned long flags; - mutex_lock(&sflist->presets_mutex); - spin_lock_irqsave(&sflist->lock, flags); - sflist->presets_locked = 1; - spin_unlock_irqrestore(&sflist->lock, flags); -} - - -/* - * remove lock - */ -static void -unlock_preset(struct snd_sf_list *sflist) -{ - unsigned long flags; - spin_lock_irqsave(&sflist->lock, flags); - sflist->presets_locked = 0; - spin_unlock_irqrestore(&sflist->lock, flags); - mutex_unlock(&sflist->presets_mutex); -} - - -/* - * close the patch if the patch was opened by this client. - */ -int -snd_soundfont_close_check(struct snd_sf_list *sflist, int client) -{ - unsigned long flags; - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->open_client == client) { - spin_unlock_irqrestore(&sflist->lock, flags); - return close_patch(sflist); - } - spin_unlock_irqrestore(&sflist->lock, flags); - return 0; -} - - -/* - * Deal with a soundfont patch. Any driver could use these routines - * although it was designed for the AWE64. - * - * The sample_write and callargs pararameters allow a callback into - * the actual driver to write sample data to the board or whatever - * it wants to do with it. - */ -int -snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, - long count, int client) -{ - struct soundfont_patch_info patch; - unsigned long flags; - int rc; - - if (count < (long)sizeof(patch)) { - snd_printk(KERN_ERR "patch record too small %ld\n", count); - return -EINVAL; - } - if (copy_from_user(&patch, data, sizeof(patch))) - return -EFAULT; - - count -= sizeof(patch); - data += sizeof(patch); - - if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) { - snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key); - return -EINVAL; - } - if (count < patch.len) { - snd_printk(KERN_ERR "Patch too short %ld, need %d\n", - count, patch.len); - return -EINVAL; - } - if (patch.len < 0) { - snd_printk(KERN_ERR "poor length %d\n", patch.len); - return -EINVAL; - } - - if (patch.type == SNDRV_SFNT_OPEN_PATCH) { - /* grab sflist to open */ - lock_preset(sflist); - rc = open_patch(sflist, data, count, client); - unlock_preset(sflist); - return rc; - } - - /* check if other client already opened patch */ - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->open_client != client) { - spin_unlock_irqrestore(&sflist->lock, flags); - return -EBUSY; - } - spin_unlock_irqrestore(&sflist->lock, flags); - - lock_preset(sflist); - rc = -EINVAL; - switch (patch.type) { - case SNDRV_SFNT_LOAD_INFO: - rc = load_info(sflist, data, count); - break; - case SNDRV_SFNT_LOAD_DATA: - rc = load_data(sflist, data, count); - break; - case SNDRV_SFNT_CLOSE_PATCH: - rc = close_patch(sflist); - break; - case SNDRV_SFNT_REPLACE_DATA: - /*rc = replace_data(&patch, data, count);*/ - break; - case SNDRV_SFNT_MAP_PRESET: - rc = load_map(sflist, data, count); - break; - case SNDRV_SFNT_PROBE_DATA: - rc = probe_data(sflist, patch.optarg); - break; - case SNDRV_SFNT_REMOVE_INFO: - /* patch must be opened */ - if (!sflist->currsf) { - snd_printk(KERN_ERR "soundfont: remove_info: " - "patch not opened\n"); - rc = -EINVAL; - } else { - int bank, instr; - bank = ((unsigned short)patch.optarg >> 8) & 0xff; - instr = (unsigned short)patch.optarg & 0xff; - if (! remove_info(sflist, sflist->currsf, bank, instr)) - rc = -EINVAL; - else - rc = 0; - } - break; - } - unlock_preset(sflist); - - return rc; -} - - -/* check if specified type is special font (GUS or preset-alias) */ -static inline int -is_special_type(int type) -{ - type &= 0x0f; - return (type == SNDRV_SFNT_PAT_TYPE_GUS || - type == SNDRV_SFNT_PAT_TYPE_MAP); -} - - -/* open patch; create sf list */ -static int -open_patch(struct snd_sf_list *sflist, const char __user *data, - int count, int client) -{ - struct soundfont_open_parm parm; - struct snd_soundfont *sf; - unsigned long flags; - - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->open_client >= 0 || sflist->currsf) { - spin_unlock_irqrestore(&sflist->lock, flags); - return -EBUSY; - } - spin_unlock_irqrestore(&sflist->lock, flags); - - if (copy_from_user(&parm, data, sizeof(parm))) - return -EFAULT; - - if (is_special_type(parm.type)) { - parm.type |= SNDRV_SFNT_PAT_SHARED; - sf = newsf(sflist, parm.type, NULL); - } else - sf = newsf(sflist, parm.type, parm.name); - if (sf == NULL) { - return -ENOMEM; - } - - spin_lock_irqsave(&sflist->lock, flags); - sflist->open_client = client; - sflist->currsf = sf; - spin_unlock_irqrestore(&sflist->lock, flags); - - return 0; -} - -/* - * Allocate a new soundfont structure. - */ -static struct snd_soundfont * -newsf(struct snd_sf_list *sflist, int type, char *name) -{ - struct snd_soundfont *sf; - - /* check the shared fonts */ - if (type & SNDRV_SFNT_PAT_SHARED) { - for (sf = sflist->fonts; sf; sf = sf->next) { - if (is_identical_font(sf, type, name)) { - return sf; - } - } - } - - /* not found -- create a new one */ - sf = kzalloc(sizeof(*sf), GFP_KERNEL); - if (sf == NULL) - return NULL; - sf->id = sflist->fonts_size; - sflist->fonts_size++; - - /* prepend this record */ - sf->next = sflist->fonts; - sflist->fonts = sf; - - sf->type = type; - sf->zones = NULL; - sf->samples = NULL; - if (name) - memcpy(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN); - - return sf; -} - -/* check if the given name matches to the existing list */ -static int -is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name) -{ - return ((sf->type & SNDRV_SFNT_PAT_SHARED) && - (sf->type & 0x0f) == (type & 0x0f) && - (name == NULL || - memcmp(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN) == 0)); -} - -/* - * Close the current patch. - */ -static int -close_patch(struct snd_sf_list *sflist) -{ - unsigned long flags; - - spin_lock_irqsave(&sflist->lock, flags); - sflist->currsf = NULL; - sflist->open_client = -1; - spin_unlock_irqrestore(&sflist->lock, flags); - - rebuild_presets(sflist); - - return 0; - -} - -/* probe sample in the current list -- nothing to be loaded */ -static int -probe_data(struct snd_sf_list *sflist, int sample_id) -{ - /* patch must be opened */ - if (sflist->currsf) { - /* search the specified sample by optarg */ - if (find_sample(sflist->currsf, sample_id)) - return 0; - } - return -EINVAL; -} - -/* - * increment zone counter - */ -static void -set_zone_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf, - struct snd_sf_zone *zp) -{ - zp->counter = sflist->zone_counter++; - if (sf->type & SNDRV_SFNT_PAT_LOCKED) - sflist->zone_locked = sflist->zone_counter; -} - -/* - * allocate a new zone record - */ -static struct snd_sf_zone * -sf_zone_new(struct snd_sf_list *sflist, struct snd_soundfont *sf) -{ - struct snd_sf_zone *zp; - - if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL) - return NULL; - zp->next = sf->zones; - sf->zones = zp; - - init_voice_info(&zp->v); - - set_zone_counter(sflist, sf, zp); - return zp; -} - - -/* - * increment sample counter - */ -static void -set_sample_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf, - struct snd_sf_sample *sp) -{ - sp->counter = sflist->sample_counter++; - if (sf->type & SNDRV_SFNT_PAT_LOCKED) - sflist->sample_locked = sflist->sample_counter; -} - -/* - * allocate a new sample list record - */ -static struct snd_sf_sample * -sf_sample_new(struct snd_sf_list *sflist, struct snd_soundfont *sf) -{ - struct snd_sf_sample *sp; - - if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL) - return NULL; - - sp->next = sf->samples; - sf->samples = sp; - - set_sample_counter(sflist, sf, sp); - return sp; -} - -/* - * delete sample list -- this is an exceptional job. - * only the last allocated sample can be deleted. - */ -static void -sf_sample_delete(struct snd_sf_list *sflist, struct snd_soundfont *sf, - struct snd_sf_sample *sp) -{ - /* only last sample is accepted */ - if (sp == sf->samples) { - sf->samples = sp->next; - kfree(sp); - } -} - - -/* load voice map */ -static int -load_map(struct snd_sf_list *sflist, const void __user *data, int count) -{ - struct snd_sf_zone *zp, *prevp; - struct snd_soundfont *sf; - struct soundfont_voice_map map; - - /* get the link info */ - if (count < (int)sizeof(map)) - return -EINVAL; - if (copy_from_user(&map, data, sizeof(map))) - return -EFAULT; - - if (map.map_instr < 0 || map.map_instr >= SF_MAX_INSTRUMENTS) - return -EINVAL; - - sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_MAP|SNDRV_SFNT_PAT_SHARED, NULL); - if (sf == NULL) - return -ENOMEM; - - prevp = NULL; - for (zp = sf->zones; zp; prevp = zp, zp = zp->next) { - if (zp->mapped && - zp->instr == map.map_instr && - zp->bank == map.map_bank && - zp->v.low == map.map_key && - zp->v.start == map.src_instr && - zp->v.end == map.src_bank && - zp->v.fixkey == map.src_key) { - /* the same mapping is already present */ - /* relink this record to the link head */ - if (prevp) { - prevp->next = zp->next; - zp->next = sf->zones; - sf->zones = zp; - } - /* update the counter */ - set_zone_counter(sflist, sf, zp); - return 0; - } - } - - /* create a new zone */ - if ((zp = sf_zone_new(sflist, sf)) == NULL) - return -ENOMEM; - - zp->bank = map.map_bank; - zp->instr = map.map_instr; - zp->mapped = 1; - if (map.map_key >= 0) { - zp->v.low = map.map_key; - zp->v.high = map.map_key; - } - zp->v.start = map.src_instr; - zp->v.end = map.src_bank; - zp->v.fixkey = map.src_key; - zp->v.sf_id = sf->id; - - add_preset(sflist, zp); - - return 0; -} - - -/* remove the present instrument layers */ -static int -remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf, - int bank, int instr) -{ - struct snd_sf_zone *prev, *next, *p; - int removed = 0; - - prev = NULL; - for (p = sf->zones; p; p = next) { - next = p->next; - if (! p->mapped && - p->bank == bank && p->instr == instr) { - /* remove this layer */ - if (prev) - prev->next = next; - else - sf->zones = next; - removed++; - kfree(p); - } else - prev = p; - } - if (removed) - rebuild_presets(sflist); - return removed; -} - - -/* - * Read an info record from the user buffer and save it on the current - * open soundfont. - */ -static int -load_info(struct snd_sf_list *sflist, const void __user *data, long count) -{ - struct snd_soundfont *sf; - struct snd_sf_zone *zone; - struct soundfont_voice_rec_hdr hdr; - int i; - - /* patch must be opened */ - if ((sf = sflist->currsf) == NULL) - return -EINVAL; - - if (is_special_type(sf->type)) - return -EINVAL; - - if (count < (long)sizeof(hdr)) { - printk(KERN_ERR "Soundfont error: invalid patch zone length\n"); - return -EINVAL; - } - if (copy_from_user((char*)&hdr, data, sizeof(hdr))) - return -EFAULT; - - data += sizeof(hdr); - count -= sizeof(hdr); - - if (hdr.nvoices <= 0 || hdr.nvoices >= 100) { - printk(KERN_ERR "Soundfont error: Illegal voice number %d\n", - hdr.nvoices); - return -EINVAL; - } - - if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) { - printk(KERN_ERR "Soundfont Error: " - "patch length(%ld) is smaller than nvoices(%d)\n", - count, hdr.nvoices); - return -EINVAL; - } - - switch (hdr.write_mode) { - case SNDRV_SFNT_WR_EXCLUSIVE: - /* exclusive mode - if the instrument already exists, - return error */ - for (zone = sf->zones; zone; zone = zone->next) { - if (!zone->mapped && - zone->bank == hdr.bank && - zone->instr == hdr.instr) - return -EINVAL; - } - break; - case SNDRV_SFNT_WR_REPLACE: - /* replace mode - remove the instrument if it already exists */ - remove_info(sflist, sf, hdr.bank, hdr.instr); - break; - } - - for (i = 0; i < hdr.nvoices; i++) { - struct snd_sf_zone tmpzone; - - /* copy awe_voice_info parameters */ - if (copy_from_user(&tmpzone.v, data, sizeof(tmpzone.v))) { - return -EFAULT; - } - - data += sizeof(tmpzone.v); - count -= sizeof(tmpzone.v); - - tmpzone.bank = hdr.bank; - tmpzone.instr = hdr.instr; - tmpzone.mapped = 0; - tmpzone.v.sf_id = sf->id; - if (tmpzone.v.mode & SNDRV_SFNT_MODE_INIT_PARM) - init_voice_parm(&tmpzone.v.parm); - - /* create a new zone */ - if ((zone = sf_zone_new(sflist, sf)) == NULL) { - return -ENOMEM; - } - - /* copy the temporary data */ - zone->bank = tmpzone.bank; - zone->instr = tmpzone.instr; - zone->v = tmpzone.v; - - /* look up the sample */ - zone->sample = set_sample(sf, &zone->v); - } - - return 0; -} - - -/* initialize voice_info record */ -static void -init_voice_info(struct soundfont_voice_info *avp) -{ - memset(avp, 0, sizeof(*avp)); - - avp->root = 60; - avp->high = 127; - avp->velhigh = 127; - avp->fixkey = -1; - avp->fixvel = -1; - avp->fixpan = -1; - avp->pan = -1; - avp->amplitude = 127; - avp->scaleTuning = 100; - - init_voice_parm(&avp->parm); -} - -/* initialize voice_parm record: - * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0. - * Vibrato and Tremolo effects are zero. - * Cutoff is maximum. - * Chorus and Reverb effects are zero. - */ -static void -init_voice_parm(struct soundfont_voice_parm *pp) -{ - memset(pp, 0, sizeof(*pp)); - - pp->moddelay = 0x8000; - pp->modatkhld = 0x7f7f; - pp->moddcysus = 0x7f7f; - pp->modrelease = 0x807f; - - pp->voldelay = 0x8000; - pp->volatkhld = 0x7f7f; - pp->voldcysus = 0x7f7f; - pp->volrelease = 0x807f; - - pp->lfo1delay = 0x8000; - pp->lfo2delay = 0x8000; - - pp->cutoff = 0xff; -} - -/* search the specified sample */ -static struct snd_sf_sample * -set_sample(struct snd_soundfont *sf, struct soundfont_voice_info *avp) -{ - struct snd_sf_sample *sample; - - sample = find_sample(sf, avp->sample); - if (sample == NULL) - return NULL; - - /* add in the actual sample offsets: - * The voice_info addresses define only the relative offset - * from sample pointers. Here we calculate the actual DRAM - * offset from sample pointers. - */ - avp->start += sample->v.start; - avp->end += sample->v.end; - avp->loopstart += sample->v.loopstart; - avp->loopend += sample->v.loopend; - - /* copy mode flags */ - avp->sample_mode = sample->v.mode_flags; - - return sample; -} - -/* find the sample pointer with the given id in the soundfont */ -static struct snd_sf_sample * -find_sample(struct snd_soundfont *sf, int sample_id) -{ - struct snd_sf_sample *p; - - if (sf == NULL) - return NULL; - - for (p = sf->samples; p; p = p->next) { - if (p->v.sample == sample_id) - return p; - } - return NULL; -} - - -/* - * Load sample information, this can include data to be loaded onto - * the soundcard. It can also just be a pointer into soundcard ROM. - * If there is data it will be written to the soundcard via the callback - * routine. - */ -static int -load_data(struct snd_sf_list *sflist, const void __user *data, long count) -{ - struct snd_soundfont *sf; - struct soundfont_sample_info sample_info; - struct snd_sf_sample *sp; - long off; - - /* patch must be opened */ - if ((sf = sflist->currsf) == NULL) - return -EINVAL; - - if (is_special_type(sf->type)) - return -EINVAL; - - if (copy_from_user(&sample_info, data, sizeof(sample_info))) - return -EFAULT; - - off = sizeof(sample_info); - - if (sample_info.size != (count-off)/2) - return -EINVAL; - - /* Check for dup */ - if (find_sample(sf, sample_info.sample)) { - /* if shared sample, skip this data */ - if (sf->type & SNDRV_SFNT_PAT_SHARED) - return 0; - return -EINVAL; - } - - /* Allocate a new sample structure */ - if ((sp = sf_sample_new(sflist, sf)) == NULL) - return -ENOMEM; - - sp->v = sample_info; - sp->v.sf_id = sf->id; - sp->v.dummy = 0; - sp->v.truesize = sp->v.size; - - /* - * If there is wave data then load it. - */ - if (sp->v.size > 0) { - int rc; - rc = sflist->callback.sample_new - (sflist->callback.private_data, sp, sflist->memhdr, - data + off, count - off); - if (rc < 0) { - sf_sample_delete(sflist, sf, sp); - return rc; - } - sflist->mem_used += sp->v.truesize; - } - - return count; -} - - -/* log2_tbl[i] = log2(i+128) * 0x10000 */ -static int log_tbl[129] = { - 0x70000, 0x702df, 0x705b9, 0x7088e, 0x70b5d, 0x70e26, 0x710eb, 0x713aa, - 0x71663, 0x71918, 0x71bc8, 0x71e72, 0x72118, 0x723b9, 0x72655, 0x728ed, - 0x72b80, 0x72e0e, 0x73098, 0x7331d, 0x7359e, 0x7381b, 0x73a93, 0x73d08, - 0x73f78, 0x741e4, 0x7444c, 0x746b0, 0x74910, 0x74b6c, 0x74dc4, 0x75019, - 0x75269, 0x754b6, 0x75700, 0x75946, 0x75b88, 0x75dc7, 0x76002, 0x7623a, - 0x7646e, 0x766a0, 0x768cd, 0x76af8, 0x76d1f, 0x76f43, 0x77164, 0x77382, - 0x7759d, 0x777b4, 0x779c9, 0x77bdb, 0x77dea, 0x77ff5, 0x781fe, 0x78404, - 0x78608, 0x78808, 0x78a06, 0x78c01, 0x78df9, 0x78fef, 0x791e2, 0x793d2, - 0x795c0, 0x797ab, 0x79993, 0x79b79, 0x79d5d, 0x79f3e, 0x7a11d, 0x7a2f9, - 0x7a4d3, 0x7a6ab, 0x7a880, 0x7aa53, 0x7ac24, 0x7adf2, 0x7afbe, 0x7b188, - 0x7b350, 0x7b515, 0x7b6d8, 0x7b899, 0x7ba58, 0x7bc15, 0x7bdd0, 0x7bf89, - 0x7c140, 0x7c2f5, 0x7c4a7, 0x7c658, 0x7c807, 0x7c9b3, 0x7cb5e, 0x7cd07, - 0x7ceae, 0x7d053, 0x7d1f7, 0x7d398, 0x7d538, 0x7d6d6, 0x7d872, 0x7da0c, - 0x7dba4, 0x7dd3b, 0x7ded0, 0x7e063, 0x7e1f4, 0x7e384, 0x7e512, 0x7e69f, - 0x7e829, 0x7e9b3, 0x7eb3a, 0x7ecc0, 0x7ee44, 0x7efc7, 0x7f148, 0x7f2c8, - 0x7f446, 0x7f5c2, 0x7f73d, 0x7f8b7, 0x7fa2f, 0x7fba5, 0x7fd1a, 0x7fe8d, - 0x80000, -}; - -/* convert from linear to log value - * - * conversion: value = log2(amount / base) * ratio - * - * argument: - * amount = linear value (unsigned, 32bit max) - * offset = base offset (:= log2(base) * 0x10000) - * ratio = division ratio - * - */ -int -snd_sf_linear_to_log(unsigned int amount, int offset, int ratio) -{ - int v; - int s, low, bit; - - if (amount < 2) - return 0; - for (bit = 0; ! (amount & 0x80000000L); bit++) - amount <<= 1; - s = (amount >> 24) & 0x7f; - low = (amount >> 16) & 0xff; - /* linear approxmimation by lower 8 bit */ - v = (log_tbl[s + 1] * low + log_tbl[s] * (0x100 - low)) >> 8; - v -= offset; - v = (v * ratio) >> 16; - v += (24 - bit) * ratio; - return v; -} - -EXPORT_SYMBOL(snd_sf_linear_to_log); - - -#define OFFSET_MSEC 653117 /* base = 1000 */ -#define OFFSET_ABSCENT 851781 /* base = 8176 */ -#define OFFSET_SAMPLERATE 1011119 /* base = 44100 */ - -#define ABSCENT_RATIO 1200 -#define TIMECENT_RATIO 1200 -#define SAMPLERATE_RATIO 4096 - -/* - * mHz to abscent - * conversion: abscent = log2(MHz / 8176) * 1200 - */ -static int -freq_to_note(int mhz) -{ - return snd_sf_linear_to_log(mhz, OFFSET_ABSCENT, ABSCENT_RATIO); -} - -/* convert Hz to AWE32 rate offset: - * sample pitch offset for the specified sample rate - * rate=44100 is no offset, each 4096 is 1 octave (twice). - * eg, when rate is 22050, this offset becomes -4096. - * - * conversion: offset = log2(Hz / 44100) * 4096 - */ -static int -calc_rate_offset(int hz) -{ - return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO); -} - - -/* calculate GUS envelope time */ -static int -calc_gus_envelope_time(int rate, int start, int end) -{ - int r, p, t; - r = (3 - ((rate >> 6) & 3)) * 3; - p = rate & 0x3f; - t = end - start; - if (t < 0) t = -t; - if (13 > r) - t = t << (13 - r); - else - t = t >> (r - 13); - return (t * 10) / (p * 441); -} - -/* convert envelope time parameter to soundfont parameters */ - -/* attack & decay/release time table (msec) */ -static short attack_time_tbl[128] = { -32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816, -707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, -361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, -180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, -90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, -45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, -22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12, -11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0, -}; - -static short decay_time_tbl[128] = { -32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082, -2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507, -1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722, -691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361, -345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180, -172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90, -86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45, -43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22, -}; - -/* delay time = 0x8000 - msec/92 */ -int -snd_sf_calc_parm_hold(int msec) -{ - int val = (0x7f * 92 - msec) / 92; - if (val < 1) val = 1; - if (val >= 126) val = 126; - return val; -} - -/* search an index for specified time from given time table */ -static int -calc_parm_search(int msec, short *table) -{ - int left = 1, right = 127, mid; - while (left < right) { - mid = (left + right) / 2; - if (msec < (int)table[mid]) - left = mid + 1; - else - right = mid; - } - return left; -} - -/* attack time: search from time table */ -int -snd_sf_calc_parm_attack(int msec) -{ - return calc_parm_search(msec, attack_time_tbl); -} - -/* decay/release time: search from time table */ -int -snd_sf_calc_parm_decay(int msec) -{ - return calc_parm_search(msec, decay_time_tbl); -} - -int snd_sf_vol_table[128] = { - 255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49, - 47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32, - 31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22, - 22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16, - 15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10, - 10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6, - 6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3, - 2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0, -}; - - -#define calc_gus_sustain(val) (0x7f - snd_sf_vol_table[(val)/2]) -#define calc_gus_attenuation(val) snd_sf_vol_table[(val)/2] - -/* load GUS patch */ -static int -load_guspatch(struct snd_sf_list *sflist, const char __user *data, - long count, int client) -{ - struct patch_info patch; - struct snd_soundfont *sf; - struct snd_sf_zone *zone; - struct snd_sf_sample *smp; - int note, sample_id; - int rc; - - if (count < (long)sizeof(patch)) { - snd_printk(KERN_ERR "patch record too small %ld\n", count); - return -EINVAL; - } - if (copy_from_user(&patch, data, sizeof(patch))) - return -EFAULT; - - count -= sizeof(patch); - data += sizeof(patch); - - sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL); - if (sf == NULL) - return -ENOMEM; - if ((smp = sf_sample_new(sflist, sf)) == NULL) - return -ENOMEM; - sample_id = sflist->sample_counter; - smp->v.sample = sample_id; - smp->v.start = 0; - smp->v.end = patch.len; - smp->v.loopstart = patch.loop_start; - smp->v.loopend = patch.loop_end; - smp->v.size = patch.len; - - /* set up mode flags */ - smp->v.mode_flags = 0; - if (!(patch.mode & WAVE_16_BITS)) - smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_8BITS; - if (patch.mode & WAVE_UNSIGNED) - smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_UNSIGNED; - smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_NO_BLANK; - if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK))) - smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_SINGLESHOT; - if (patch.mode & WAVE_BIDIR_LOOP) - smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_BIDIR_LOOP; - if (patch.mode & WAVE_LOOP_BACK) - smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_REVERSE_LOOP; - - if (patch.mode & WAVE_16_BITS) { - /* convert to word offsets */ - smp->v.size /= 2; - smp->v.end /= 2; - smp->v.loopstart /= 2; - smp->v.loopend /= 2; - } - /*smp->v.loopend++;*/ - - smp->v.dummy = 0; - smp->v.truesize = 0; - smp->v.sf_id = sf->id; - - /* set up voice info */ - if ((zone = sf_zone_new(sflist, sf)) == NULL) { - sf_sample_delete(sflist, sf, smp); - return -ENOMEM; - } - - /* - * load wave data - */ - if (sflist->callback.sample_new) { - rc = sflist->callback.sample_new - (sflist->callback.private_data, smp, sflist->memhdr, - data, count); - if (rc < 0) { - sf_sample_delete(sflist, sf, smp); - return rc; - } - /* memory offset is updated after */ - } - - /* update the memory offset here */ - sflist->mem_used += smp->v.truesize; - - zone->v.sample = sample_id; /* the last sample */ - zone->v.rate_offset = calc_rate_offset(patch.base_freq); - note = freq_to_note(patch.base_note); - zone->v.root = note / 100; - zone->v.tune = -(note % 100); - zone->v.low = (freq_to_note(patch.low_note) + 99) / 100; - zone->v.high = freq_to_note(patch.high_note) / 100; - /* panning position; -128 - 127 => 0-127 */ - zone->v.pan = (patch.panning + 128) / 2; -#if 0 - snd_printk(KERN_DEBUG - "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n", - (int)patch.base_freq, zone->v.rate_offset, - zone->v.root, zone->v.tune, zone->v.low, zone->v.high); -#endif - - /* detuning is ignored */ - /* 6points volume envelope */ - if (patch.mode & WAVE_ENVELOPES) { - int attack, hold, decay, release; - attack = calc_gus_envelope_time - (patch.env_rate[0], 0, patch.env_offset[0]); - hold = calc_gus_envelope_time - (patch.env_rate[1], patch.env_offset[0], - patch.env_offset[1]); - decay = calc_gus_envelope_time - (patch.env_rate[2], patch.env_offset[1], - patch.env_offset[2]); - release = calc_gus_envelope_time - (patch.env_rate[3], patch.env_offset[1], - patch.env_offset[4]); - release += calc_gus_envelope_time - (patch.env_rate[4], patch.env_offset[3], - patch.env_offset[4]); - release += calc_gus_envelope_time - (patch.env_rate[5], patch.env_offset[4], - patch.env_offset[5]); - zone->v.parm.volatkhld = - (snd_sf_calc_parm_hold(hold) << 8) | - snd_sf_calc_parm_attack(attack); - zone->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) | - snd_sf_calc_parm_decay(decay); - zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release); - zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]); -#if 0 - snd_printk(KERN_DEBUG - "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n", - zone->v.parm.volatkhld, - zone->v.parm.voldcysus, - zone->v.parm.volrelease, - zone->v.attenuation); -#endif - } - - /* fast release */ - if (patch.mode & WAVE_FAST_RELEASE) { - zone->v.parm.volrelease = 0x807f; - } - - /* tremolo effect */ - if (patch.mode & WAVE_TREMOLO) { - int rate = (patch.tremolo_rate * 1000 / 38) / 42; - zone->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate; - } - /* vibrato effect */ - if (patch.mode & WAVE_VIBRATO) { - int rate = (patch.vibrato_rate * 1000 / 38) / 42; - zone->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate; - } - - /* scale_freq, scale_factor, volume, and fractions not implemented */ - - if (!(smp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT)) - zone->v.mode = SNDRV_SFNT_MODE_LOOPING; - else - zone->v.mode = 0; - - /* append to the tail of the list */ - /*zone->bank = ctrls[AWE_MD_GUS_BANK];*/ - zone->bank = 0; - zone->instr = patch.instr_no; - zone->mapped = 0; - zone->v.sf_id = sf->id; - - zone->sample = set_sample(sf, &zone->v); - - /* rebuild preset now */ - add_preset(sflist, zone); - - return 0; -} - -/* load GUS patch */ -int -snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data, - long count, int client) -{ - int rc; - lock_preset(sflist); - rc = load_guspatch(sflist, data, count, client); - unlock_preset(sflist); - return rc; -} - - -/* - * Rebuild the preset table. This is like a hash table in that it allows - * quick access to the zone information. For each preset there are zone - * structures linked by next_instr and by next_zone. Former is the whole - * link for this preset, and latter is the link for zone (i.e. instrument/ - * bank/key combination). - */ -static void -rebuild_presets(struct snd_sf_list *sflist) -{ - struct snd_soundfont *sf; - struct snd_sf_zone *cur; - - /* clear preset table */ - memset(sflist->presets, 0, sizeof(sflist->presets)); - - /* search all fonts and insert each font */ - for (sf = sflist->fonts; sf; sf = sf->next) { - for (cur = sf->zones; cur; cur = cur->next) { - if (! cur->mapped && cur->sample == NULL) { - /* try again to search the corresponding sample */ - cur->sample = set_sample(sf, &cur->v); - if (cur->sample == NULL) - continue; - } - - add_preset(sflist, cur); - } - } -} - - -/* - * add the given zone to preset table - */ -static void -add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur) -{ - struct snd_sf_zone *zone; - int index; - - zone = search_first_zone(sflist, cur->bank, cur->instr, cur->v.low); - if (zone && zone->v.sf_id != cur->v.sf_id) { - /* different instrument was already defined */ - struct snd_sf_zone *p; - /* compare the allocated time */ - for (p = zone; p; p = p->next_zone) { - if (p->counter > cur->counter) - /* the current is older.. skipped */ - return; - } - /* remove old zones */ - delete_preset(sflist, zone); - zone = NULL; /* do not forget to clear this! */ - } - - /* prepend this zone */ - if ((index = get_index(cur->bank, cur->instr, cur->v.low)) < 0) - return; - cur->next_zone = zone; /* zone link */ - cur->next_instr = sflist->presets[index]; /* preset table link */ - sflist->presets[index] = cur; -} - -/* - * delete the given zones from preset_table - */ -static void -delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp) -{ - int index; - struct snd_sf_zone *p; - - if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0) - return; - for (p = sflist->presets[index]; p; p = p->next_instr) { - while (p->next_instr == zp) { - p->next_instr = zp->next_instr; - zp = zp->next_zone; - if (zp == NULL) - return; - } - } -} - - -/* - * Search matching zones from preset table. - * The note can be rewritten by preset mapping (alias). - * The found zones are stored on 'table' array. max_layers defines - * the maximum number of elements in this array. - * This function returns the number of found zones. 0 if not found. - */ -int -snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel, - int preset, int bank, - int def_preset, int def_bank, - struct snd_sf_zone **table, int max_layers) -{ - int nvoices; - unsigned long flags; - - /* this function is supposed to be called atomically, - * so we check the lock. if it's busy, just returns 0 to - * tell the caller the busy state - */ - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->presets_locked) { - spin_unlock_irqrestore(&sflist->lock, flags); - return 0; - } - nvoices = search_zones(sflist, notep, vel, preset, bank, - table, max_layers, 0); - if (! nvoices) { - if (preset != def_preset || bank != def_bank) - nvoices = search_zones(sflist, notep, vel, - def_preset, def_bank, - table, max_layers, 0); - } - spin_unlock_irqrestore(&sflist->lock, flags); - return nvoices; -} - - -/* - * search the first matching zone - */ -static struct snd_sf_zone * -search_first_zone(struct snd_sf_list *sflist, int bank, int preset, int key) -{ - int index; - struct snd_sf_zone *zp; - - if ((index = get_index(bank, preset, key)) < 0) - return NULL; - for (zp = sflist->presets[index]; zp; zp = zp->next_instr) { - if (zp->instr == preset && zp->bank == bank) - return zp; - } - return NULL; -} - - -/* - * search matching zones from sflist. can be called recursively. - */ -static int -search_zones(struct snd_sf_list *sflist, int *notep, int vel, - int preset, int bank, struct snd_sf_zone **table, - int max_layers, int level) -{ - struct snd_sf_zone *zp; - int nvoices; - - zp = search_first_zone(sflist, bank, preset, *notep); - nvoices = 0; - for (; zp; zp = zp->next_zone) { - if (*notep >= zp->v.low && *notep <= zp->v.high && - vel >= zp->v.vellow && vel <= zp->v.velhigh) { - if (zp->mapped) { - /* search preset mapping (aliasing) */ - int key = zp->v.fixkey; - preset = zp->v.start; - bank = zp->v.end; - - if (level > 5) /* too deep alias level */ - return 0; - if (key < 0) - key = *notep; - nvoices = search_zones(sflist, &key, vel, - preset, bank, table, - max_layers, level + 1); - if (nvoices > 0) - *notep = key; - break; - } - table[nvoices++] = zp; - if (nvoices >= max_layers) - break; - } - } - - return nvoices; -} - - -/* calculate the index of preset table: - * drums are mapped from 128 to 255 according to its note key. - * other instruments are mapped from 0 to 127. - * if the index is out of range, return -1. - */ -static int -get_index(int bank, int instr, int key) -{ - int index; - if (SF_IS_DRUM_BANK(bank)) - index = key + SF_MAX_INSTRUMENTS; - else - index = instr; - index = index % SF_MAX_PRESETS; - if (index < 0) - return -1; - return index; -} - -/* - * Initialise the sflist structure. - */ -static void -snd_sf_init(struct snd_sf_list *sflist) -{ - memset(sflist->presets, 0, sizeof(sflist->presets)); - - sflist->mem_used = 0; - sflist->currsf = NULL; - sflist->open_client = -1; - sflist->fonts = NULL; - sflist->fonts_size = 0; - sflist->zone_counter = 0; - sflist->sample_counter = 0; - sflist->zone_locked = 0; - sflist->sample_locked = 0; -} - -/* - * Release all list records - */ -static void -snd_sf_clear(struct snd_sf_list *sflist) -{ - struct snd_soundfont *sf, *nextsf; - struct snd_sf_zone *zp, *nextzp; - struct snd_sf_sample *sp, *nextsp; - - for (sf = sflist->fonts; sf; sf = nextsf) { - nextsf = sf->next; - for (zp = sf->zones; zp; zp = nextzp) { - nextzp = zp->next; - kfree(zp); - } - for (sp = sf->samples; sp; sp = nextsp) { - nextsp = sp->next; - if (sflist->callback.sample_free) - sflist->callback.sample_free(sflist->callback.private_data, - sp, sflist->memhdr); - kfree(sp); - } - kfree(sf); - } - - snd_sf_init(sflist); -} - - -/* - * Create a new sflist structure - */ -struct snd_sf_list * -snd_sf_new(struct snd_sf_callback *callback, struct snd_util_memhdr *hdr) -{ - struct snd_sf_list *sflist; - - if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL) - return NULL; - - mutex_init(&sflist->presets_mutex); - spin_lock_init(&sflist->lock); - sflist->memhdr = hdr; - - if (callback) - sflist->callback = *callback; - - snd_sf_init(sflist); - return sflist; -} - - -/* - * Free everything allocated off the sflist structure. - */ -void -snd_sf_free(struct snd_sf_list *sflist) -{ - if (sflist == NULL) - return; - - lock_preset(sflist); - if (sflist->callback.sample_reset) - sflist->callback.sample_reset(sflist->callback.private_data); - snd_sf_clear(sflist); - unlock_preset(sflist); - - kfree(sflist); -} - -/* - * Remove all samples - * The soundcard should be silet before calling this function. - */ -int -snd_soundfont_remove_samples(struct snd_sf_list *sflist) -{ - lock_preset(sflist); - if (sflist->callback.sample_reset) - sflist->callback.sample_reset(sflist->callback.private_data); - snd_sf_clear(sflist); - unlock_preset(sflist); - - return 0; -} - -/* - * Remove unlocked samples. - * The soundcard should be silent before calling this function. - */ -int -snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) -{ - struct snd_soundfont *sf; - struct snd_sf_zone *zp, *nextzp; - struct snd_sf_sample *sp, *nextsp; - - lock_preset(sflist); - - if (sflist->callback.sample_reset) - sflist->callback.sample_reset(sflist->callback.private_data); - - /* to be sure */ - memset(sflist->presets, 0, sizeof(sflist->presets)); - - for (sf = sflist->fonts; sf; sf = sf->next) { - for (zp = sf->zones; zp; zp = nextzp) { - if (zp->counter < sflist->zone_locked) - break; - nextzp = zp->next; - sf->zones = nextzp; - kfree(zp); - } - - for (sp = sf->samples; sp; sp = nextsp) { - if (sp->counter < sflist->sample_locked) - break; - nextsp = sp->next; - sf->samples = nextsp; - sflist->mem_used -= sp->v.truesize; - if (sflist->callback.sample_free) - sflist->callback.sample_free(sflist->callback.private_data, - sp, sflist->memhdr); - kfree(sp); - } - } - - sflist->zone_counter = sflist->zone_locked; - sflist->sample_counter = sflist->sample_locked; - - rebuild_presets(sflist); - - unlock_preset(sflist); - return 0; -} |