aboutsummaryrefslogtreecommitdiffstats
path: root/sound/synth
diff options
context:
space:
mode:
Diffstat (limited to 'sound/synth')
-rw-r--r--sound/synth/Makefile20
-rw-r--r--sound/synth/emux/Makefile20
-rw-r--r--sound/synth/emux/emux.c173
-rw-r--r--sound/synth/emux/emux_effect.c308
-rw-r--r--sound/synth/emux/emux_hwdep.c171
-rw-r--r--sound/synth/emux/emux_nrpn.c392
-rw-r--r--sound/synth/emux/emux_oss.c497
-rw-r--r--sound/synth/emux/emux_proc.c138
-rw-r--r--sound/synth/emux/emux_seq.c428
-rw-r--r--sound/synth/emux/emux_synth.c963
-rw-r--r--sound/synth/emux/emux_voice.h88
-rw-r--r--sound/synth/emux/soundfont.c1462
-rw-r--r--sound/synth/util_mem.c207
13 files changed, 4867 insertions, 0 deletions
diff --git a/sound/synth/Makefile b/sound/synth/Makefile
new file mode 100644
index 000000000000..986291dcb914
--- /dev/null
+++ b/sound/synth/Makefile
@@ -0,0 +1,20 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-util-mem-objs := util_mem.o
7
8#
9# this function returns:
10# "m" - CONFIG_SND_SEQUENCER is m
11# <empty string> - CONFIG_SND_SEQUENCER is undefined
12# otherwise parameter #1 value
13#
14sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
15
16# Toplevel Module Dependency
17obj-$(CONFIG_SND_EMU10K1) += snd-util-mem.o
18obj-$(CONFIG_SND_TRIDENT) += snd-util-mem.o
19obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-util-mem.o
20obj-$(call sequencer,$(CONFIG_SND)) += emux/
diff --git a/sound/synth/emux/Makefile b/sound/synth/emux/Makefile
new file mode 100644
index 000000000000..32a102d26709
--- /dev/null
+++ b/sound/synth/emux/Makefile
@@ -0,0 +1,20 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \
7 emux_effect.o emux_proc.o emux_hwdep.o soundfont.o \
8 $(if $(CONFIG_SND_SEQUENCER_OSS),emux_oss.o)
9
10#
11# this function returns:
12# "m" - CONFIG_SND_SEQUENCER is m
13# <empty string> - CONFIG_SND_SEQUENCER is undefined
14# otherwise parameter #1 value
15#
16sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
17
18# Toplevel Module Dependencies
19obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-emux-synth.o
20obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-emux-synth.o
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
new file mode 100644
index 000000000000..16f3b461627a
--- /dev/null
+++ b/sound/synth/emux/emux.c
@@ -0,0 +1,173 @@
1/*
2 * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
3 *
4 * Routines for control of EMU WaveTable chip
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <sound/driver.h>
22#include <linux/wait.h>
23#include <linux/sched.h>
24#include <linux/slab.h>
25#include <sound/core.h>
26#include <sound/emux_synth.h>
27#include <linux/init.h>
28#include "emux_voice.h"
29
30MODULE_AUTHOR("Takashi Iwai");
31MODULE_DESCRIPTION("Routines for control of EMU WaveTable chip");
32MODULE_LICENSE("GPL");
33
34/*
35 * create a new hardware dependent device for Emu8000/Emu10k1
36 */
37int snd_emux_new(snd_emux_t **remu)
38{
39 snd_emux_t *emu;
40
41 *remu = NULL;
42 emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
43 if (emu == NULL)
44 return -ENOMEM;
45
46 spin_lock_init(&emu->voice_lock);
47 init_MUTEX(&emu->register_mutex);
48
49 emu->client = -1;
50#ifdef CONFIG_SND_SEQUENCER_OSS
51 emu->oss_synth = NULL;
52#endif
53 emu->max_voices = 0;
54 emu->use_time = 0;
55
56 init_timer(&emu->tlist);
57 emu->tlist.function = snd_emux_timer_callback;
58 emu->tlist.data = (unsigned long)emu;
59 emu->timer_active = 0;
60
61 *remu = emu;
62 return 0;
63}
64
65
66/*
67 */
68int snd_emux_register(snd_emux_t *emu, snd_card_t *card, int index, char *name)
69{
70 int err;
71 snd_sf_callback_t sf_cb;
72
73 snd_assert(emu->hw != NULL, return -EINVAL);
74 snd_assert(emu->max_voices > 0, return -EINVAL);
75 snd_assert(card != NULL, return -EINVAL);
76 snd_assert(name != NULL, return -EINVAL);
77
78 emu->card = card;
79 emu->name = snd_kmalloc_strdup(name, GFP_KERNEL);
80 emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL);
81 if (emu->voices == NULL)
82 return -ENOMEM;
83
84 /* create soundfont list */
85 memset(&sf_cb, 0, sizeof(sf_cb));
86 sf_cb.private_data = emu;
87 sf_cb.sample_new = (snd_sf_sample_new_t)emu->ops.sample_new;
88 sf_cb.sample_free = (snd_sf_sample_free_t)emu->ops.sample_free;
89 sf_cb.sample_reset = (snd_sf_sample_reset_t)emu->ops.sample_reset;
90 emu->sflist = snd_sf_new(&sf_cb, emu->memhdr);
91 if (emu->sflist == NULL)
92 return -ENOMEM;
93
94 if ((err = snd_emux_init_hwdep(emu)) < 0)
95 return err;
96
97 snd_emux_init_voices(emu);
98
99 snd_emux_init_seq(emu, card, index);
100#ifdef CONFIG_SND_SEQUENCER_OSS
101 snd_emux_init_seq_oss(emu);
102#endif
103 snd_emux_init_virmidi(emu, card);
104
105#ifdef CONFIG_PROC_FS
106 snd_emux_proc_init(emu, card, index);
107#endif
108 return 0;
109}
110
111
112/*
113 */
114int snd_emux_free(snd_emux_t *emu)
115{
116 unsigned long flags;
117
118 if (! emu)
119 return -EINVAL;
120
121 spin_lock_irqsave(&emu->voice_lock, flags);
122 if (emu->timer_active)
123 del_timer(&emu->tlist);
124 spin_unlock_irqrestore(&emu->voice_lock, flags);
125
126#ifdef CONFIG_PROC_FS
127 snd_emux_proc_free(emu);
128#endif
129 snd_emux_delete_virmidi(emu);
130#ifdef CONFIG_SND_SEQUENCER_OSS
131 snd_emux_detach_seq_oss(emu);
132#endif
133 snd_emux_detach_seq(emu);
134
135 snd_emux_delete_hwdep(emu);
136
137 if (emu->sflist)
138 snd_sf_free(emu->sflist);
139
140 kfree(emu->voices);
141 kfree(emu->name);
142 kfree(emu);
143 return 0;
144}
145
146
147EXPORT_SYMBOL(snd_emux_new);
148EXPORT_SYMBOL(snd_emux_register);
149EXPORT_SYMBOL(snd_emux_free);
150
151EXPORT_SYMBOL(snd_emux_terminate_all);
152EXPORT_SYMBOL(snd_emux_lock_voice);
153EXPORT_SYMBOL(snd_emux_unlock_voice);
154
155/* soundfont.c */
156EXPORT_SYMBOL(snd_sf_linear_to_log);
157
158
159/*
160 * INIT part
161 */
162
163static int __init alsa_emux_init(void)
164{
165 return 0;
166}
167
168static void __exit alsa_emux_exit(void)
169{
170}
171
172module_init(alsa_emux_init)
173module_exit(alsa_emux_exit)
diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c
new file mode 100644
index 000000000000..ec3fc1ba7fca
--- /dev/null
+++ b/sound/synth/emux/emux_effect.c
@@ -0,0 +1,308 @@
1/*
2 * Midi synth routines for the Emu8k/Emu10k1
3 *
4 * Copyright (C) 1999 Steve Ratcliffe
5 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
6 *
7 * Contains code based on awe_wave.c by Takashi Iwai
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include "emux_voice.h"
26#include <linux/slab.h>
27
28#ifdef SNDRV_EMUX_USE_RAW_EFFECT
29/*
30 * effects table
31 */
32
33#define xoffsetof(type,tag) ((long)(&((type)NULL)->tag) - (long)(NULL))
34
35#define parm_offset(tag) xoffsetof(soundfont_voice_parm_t*, tag)
36
37#define PARM_IS_BYTE (1 << 0)
38#define PARM_IS_WORD (1 << 1)
39#define PARM_IS_ALIGNED (3 << 2)
40#define PARM_IS_ALIGN_HI (1 << 2)
41#define PARM_IS_ALIGN_LO (2 << 2)
42#define PARM_IS_SIGNED (1 << 4)
43
44#define PARM_WORD (PARM_IS_WORD)
45#define PARM_BYTE_LO (PARM_IS_BYTE|PARM_IS_ALIGN_LO)
46#define PARM_BYTE_HI (PARM_IS_BYTE|PARM_IS_ALIGN_HI)
47#define PARM_BYTE (PARM_IS_BYTE)
48#define PARM_SIGN_LO (PARM_IS_BYTE|PARM_IS_ALIGN_LO|PARM_IS_SIGNED)
49#define PARM_SIGN_HI (PARM_IS_BYTE|PARM_IS_ALIGN_HI|PARM_IS_SIGNED)
50
51static struct emux_parm_defs {
52 int type; /* byte or word */
53 int low, high; /* value range */
54 long offset; /* offset in parameter record (-1 = not written) */
55 int update; /* flgas for real-time update */
56} parm_defs[EMUX_NUM_EFFECTS] = {
57 {PARM_WORD, 0, 0x8000, parm_offset(moddelay), 0}, /* env1 delay */
58 {PARM_BYTE_LO, 1, 0x80, parm_offset(modatkhld), 0}, /* env1 attack */
59 {PARM_BYTE_HI, 0, 0x7e, parm_offset(modatkhld), 0}, /* env1 hold */
60 {PARM_BYTE_LO, 1, 0x7f, parm_offset(moddcysus), 0}, /* env1 decay */
61 {PARM_BYTE_LO, 1, 0x7f, parm_offset(modrelease), 0}, /* env1 release */
62 {PARM_BYTE_HI, 0, 0x7f, parm_offset(moddcysus), 0}, /* env1 sustain */
63 {PARM_BYTE_HI, 0, 0xff, parm_offset(pefe), 0}, /* env1 pitch */
64 {PARM_BYTE_LO, 0, 0xff, parm_offset(pefe), 0}, /* env1 fc */
65
66 {PARM_WORD, 0, 0x8000, parm_offset(voldelay), 0}, /* env2 delay */
67 {PARM_BYTE_LO, 1, 0x80, parm_offset(volatkhld), 0}, /* env2 attack */
68 {PARM_BYTE_HI, 0, 0x7e, parm_offset(volatkhld), 0}, /* env2 hold */
69 {PARM_BYTE_LO, 1, 0x7f, parm_offset(voldcysus), 0}, /* env2 decay */
70 {PARM_BYTE_LO, 1, 0x7f, parm_offset(volrelease), 0}, /* env2 release */
71 {PARM_BYTE_HI, 0, 0x7f, parm_offset(voldcysus), 0}, /* env2 sustain */
72
73 {PARM_WORD, 0, 0x8000, parm_offset(lfo1delay), 0}, /* lfo1 delay */
74 {PARM_BYTE_LO, 0, 0xff, parm_offset(tremfrq), SNDRV_EMUX_UPDATE_TREMFREQ}, /* lfo1 freq */
75 {PARM_SIGN_HI, -128, 127, parm_offset(tremfrq), SNDRV_EMUX_UPDATE_TREMFREQ}, /* lfo1 vol */
76 {PARM_SIGN_HI, -128, 127, parm_offset(fmmod), SNDRV_EMUX_UPDATE_FMMOD}, /* lfo1 pitch */
77 {PARM_BYTE_LO, 0, 0xff, parm_offset(fmmod), SNDRV_EMUX_UPDATE_FMMOD}, /* lfo1 cutoff */
78
79 {PARM_WORD, 0, 0x8000, parm_offset(lfo2delay), 0}, /* lfo2 delay */
80 {PARM_BYTE_LO, 0, 0xff, parm_offset(fm2frq2), SNDRV_EMUX_UPDATE_FM2FRQ2}, /* lfo2 freq */
81 {PARM_SIGN_HI, -128, 127, parm_offset(fm2frq2), SNDRV_EMUX_UPDATE_FM2FRQ2}, /* lfo2 pitch */
82
83 {PARM_WORD, 0, 0xffff, -1, SNDRV_EMUX_UPDATE_PITCH}, /* initial pitch */
84 {PARM_BYTE, 0, 0xff, parm_offset(chorus), 0}, /* chorus */
85 {PARM_BYTE, 0, 0xff, parm_offset(reverb), 0}, /* reverb */
86 {PARM_BYTE, 0, 0xff, parm_offset(cutoff), SNDRV_EMUX_UPDATE_VOLUME}, /* cutoff */
87 {PARM_BYTE, 0, 15, parm_offset(filterQ), SNDRV_EMUX_UPDATE_Q}, /* resonance */
88
89 {PARM_WORD, 0, 0xffff, -1, 0}, /* sample start */
90 {PARM_WORD, 0, 0xffff, -1, 0}, /* loop start */
91 {PARM_WORD, 0, 0xffff, -1, 0}, /* loop end */
92 {PARM_WORD, 0, 0xffff, -1, 0}, /* coarse sample start */
93 {PARM_WORD, 0, 0xffff, -1, 0}, /* coarse loop start */
94 {PARM_WORD, 0, 0xffff, -1, 0}, /* coarse loop end */
95 {PARM_BYTE, 0, 0xff, -1, SNDRV_EMUX_UPDATE_VOLUME}, /* initial attenuation */
96};
97
98/* set byte effect value */
99static void
100effect_set_byte(unsigned char *valp, snd_midi_channel_t *chan, int type)
101{
102 short effect;
103 snd_emux_effect_table_t *fx = chan->private;
104
105 effect = fx->val[type];
106 if (fx->flag[type] == EMUX_FX_FLAG_ADD) {
107 if (parm_defs[type].type & PARM_IS_SIGNED)
108 effect += *(char*)valp;
109 else
110 effect += *valp;
111 }
112 if (effect < parm_defs[type].low)
113 effect = parm_defs[type].low;
114 else if (effect > parm_defs[type].high)
115 effect = parm_defs[type].high;
116 *valp = (unsigned char)effect;
117}
118
119/* set word effect value */
120static void
121effect_set_word(unsigned short *valp, snd_midi_channel_t *chan, int type)
122{
123 int effect;
124 snd_emux_effect_table_t *fx = chan->private;
125
126 effect = *(unsigned short*)&fx->val[type];
127 if (fx->flag[type] == EMUX_FX_FLAG_ADD)
128 effect += *valp;
129 if (effect < parm_defs[type].low)
130 effect = parm_defs[type].low;
131 else if (effect > parm_defs[type].high)
132 effect = parm_defs[type].high;
133 *valp = (unsigned short)effect;
134}
135
136/* address offset */
137static int
138effect_get_offset(snd_midi_channel_t *chan, int lo, int hi, int mode)
139{
140 int addr = 0;
141 snd_emux_effect_table_t *fx = chan->private;
142
143 if (fx->flag[hi])
144 addr = (short)fx->val[hi];
145 addr = addr << 15;
146 if (fx->flag[lo])
147 addr += (short)fx->val[lo];
148 if (!(mode & SNDRV_SFNT_SAMPLE_8BITS))
149 addr /= 2;
150 return addr;
151}
152
153#ifdef CONFIG_SND_SEQUENCER_OSS
154/* change effects - for OSS sequencer compatibility */
155void
156snd_emux_send_effect_oss(snd_emux_port_t *port, snd_midi_channel_t *chan, int type, int val)
157{
158 int mode;
159
160 if (type & 0x40)
161 mode = EMUX_FX_FLAG_OFF;
162 else if (type & 0x80)
163 mode = EMUX_FX_FLAG_ADD;
164 else
165 mode = EMUX_FX_FLAG_SET;
166 type &= 0x3f;
167
168 snd_emux_send_effect(port, chan, type, val, mode);
169}
170#endif
171
172/* Modify the effect value.
173 * if update is necessary, call emu8000_control
174 */
175void
176snd_emux_send_effect(snd_emux_port_t *port, snd_midi_channel_t *chan, int type, int val, int mode)
177{
178 int i;
179 int offset;
180 unsigned char *srcp, *origp;
181 snd_emux_t *emu;
182 snd_emux_effect_table_t *fx;
183 unsigned long flags;
184
185 emu = port->emu;
186 fx = chan->private;
187 if (emu == NULL || fx == NULL)
188 return;
189 if (type < 0 || type >= EMUX_NUM_EFFECTS)
190 return;
191
192 fx->val[type] = val;
193 fx->flag[type] = mode;
194
195 /* do we need to modify the register in realtime ? */
196 if (! parm_defs[type].update || (offset = parm_defs[type].offset) < 0)
197 return;
198
199#ifdef SNDRV_LITTLE_ENDIAN
200 if (parm_defs[type].type & PARM_IS_ALIGN_HI)
201 offset++;
202#else
203 if (parm_defs[type].type & PARM_IS_ALIGN_LO)
204 offset++;
205#endif
206 /* modify the register values */
207 spin_lock_irqsave(&emu->voice_lock, flags);
208 for (i = 0; i < emu->max_voices; i++) {
209 snd_emux_voice_t *vp = &emu->voices[i];
210 if (!STATE_IS_PLAYING(vp->state) || vp->chan != chan)
211 continue;
212 srcp = (unsigned char*)&vp->reg.parm + offset;
213 origp = (unsigned char*)&vp->zone->v.parm + offset;
214 if (parm_defs[i].type & PARM_IS_BYTE) {
215 *srcp = *origp;
216 effect_set_byte(srcp, chan, type);
217 } else {
218 *(unsigned short*)srcp = *(unsigned short*)origp;
219 effect_set_word((unsigned short*)srcp, chan, type);
220 }
221 }
222 spin_unlock_irqrestore(&emu->voice_lock, flags);
223
224 /* activate them */
225 snd_emux_update_channel(port, chan, parm_defs[type].update);
226}
227
228
229/* copy wavetable registers to voice table */
230void
231snd_emux_setup_effect(snd_emux_voice_t *vp)
232{
233 snd_midi_channel_t *chan = vp->chan;
234 snd_emux_effect_table_t *fx;
235 unsigned char *srcp;
236 int i;
237
238 if (! (fx = chan->private))
239 return;
240
241 /* modify the register values via effect table */
242 for (i = 0; i < EMUX_FX_END; i++) {
243 int offset;
244 if (! fx->flag[i] || (offset = parm_defs[i].offset) < 0)
245 continue;
246#ifdef SNDRV_LITTLE_ENDIAN
247 if (parm_defs[i].type & PARM_IS_ALIGN_HI)
248 offset++;
249#else
250 if (parm_defs[i].type & PARM_IS_ALIGN_LO)
251 offset++;
252#endif
253 srcp = (unsigned char*)&vp->reg.parm + offset;
254 if (parm_defs[i].type & PARM_IS_BYTE)
255 effect_set_byte(srcp, chan, i);
256 else
257 effect_set_word((unsigned short*)srcp, chan, i);
258 }
259
260 /* correct sample and loop points */
261 vp->reg.start += effect_get_offset(chan, EMUX_FX_SAMPLE_START,
262 EMUX_FX_COARSE_SAMPLE_START,
263 vp->reg.sample_mode);
264
265 vp->reg.loopstart += effect_get_offset(chan, EMUX_FX_LOOP_START,
266 EMUX_FX_COARSE_LOOP_START,
267 vp->reg.sample_mode);
268
269 vp->reg.loopend += effect_get_offset(chan, EMUX_FX_LOOP_END,
270 EMUX_FX_COARSE_LOOP_END,
271 vp->reg.sample_mode);
272}
273
274/*
275 * effect table
276 */
277void
278snd_emux_create_effect(snd_emux_port_t *p)
279{
280 int i;
281 p->effect = kcalloc(p->chset.max_channels, sizeof(snd_emux_effect_table_t), GFP_KERNEL);
282 if (p->effect) {
283 for (i = 0; i < p->chset.max_channels; i++)
284 p->chset.channels[i].private = p->effect + i;
285 } else {
286 for (i = 0; i < p->chset.max_channels; i++)
287 p->chset.channels[i].private = NULL;
288 }
289}
290
291void
292snd_emux_delete_effect(snd_emux_port_t *p)
293{
294 if (p->effect) {
295 kfree(p->effect);
296 p->effect = NULL;
297 }
298}
299
300void
301snd_emux_clear_effect(snd_emux_port_t *p)
302{
303 if (p->effect) {
304 memset(p->effect, 0, sizeof(snd_emux_effect_table_t) * p->chset.max_channels);
305 }
306}
307
308#endif /* SNDRV_EMUX_USE_RAW_EFFECT */
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c
new file mode 100644
index 000000000000..4182b44eb47e
--- /dev/null
+++ b/sound/synth/emux/emux_hwdep.c
@@ -0,0 +1,171 @@
1/*
2 * Interface for hwdep device
3 *
4 * Copyright (C) 2004 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <sound/core.h>
24#include <sound/hwdep.h>
25#include <asm/uaccess.h>
26#include "emux_voice.h"
27
28/*
29 * open the hwdep device
30 */
31static int
32snd_emux_hwdep_open(snd_hwdep_t *hw, struct file *file)
33{
34 return 0;
35}
36
37
38/*
39 * close the device
40 */
41static int
42snd_emux_hwdep_release(snd_hwdep_t *hw, struct file *file)
43{
44 return 0;
45}
46
47
48#define TMP_CLIENT_ID 0x1001
49
50/*
51 * load patch
52 */
53static int
54snd_emux_hwdep_load_patch(snd_emux_t *emu, void __user *arg)
55{
56 int err;
57 soundfont_patch_info_t patch;
58
59 if (copy_from_user(&patch, arg, sizeof(patch)))
60 return -EFAULT;
61
62 if (patch.type >= SNDRV_SFNT_LOAD_INFO &&
63 patch.type <= SNDRV_SFNT_PROBE_DATA) {
64 err = snd_soundfont_load(emu->sflist, arg, patch.len + sizeof(patch), TMP_CLIENT_ID);
65 if (err < 0)
66 return err;
67 } else {
68 if (emu->ops.load_fx)
69 return emu->ops.load_fx(emu, patch.type, patch.optarg, arg, patch.len + sizeof(patch));
70 else
71 return -EINVAL;
72 }
73 return 0;
74}
75
76/*
77 * set misc mode
78 */
79static int
80snd_emux_hwdep_misc_mode(snd_emux_t *emu, void __user *arg)
81{
82 struct sndrv_emux_misc_mode info;
83 int i;
84
85 if (copy_from_user(&info, arg, sizeof(info)))
86 return -EFAULT;
87 if (info.mode < 0 || info.mode >= EMUX_MD_END)
88 return -EINVAL;
89
90 if (info.port < 0) {
91 for (i = 0; i < emu->num_ports; i++)
92 emu->portptrs[i]->ctrls[info.mode] = info.value;
93 } else {
94 if (info.port < emu->num_ports)
95 emu->portptrs[info.port]->ctrls[info.mode] = info.value;
96 }
97 return 0;
98}
99
100
101/*
102 * ioctl
103 */
104static int
105snd_emux_hwdep_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
106{
107 snd_emux_t *emu = hw->private_data;
108
109 switch (cmd) {
110 case SNDRV_EMUX_IOCTL_VERSION:
111 return put_user(SNDRV_EMUX_VERSION, (unsigned int __user *)arg);
112 case SNDRV_EMUX_IOCTL_LOAD_PATCH:
113 return snd_emux_hwdep_load_patch(emu, (void __user *)arg);
114 case SNDRV_EMUX_IOCTL_RESET_SAMPLES:
115 snd_soundfont_remove_samples(emu->sflist);
116 break;
117 case SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES:
118 snd_soundfont_remove_unlocked(emu->sflist);
119 break;
120 case SNDRV_EMUX_IOCTL_MEM_AVAIL:
121 if (emu->memhdr) {
122 int size = snd_util_mem_avail(emu->memhdr);
123 return put_user(size, (unsigned int __user *)arg);
124 }
125 break;
126 case SNDRV_EMUX_IOCTL_MISC_MODE:
127 return snd_emux_hwdep_misc_mode(emu, (void __user *)arg);
128 }
129
130 return 0;
131}
132
133
134/*
135 * register hwdep device
136 */
137
138int
139snd_emux_init_hwdep(snd_emux_t *emu)
140{
141 snd_hwdep_t *hw;
142 int err;
143
144 if ((err = snd_hwdep_new(emu->card, SNDRV_EMUX_HWDEP_NAME, emu->hwdep_idx, &hw)) < 0)
145 return err;
146 emu->hwdep = hw;
147 strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME);
148 hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE;
149 hw->ops.open = snd_emux_hwdep_open;
150 hw->ops.release = snd_emux_hwdep_release;
151 hw->ops.ioctl = snd_emux_hwdep_ioctl;
152 hw->exclusive = 1;
153 hw->private_data = emu;
154 if ((err = snd_card_register(emu->card)) < 0)
155 return err;
156
157 return 0;
158}
159
160
161/*
162 * unregister
163 */
164void
165snd_emux_delete_hwdep(snd_emux_t *emu)
166{
167 if (emu->hwdep) {
168 snd_device_free(emu->card, emu->hwdep);
169 emu->hwdep = NULL;
170 }
171}
diff --git a/sound/synth/emux/emux_nrpn.c b/sound/synth/emux/emux_nrpn.c
new file mode 100644
index 000000000000..25edff9e1fc2
--- /dev/null
+++ b/sound/synth/emux/emux_nrpn.c
@@ -0,0 +1,392 @@
1/*
2 * NRPN / SYSEX callbacks for Emu8k/Emu10k1
3 *
4 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include "emux_voice.h"
23#include <sound/asoundef.h>
24
25/*
26 * conversion from NRPN/control parameters to Emu8000 raw parameters
27 */
28
29/* NRPN / CC -> Emu8000 parameter converter */
30typedef struct {
31 int control;
32 int effect;
33 int (*convert)(int val);
34} nrpn_conv_table;
35
36/* effect sensitivity */
37
38#define FX_CUTOFF 0
39#define FX_RESONANCE 1
40#define FX_ATTACK 2
41#define FX_RELEASE 3
42#define FX_VIBRATE 4
43#define FX_VIBDEPTH 5
44#define FX_VIBDELAY 6
45#define FX_NUMS 7
46
47/*
48 * convert NRPN/control values
49 */
50
51static int send_converted_effect(nrpn_conv_table *table, int num_tables,
52 snd_emux_port_t *port, snd_midi_channel_t *chan,
53 int type, int val, int mode)
54{
55 int i, cval;
56 for (i = 0; i < num_tables; i++) {
57 if (table[i].control == type) {
58 cval = table[i].convert(val);
59 snd_emux_send_effect(port, chan, table[i].effect,
60 cval, mode);
61 return 1;
62 }
63 }
64 return 0;
65}
66
67#define DEF_FX_CUTOFF 170
68#define DEF_FX_RESONANCE 6
69#define DEF_FX_ATTACK 50
70#define DEF_FX_RELEASE 50
71#define DEF_FX_VIBRATE 30
72#define DEF_FX_VIBDEPTH 4
73#define DEF_FX_VIBDELAY 1500
74
75/* effect sensitivities for GS NRPN:
76 * adjusted for chaos 8MB soundfonts
77 */
78static int gs_sense[] =
79{
80 DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
81 DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
82};
83
84/* effect sensitivies for XG controls:
85 * adjusted for chaos 8MB soundfonts
86 */
87static int xg_sense[] =
88{
89 DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
90 DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
91};
92
93
94/*
95 * AWE32 NRPN effects
96 */
97
98static int fx_delay(int val);
99static int fx_attack(int val);
100static int fx_hold(int val);
101static int fx_decay(int val);
102static int fx_the_value(int val);
103static int fx_twice_value(int val);
104static int fx_conv_pitch(int val);
105static int fx_conv_Q(int val);
106
107/* function for each NRPN */ /* [range] units */
108#define fx_env1_delay fx_delay /* [0,5900] 4msec */
109#define fx_env1_attack fx_attack /* [0,5940] 1msec */
110#define fx_env1_hold fx_hold /* [0,8191] 1msec */
111#define fx_env1_decay fx_decay /* [0,5940] 4msec */
112#define fx_env1_release fx_decay /* [0,5940] 4msec */
113#define fx_env1_sustain fx_the_value /* [0,127] 0.75dB */
114#define fx_env1_pitch fx_the_value /* [-127,127] 9.375cents */
115#define fx_env1_cutoff fx_the_value /* [-127,127] 56.25cents */
116
117#define fx_env2_delay fx_delay /* [0,5900] 4msec */
118#define fx_env2_attack fx_attack /* [0,5940] 1msec */
119#define fx_env2_hold fx_hold /* [0,8191] 1msec */
120#define fx_env2_decay fx_decay /* [0,5940] 4msec */
121#define fx_env2_release fx_decay /* [0,5940] 4msec */
122#define fx_env2_sustain fx_the_value /* [0,127] 0.75dB */
123
124#define fx_lfo1_delay fx_delay /* [0,5900] 4msec */
125#define fx_lfo1_freq fx_twice_value /* [0,127] 84mHz */
126#define fx_lfo1_volume fx_twice_value /* [0,127] 0.1875dB */
127#define fx_lfo1_pitch fx_the_value /* [-127,127] 9.375cents */
128#define fx_lfo1_cutoff fx_twice_value /* [-64,63] 56.25cents */
129
130#define fx_lfo2_delay fx_delay /* [0,5900] 4msec */
131#define fx_lfo2_freq fx_twice_value /* [0,127] 84mHz */
132#define fx_lfo2_pitch fx_the_value /* [-127,127] 9.375cents */
133
134#define fx_init_pitch fx_conv_pitch /* [-8192,8192] cents */
135#define fx_chorus fx_the_value /* [0,255] -- */
136#define fx_reverb fx_the_value /* [0,255] -- */
137#define fx_cutoff fx_twice_value /* [0,127] 62Hz */
138#define fx_filterQ fx_conv_Q /* [0,127] -- */
139
140static int fx_delay(int val)
141{
142 return (unsigned short)snd_sf_calc_parm_delay(val);
143}
144
145static int fx_attack(int val)
146{
147 return (unsigned short)snd_sf_calc_parm_attack(val);
148}
149
150static int fx_hold(int val)
151{
152 return (unsigned short)snd_sf_calc_parm_hold(val);
153}
154
155static int fx_decay(int val)
156{
157 return (unsigned short)snd_sf_calc_parm_decay(val);
158}
159
160static int fx_the_value(int val)
161{
162 return (unsigned short)(val & 0xff);
163}
164
165static int fx_twice_value(int val)
166{
167 return (unsigned short)((val * 2) & 0xff);
168}
169
170static int fx_conv_pitch(int val)
171{
172 return (short)(val * 4096 / 1200);
173}
174
175static int fx_conv_Q(int val)
176{
177 return (unsigned short)((val / 8) & 0xff);
178}
179
180
181static nrpn_conv_table awe_effects[] =
182{
183 { 0, EMUX_FX_LFO1_DELAY, fx_lfo1_delay},
184 { 1, EMUX_FX_LFO1_FREQ, fx_lfo1_freq},
185 { 2, EMUX_FX_LFO2_DELAY, fx_lfo2_delay},
186 { 3, EMUX_FX_LFO2_FREQ, fx_lfo2_freq},
187
188 { 4, EMUX_FX_ENV1_DELAY, fx_env1_delay},
189 { 5, EMUX_FX_ENV1_ATTACK,fx_env1_attack},
190 { 6, EMUX_FX_ENV1_HOLD, fx_env1_hold},
191 { 7, EMUX_FX_ENV1_DECAY, fx_env1_decay},
192 { 8, EMUX_FX_ENV1_SUSTAIN, fx_env1_sustain},
193 { 9, EMUX_FX_ENV1_RELEASE, fx_env1_release},
194
195 {10, EMUX_FX_ENV2_DELAY, fx_env2_delay},
196 {11, EMUX_FX_ENV2_ATTACK, fx_env2_attack},
197 {12, EMUX_FX_ENV2_HOLD, fx_env2_hold},
198 {13, EMUX_FX_ENV2_DECAY, fx_env2_decay},
199 {14, EMUX_FX_ENV2_SUSTAIN, fx_env2_sustain},
200 {15, EMUX_FX_ENV2_RELEASE, fx_env2_release},
201
202 {16, EMUX_FX_INIT_PITCH, fx_init_pitch},
203 {17, EMUX_FX_LFO1_PITCH, fx_lfo1_pitch},
204 {18, EMUX_FX_LFO2_PITCH, fx_lfo2_pitch},
205 {19, EMUX_FX_ENV1_PITCH, fx_env1_pitch},
206 {20, EMUX_FX_LFO1_VOLUME, fx_lfo1_volume},
207 {21, EMUX_FX_CUTOFF, fx_cutoff},
208 {22, EMUX_FX_FILTERQ, fx_filterQ},
209 {23, EMUX_FX_LFO1_CUTOFF, fx_lfo1_cutoff},
210 {24, EMUX_FX_ENV1_CUTOFF, fx_env1_cutoff},
211 {25, EMUX_FX_CHORUS, fx_chorus},
212 {26, EMUX_FX_REVERB, fx_reverb},
213};
214
215
216/*
217 * GS(SC88) NRPN effects; still experimental
218 */
219
220/* cutoff: quarter semitone step, max=255 */
221static int gs_cutoff(int val)
222{
223 return (val - 64) * gs_sense[FX_CUTOFF] / 50;
224}
225
226/* resonance: 0 to 15(max) */
227static int gs_filterQ(int val)
228{
229 return (val - 64) * gs_sense[FX_RESONANCE] / 50;
230}
231
232/* attack: */
233static int gs_attack(int val)
234{
235 return -(val - 64) * gs_sense[FX_ATTACK] / 50;
236}
237
238/* decay: */
239static int gs_decay(int val)
240{
241 return -(val - 64) * gs_sense[FX_RELEASE] / 50;
242}
243
244/* release: */
245static int gs_release(int val)
246{
247 return -(val - 64) * gs_sense[FX_RELEASE] / 50;
248}
249
250/* vibrato freq: 0.042Hz step, max=255 */
251static int gs_vib_rate(int val)
252{
253 return (val - 64) * gs_sense[FX_VIBRATE] / 50;
254}
255
256/* vibrato depth: max=127, 1 octave */
257static int gs_vib_depth(int val)
258{
259 return (val - 64) * gs_sense[FX_VIBDEPTH] / 50;
260}
261
262/* vibrato delay: -0.725msec step */
263static int gs_vib_delay(int val)
264{
265 return -(val - 64) * gs_sense[FX_VIBDELAY] / 50;
266}
267
268static nrpn_conv_table gs_effects[] =
269{
270 {32, EMUX_FX_CUTOFF, gs_cutoff},
271 {33, EMUX_FX_FILTERQ, gs_filterQ},
272 {99, EMUX_FX_ENV2_ATTACK, gs_attack},
273 {100, EMUX_FX_ENV2_DECAY, gs_decay},
274 {102, EMUX_FX_ENV2_RELEASE, gs_release},
275 {8, EMUX_FX_LFO1_FREQ, gs_vib_rate},
276 {9, EMUX_FX_LFO1_VOLUME, gs_vib_depth},
277 {10, EMUX_FX_LFO1_DELAY, gs_vib_delay},
278};
279
280
281/*
282 * NRPN events
283 */
284void
285snd_emux_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset)
286{
287 snd_emux_port_t *port;
288
289 port = p;
290 snd_assert(port != NULL, return);
291 snd_assert(chan != NULL, return);
292
293 if (chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] == 127 &&
294 chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB] <= 26) {
295 int val;
296 /* Win/DOS AWE32 specific NRPNs */
297 /* both MSB/LSB necessary */
298 val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) |
299 chan->control[MIDI_CTL_LSB_DATA_ENTRY];
300 val -= 8192;
301 send_converted_effect
302 (awe_effects, ARRAY_SIZE(awe_effects),
303 port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
304 val, EMUX_FX_FLAG_SET);
305 return;
306 }
307
308 if (port->chset.midi_mode == SNDRV_MIDI_MODE_GS &&
309 chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] == 1) {
310 int val;
311 /* GS specific NRPNs */
312 /* only MSB is valid */
313 val = chan->control[MIDI_CTL_MSB_DATA_ENTRY];
314 send_converted_effect
315 (gs_effects, ARRAY_SIZE(gs_effects),
316 port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
317 val, EMUX_FX_FLAG_ADD);
318 return;
319 }
320}
321
322
323/*
324 * XG control effects; still experimental
325 */
326
327/* cutoff: quarter semitone step, max=255 */
328static int xg_cutoff(int val)
329{
330 return (val - 64) * xg_sense[FX_CUTOFF] / 64;
331}
332
333/* resonance: 0(open) to 15(most nasal) */
334static int xg_filterQ(int val)
335{
336 return (val - 64) * xg_sense[FX_RESONANCE] / 64;
337}
338
339/* attack: */
340static int xg_attack(int val)
341{
342 return -(val - 64) * xg_sense[FX_ATTACK] / 64;
343}
344
345/* release: */
346static int xg_release(int val)
347{
348 return -(val - 64) * xg_sense[FX_RELEASE] / 64;
349}
350
351static nrpn_conv_table xg_effects[] =
352{
353 {71, EMUX_FX_CUTOFF, xg_cutoff},
354 {74, EMUX_FX_FILTERQ, xg_filterQ},
355 {72, EMUX_FX_ENV2_RELEASE, xg_release},
356 {73, EMUX_FX_ENV2_ATTACK, xg_attack},
357};
358
359int
360snd_emux_xg_control(snd_emux_port_t *port, snd_midi_channel_t *chan, int param)
361{
362 return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects),
363 port, chan, param,
364 chan->control[param],
365 EMUX_FX_FLAG_ADD);
366}
367
368/*
369 * receive sysex
370 */
371void
372snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset)
373{
374 snd_emux_port_t *port;
375 snd_emux_t *emu;
376
377 port = p;
378 snd_assert(port != NULL, return);
379 snd_assert(chset != NULL, return);
380 emu = port->emu;
381
382 switch (parsed) {
383 case SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME:
384 snd_emux_update_port(port, SNDRV_EMUX_UPDATE_VOLUME);
385 break;
386 default:
387 if (emu->ops.sysex)
388 emu->ops.sysex(emu, buf, len, parsed, chset);
389 break;
390 }
391}
392
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c
new file mode 100644
index 000000000000..5272f4ac8afd
--- /dev/null
+++ b/sound/synth/emux/emux_oss.c
@@ -0,0 +1,497 @@
1/*
2 * Interface for OSS sequencer emulation
3 *
4 * Copyright (C) 1999 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * Changes
21 * 19990227 Steve Ratcliffe Made separate file and merged in latest
22 * midi emulation.
23 */
24
25#include <sound/driver.h>
26
27#ifdef CONFIG_SND_SEQUENCER_OSS
28
29#include <asm/uaccess.h>
30#include <sound/core.h>
31#include "emux_voice.h"
32#include <sound/asoundef.h>
33
34static int snd_emux_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure);
35static int snd_emux_close_seq_oss(snd_seq_oss_arg_t *arg);
36static int snd_emux_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd, unsigned long ioarg);
37static int snd_emux_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format, const char __user *buf, int offs, int count);
38static int snd_emux_reset_seq_oss(snd_seq_oss_arg_t *arg);
39static int snd_emux_event_oss_input(snd_seq_event_t *ev, int direct, void *private, int atomic, int hop);
40static void reset_port_mode(snd_emux_port_t *port, int midi_mode);
41static void emuspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd, unsigned char *event, int atomic, int hop);
42static void gusspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd, unsigned char *event, int atomic, int hop);
43static void fake_event(snd_emux_t *emu, snd_emux_port_t *port, int ch, int param, int val, int atomic, int hop);
44
45/* operators */
46static snd_seq_oss_callback_t oss_callback = {
47 .owner = THIS_MODULE,
48 .open = snd_emux_open_seq_oss,
49 .close = snd_emux_close_seq_oss,
50 .ioctl = snd_emux_ioctl_seq_oss,
51 .load_patch = snd_emux_load_patch_seq_oss,
52 .reset = snd_emux_reset_seq_oss,
53};
54
55
56/*
57 * register OSS synth
58 */
59
60void
61snd_emux_init_seq_oss(snd_emux_t *emu)
62{
63 snd_seq_oss_reg_t *arg;
64 snd_seq_device_t *dev;
65
66 if (snd_seq_device_new(emu->card, 0, SNDRV_SEQ_DEV_ID_OSS,
67 sizeof(snd_seq_oss_reg_t), &dev) < 0)
68 return;
69
70 emu->oss_synth = dev;
71 strcpy(dev->name, emu->name);
72 arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
73 arg->type = SYNTH_TYPE_SAMPLE;
74 arg->subtype = SAMPLE_TYPE_AWE32;
75 arg->nvoices = emu->max_voices;
76 arg->oper = oss_callback;
77 arg->private_data = emu;
78
79 /* register to OSS synth table */
80 snd_device_register(emu->card, dev);
81}
82
83
84/*
85 * unregister
86 */
87void
88snd_emux_detach_seq_oss(snd_emux_t *emu)
89{
90 if (emu->oss_synth) {
91 snd_device_free(emu->card, emu->oss_synth);
92 emu->oss_synth = NULL;
93 }
94}
95
96
97/* use port number as a unique soundfont client number */
98#define SF_CLIENT_NO(p) ((p) + 0x1000)
99
100/*
101 * open port for OSS sequencer
102 */
103static int
104snd_emux_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure)
105{
106 snd_emux_t *emu;
107 snd_emux_port_t *p;
108 snd_seq_port_callback_t callback;
109 char tmpname[64];
110
111 emu = closure;
112 snd_assert(arg != NULL && emu != NULL, return -ENXIO);
113
114 down(&emu->register_mutex);
115
116 if (!snd_emux_inc_count(emu)) {
117 up(&emu->register_mutex);
118 return -EFAULT;
119 }
120
121 memset(&callback, 0, sizeof(callback));
122 callback.owner = THIS_MODULE;
123 callback.event_input = snd_emux_event_oss_input;
124
125 sprintf(tmpname, "%s OSS Port", emu->name);
126 p = snd_emux_create_port(emu, tmpname, 32,
127 1, &callback);
128 if (p == NULL) {
129 snd_printk("can't create port\n");
130 snd_emux_dec_count(emu);
131 up(&emu->register_mutex);
132 return -ENOMEM;
133 }
134
135 /* fill the argument data */
136 arg->private_data = p;
137 arg->addr.client = p->chset.client;
138 arg->addr.port = p->chset.port;
139 p->oss_arg = arg;
140
141 reset_port_mode(p, arg->seq_mode);
142
143 snd_emux_reset_port(p);
144
145 up(&emu->register_mutex);
146 return 0;
147}
148
149
150#define DEFAULT_DRUM_FLAGS ((1<<9) | (1<<25))
151
152/*
153 * reset port mode
154 */
155static void
156reset_port_mode(snd_emux_port_t *port, int midi_mode)
157{
158 if (midi_mode) {
159 port->port_mode = SNDRV_EMUX_PORT_MODE_OSS_MIDI;
160 port->drum_flags = DEFAULT_DRUM_FLAGS;
161 port->volume_atten = 0;
162 port->oss_arg->event_passing = SNDRV_SEQ_OSS_PROCESS_KEYPRESS;
163 } else {
164 port->port_mode = SNDRV_EMUX_PORT_MODE_OSS_SYNTH;
165 port->drum_flags = 0;
166 port->volume_atten = 32;
167 port->oss_arg->event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS;
168 }
169}
170
171
172/*
173 * close port
174 */
175static int
176snd_emux_close_seq_oss(snd_seq_oss_arg_t *arg)
177{
178 snd_emux_t *emu;
179 snd_emux_port_t *p;
180
181 snd_assert(arg != NULL, return -ENXIO);
182 p = arg->private_data;
183 snd_assert(p != NULL, return -ENXIO);
184
185 emu = p->emu;
186 snd_assert(emu != NULL, return -ENXIO);
187
188 down(&emu->register_mutex);
189 snd_emux_sounds_off_all(p);
190 snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port));
191 snd_seq_event_port_detach(p->chset.client, p->chset.port);
192 snd_emux_dec_count(emu);
193
194 up(&emu->register_mutex);
195 return 0;
196}
197
198
199/*
200 * load patch
201 */
202static int
203snd_emux_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
204 const char __user *buf, int offs, int count)
205{
206 snd_emux_t *emu;
207 snd_emux_port_t *p;
208 int rc;
209
210 snd_assert(arg != NULL, return -ENXIO);
211 p = arg->private_data;
212 snd_assert(p != NULL, return -ENXIO);
213
214 emu = p->emu;
215 snd_assert(emu != NULL, return -ENXIO);
216
217 if (format == GUS_PATCH)
218 rc = snd_soundfont_load_guspatch(emu->sflist, buf, count,
219 SF_CLIENT_NO(p->chset.port));
220 else if (format == SNDRV_OSS_SOUNDFONT_PATCH) {
221 soundfont_patch_info_t patch;
222 if (count < (int)sizeof(patch))
223 rc = -EINVAL;
224 if (copy_from_user(&patch, buf, sizeof(patch)))
225 rc = -EFAULT;
226 if (patch.type >= SNDRV_SFNT_LOAD_INFO &&
227 patch.type <= SNDRV_SFNT_PROBE_DATA)
228 rc = snd_soundfont_load(emu->sflist, buf, count, SF_CLIENT_NO(p->chset.port));
229 else {
230 if (emu->ops.load_fx)
231 rc = emu->ops.load_fx(emu, patch.type, patch.optarg, buf, count);
232 else
233 rc = -EINVAL;
234 }
235 } else
236 rc = 0;
237 return rc;
238}
239
240
241/*
242 * ioctl
243 */
244static int
245snd_emux_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd, unsigned long ioarg)
246{
247 snd_emux_port_t *p;
248 snd_emux_t *emu;
249
250 snd_assert(arg != NULL, return -ENXIO);
251 p = arg->private_data;
252 snd_assert(p != NULL, return -ENXIO);
253
254 emu = p->emu;
255 snd_assert(emu != NULL, return -ENXIO);
256
257 switch (cmd) {
258 case SNDCTL_SEQ_RESETSAMPLES:
259 snd_soundfont_remove_samples(emu->sflist);
260 return 0;
261
262 case SNDCTL_SYNTH_MEMAVL:
263 if (emu->memhdr)
264 return snd_util_mem_avail(emu->memhdr);
265 return 0;
266 }
267
268 return 0;
269}
270
271
272/*
273 * reset device
274 */
275static int
276snd_emux_reset_seq_oss(snd_seq_oss_arg_t *arg)
277{
278 snd_emux_port_t *p;
279
280 snd_assert(arg != NULL, return -ENXIO);
281 p = arg->private_data;
282 snd_assert(p != NULL, return -ENXIO);
283 snd_emux_reset_port(p);
284 return 0;
285}
286
287
288/*
289 * receive raw events: only SEQ_PRIVATE is accepted.
290 */
291static int
292snd_emux_event_oss_input(snd_seq_event_t *ev, int direct, void *private_data,
293 int atomic, int hop)
294{
295 snd_emux_t *emu;
296 snd_emux_port_t *p;
297 unsigned char cmd, *data;
298
299 p = private_data;
300 snd_assert(p != NULL, return -EINVAL);
301 emu = p->emu;
302 snd_assert(emu != NULL, return -EINVAL);
303 if (ev->type != SNDRV_SEQ_EVENT_OSS)
304 return snd_emux_event_input(ev, direct, private_data, atomic, hop);
305
306 data = ev->data.raw8.d;
307 /* only SEQ_PRIVATE is accepted */
308 if (data[0] != 0xfe)
309 return 0;
310 cmd = data[2] & _EMUX_OSS_MODE_VALUE_MASK;
311 if (data[2] & _EMUX_OSS_MODE_FLAG)
312 emuspec_control(emu, p, cmd, data, atomic, hop);
313 else
314 gusspec_control(emu, p, cmd, data, atomic, hop);
315 return 0;
316}
317
318
319/*
320 * OSS/AWE driver specific h/w controls
321 */
322static void
323emuspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd,
324 unsigned char *event, int atomic, int hop)
325{
326 int voice;
327 unsigned short p1;
328 short p2;
329 int i;
330 snd_midi_channel_t *chan;
331
332 voice = event[3];
333 if (voice < 0 || voice >= port->chset.max_channels)
334 chan = NULL;
335 else
336 chan = &port->chset.channels[voice];
337
338 p1 = *(unsigned short *) &event[4];
339 p2 = *(short *) &event[6];
340
341 switch (cmd) {
342#if 0 /* don't do this atomically */
343 case _EMUX_OSS_REMOVE_LAST_SAMPLES:
344 snd_soundfont_remove_unlocked(emu->sflist);
345 break;
346#endif
347 case _EMUX_OSS_SEND_EFFECT:
348 if (chan)
349 snd_emux_send_effect_oss(port, chan, p1, p2);
350 break;
351
352 case _EMUX_OSS_TERMINATE_ALL:
353 snd_emux_terminate_all(emu);
354 break;
355
356 case _EMUX_OSS_TERMINATE_CHANNEL:
357 /*snd_emux_mute_channel(emu, chan);*/
358 break;
359 case _EMUX_OSS_RESET_CHANNEL:
360 /*snd_emux_channel_init(chset, chan);*/
361 break;
362
363 case _EMUX_OSS_RELEASE_ALL:
364 fake_event(emu, port, voice, MIDI_CTL_ALL_NOTES_OFF, 0, atomic, hop);
365 break;
366 case _EMUX_OSS_NOTEOFF_ALL:
367 fake_event(emu, port, voice, MIDI_CTL_ALL_SOUNDS_OFF, 0, atomic, hop);
368 break;
369
370 case _EMUX_OSS_INITIAL_VOLUME:
371 if (p2) {
372 port->volume_atten = (short)p1;
373 snd_emux_update_port(port, SNDRV_EMUX_UPDATE_VOLUME);
374 }
375 break;
376
377 case _EMUX_OSS_CHN_PRESSURE:
378 if (chan) {
379 chan->midi_pressure = p1;
380 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_FMMOD|SNDRV_EMUX_UPDATE_FM2FRQ2);
381 }
382 break;
383
384 case _EMUX_OSS_CHANNEL_MODE:
385 reset_port_mode(port, p1);
386 snd_emux_reset_port(port);
387 break;
388
389 case _EMUX_OSS_DRUM_CHANNELS:
390 port->drum_flags = *(unsigned int*)&event[4];
391 for (i = 0; i < port->chset.max_channels; i++) {
392 chan = &port->chset.channels[i];
393 chan->drum_channel = ((port->drum_flags >> i) & 1) ? 1 : 0;
394 }
395 break;
396
397 case _EMUX_OSS_MISC_MODE:
398 if (p1 < EMUX_MD_END)
399 port->ctrls[p1] = p2;
400 break;
401 case _EMUX_OSS_DEBUG_MODE:
402 break;
403
404 default:
405 if (emu->ops.oss_ioctl)
406 emu->ops.oss_ioctl(emu, cmd, p1, p2);
407 break;
408 }
409}
410
411/*
412 * GUS specific h/w controls
413 */
414
415#include <linux/ultrasound.h>
416
417static void
418gusspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd,
419 unsigned char *event, int atomic, int hop)
420{
421 int voice;
422 unsigned short p1;
423 short p2;
424 int plong;
425 snd_midi_channel_t *chan;
426
427 if (port->port_mode != SNDRV_EMUX_PORT_MODE_OSS_SYNTH)
428 return;
429 if (cmd == _GUS_NUMVOICES)
430 return;
431 voice = event[3];
432 if (voice < 0 || voice >= port->chset.max_channels)
433 return;
434
435 chan = &port->chset.channels[voice];
436
437 p1 = *(unsigned short *) &event[4];
438 p2 = *(short *) &event[6];
439 plong = *(int*) &event[4];
440
441 switch (cmd) {
442 case _GUS_VOICESAMPLE:
443 chan->midi_program = p1;
444 return;
445
446 case _GUS_VOICEBALA:
447 /* 0 to 15 --> 0 to 127 */
448 chan->control[MIDI_CTL_MSB_PAN] = (int)p1 << 3;
449 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN);
450 return;
451
452 case _GUS_VOICEVOL:
453 case _GUS_VOICEVOL2:
454 /* not supported yet */
455 return;
456
457 case _GUS_RAMPRANGE:
458 case _GUS_RAMPRATE:
459 case _GUS_RAMPMODE:
460 case _GUS_RAMPON:
461 case _GUS_RAMPOFF:
462 /* volume ramping not supported */
463 return;
464
465 case _GUS_VOLUME_SCALE:
466 return;
467
468 case _GUS_VOICE_POS:
469#ifdef SNDRV_EMUX_USE_RAW_EFFECT
470 snd_emux_send_effect(port, chan, EMUX_FX_SAMPLE_START,
471 (short)(plong & 0x7fff),
472 EMUX_FX_FLAG_SET);
473 snd_emux_send_effect(port, chan, EMUX_FX_COARSE_SAMPLE_START,
474 (plong >> 15) & 0xffff,
475 EMUX_FX_FLAG_SET);
476#endif
477 return;
478 }
479}
480
481
482/*
483 * send an event to midi emulation
484 */
485static void
486fake_event(snd_emux_t *emu, snd_emux_port_t *port, int ch, int param, int val, int atomic, int hop)
487{
488 snd_seq_event_t ev;
489 memset(&ev, 0, sizeof(ev));
490 ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
491 ev.data.control.channel = ch;
492 ev.data.control.param = param;
493 ev.data.control.value = val;
494 snd_emux_event_input(&ev, 0, port, atomic, hop);
495}
496
497#endif /* CONFIG_SND_SEQUENCER_OSS */
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c
new file mode 100644
index 000000000000..0f155d68de0d
--- /dev/null
+++ b/sound/synth/emux/emux_proc.c
@@ -0,0 +1,138 @@
1/*
2 * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
3 *
4 * Proc interface for Emu8k/Emu10k1 WaveTable synth
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <sound/driver.h>
22#include <linux/wait.h>
23#include <linux/sched.h>
24#include <linux/slab.h>
25#include <sound/core.h>
26#include <sound/emux_synth.h>
27#include <sound/info.h>
28#include "emux_voice.h"
29
30#ifdef CONFIG_PROC_FS
31
32static void
33snd_emux_proc_info_read(snd_info_entry_t *entry,
34 snd_info_buffer_t *buf)
35{
36 snd_emux_t *emu;
37 int i;
38
39 emu = entry->private_data;
40 down(&emu->register_mutex);
41 if (emu->name)
42 snd_iprintf(buf, "Device: %s\n", emu->name);
43 snd_iprintf(buf, "Ports: %d\n", emu->num_ports);
44 snd_iprintf(buf, "Addresses:");
45 for (i = 0; i < emu->num_ports; i++)
46 snd_iprintf(buf, " %d:%d", emu->client, emu->ports[i]);
47 snd_iprintf(buf, "\n");
48 snd_iprintf(buf, "Use Counter: %d\n", emu->used);
49 snd_iprintf(buf, "Max Voices: %d\n", emu->max_voices);
50 snd_iprintf(buf, "Allocated Voices: %d\n", emu->num_voices);
51 if (emu->memhdr) {
52 snd_iprintf(buf, "Memory Size: %d\n", emu->memhdr->size);
53 snd_iprintf(buf, "Memory Available: %d\n", snd_util_mem_avail(emu->memhdr));
54 snd_iprintf(buf, "Allocated Blocks: %d\n", emu->memhdr->nblocks);
55 } else {
56 snd_iprintf(buf, "Memory Size: 0\n");
57 }
58 if (emu->sflist) {
59 down(&emu->sflist->presets_mutex);
60 snd_iprintf(buf, "SoundFonts: %d\n", emu->sflist->fonts_size);
61 snd_iprintf(buf, "Instruments: %d\n", emu->sflist->zone_counter);
62 snd_iprintf(buf, "Samples: %d\n", emu->sflist->sample_counter);
63 snd_iprintf(buf, "Locked Instruments: %d\n", emu->sflist->zone_locked);
64 snd_iprintf(buf, "Locked Samples: %d\n", emu->sflist->sample_locked);
65 up(&emu->sflist->presets_mutex);
66 }
67#if 0 /* debug */
68 if (emu->voices[0].state != SNDRV_EMUX_ST_OFF && emu->voices[0].ch >= 0) {
69 snd_emux_voice_t *vp = &emu->voices[0];
70 snd_iprintf(buf, "voice 0: on\n");
71 snd_iprintf(buf, "mod delay=%x, atkhld=%x, dcysus=%x, rel=%x\n",
72 vp->reg.parm.moddelay,
73 vp->reg.parm.modatkhld,
74 vp->reg.parm.moddcysus,
75 vp->reg.parm.modrelease);
76 snd_iprintf(buf, "vol delay=%x, atkhld=%x, dcysus=%x, rel=%x\n",
77 vp->reg.parm.voldelay,
78 vp->reg.parm.volatkhld,
79 vp->reg.parm.voldcysus,
80 vp->reg.parm.volrelease);
81 snd_iprintf(buf, "lfo1 delay=%x, lfo2 delay=%x, pefe=%x\n",
82 vp->reg.parm.lfo1delay,
83 vp->reg.parm.lfo2delay,
84 vp->reg.parm.pefe);
85 snd_iprintf(buf, "fmmod=%x, tremfrq=%x, fm2frq2=%x\n",
86 vp->reg.parm.fmmod,
87 vp->reg.parm.tremfrq,
88 vp->reg.parm.fm2frq2);
89 snd_iprintf(buf, "cutoff=%x, filterQ=%x, chorus=%x, reverb=%x\n",
90 vp->reg.parm.cutoff,
91 vp->reg.parm.filterQ,
92 vp->reg.parm.chorus,
93 vp->reg.parm.reverb);
94 snd_iprintf(buf, "avol=%x, acutoff=%x, apitch=%x\n",
95 vp->avol, vp->acutoff, vp->apitch);
96 snd_iprintf(buf, "apan=%x, aaux=%x, ptarget=%x, vtarget=%x, ftarget=%x\n",
97 vp->apan, vp->aaux,
98 vp->ptarget,
99 vp->vtarget,
100 vp->ftarget);
101 snd_iprintf(buf, "start=%x, end=%x, loopstart=%x, loopend=%x\n",
102 vp->reg.start, vp->reg.end, vp->reg.loopstart, vp->reg.loopend);
103 snd_iprintf(buf, "sample_mode=%x, rate=%x\n", vp->reg.sample_mode, vp->reg.rate_offset);
104 }
105#endif
106 up(&emu->register_mutex);
107}
108
109
110void snd_emux_proc_init(snd_emux_t *emu, snd_card_t *card, int device)
111{
112 snd_info_entry_t *entry;
113 char name[64];
114
115 sprintf(name, "wavetableD%d", device);
116 entry = snd_info_create_card_entry(card, name, card->proc_root);
117 if (entry == NULL)
118 return;
119
120 entry->content = SNDRV_INFO_CONTENT_TEXT;
121 entry->private_data = emu;
122 entry->c.text.read_size = 1024;
123 entry->c.text.read = snd_emux_proc_info_read;
124 if (snd_info_register(entry) < 0)
125 snd_info_free_entry(entry);
126 else
127 emu->proc = entry;
128}
129
130void snd_emux_proc_free(snd_emux_t *emu)
131{
132 if (emu->proc) {
133 snd_info_unregister(emu->proc);
134 emu->proc = NULL;
135 }
136}
137
138#endif /* CONFIG_PROC_FS */
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
new file mode 100644
index 000000000000..e41b28d9bf52
--- /dev/null
+++ b/sound/synth/emux/emux_seq.c
@@ -0,0 +1,428 @@
1/*
2 * Midi Sequencer interface routines.
3 *
4 * Copyright (C) 1999 Steve Ratcliffe
5 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "emux_voice.h"
23#include <linux/slab.h>
24
25
26/* Prototypes for static functions */
27static void free_port(void *private);
28static void snd_emux_init_port(snd_emux_port_t *p);
29static int snd_emux_use(void *private_data, snd_seq_port_subscribe_t *info);
30static int snd_emux_unuse(void *private_data, snd_seq_port_subscribe_t *info);
31static int get_client(snd_card_t *card, int index, char *name);
32
33/*
34 * MIDI emulation operators
35 */
36static snd_midi_op_t emux_ops = {
37 snd_emux_note_on,
38 snd_emux_note_off,
39 snd_emux_key_press,
40 snd_emux_terminate_note,
41 snd_emux_control,
42 snd_emux_nrpn,
43 snd_emux_sysex,
44};
45
46
47/*
48 * number of MIDI channels
49 */
50#define MIDI_CHANNELS 16
51
52/*
53 * type flags for MIDI sequencer port
54 */
55#define DEFAULT_MIDI_TYPE (SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |\
56 SNDRV_SEQ_PORT_TYPE_MIDI_GM |\
57 SNDRV_SEQ_PORT_TYPE_MIDI_GS |\
58 SNDRV_SEQ_PORT_TYPE_MIDI_XG |\
59 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE)
60
61/*
62 * Initialise the EMUX Synth by creating a client and registering
63 * a series of ports.
64 * Each of the ports will contain the 16 midi channels. Applications
65 * can connect to these ports to play midi data.
66 */
67int
68snd_emux_init_seq(snd_emux_t *emu, snd_card_t *card, int index)
69{
70 int i;
71 snd_seq_port_callback_t pinfo;
72 char tmpname[64];
73
74 sprintf(tmpname, "%s WaveTable", emu->name);
75 emu->client = get_client(card, index, tmpname);
76 if (emu->client < 0) {
77 snd_printk("can't create client\n");
78 return -ENODEV;
79 }
80
81 if (emu->num_ports < 0) {
82 snd_printk("seqports must be greater than zero\n");
83 emu->num_ports = 1;
84 } else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) {
85 snd_printk("too many ports."
86 "limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS);
87 emu->num_ports = SNDRV_EMUX_MAX_PORTS;
88 }
89
90 memset(&pinfo, 0, sizeof(pinfo));
91 pinfo.owner = THIS_MODULE;
92 pinfo.use = snd_emux_use;
93 pinfo.unuse = snd_emux_unuse;
94 pinfo.event_input = snd_emux_event_input;
95
96 for (i = 0; i < emu->num_ports; i++) {
97 snd_emux_port_t *p;
98
99 sprintf(tmpname, "%s Port %d", emu->name, i);
100 p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS,
101 0, &pinfo);
102 if (p == NULL) {
103 snd_printk("can't create port\n");
104 return -ENOMEM;
105 }
106
107 p->port_mode = SNDRV_EMUX_PORT_MODE_MIDI;
108 snd_emux_init_port(p);
109 emu->ports[i] = p->chset.port;
110 emu->portptrs[i] = p;
111 }
112
113 return 0;
114}
115
116
117/*
118 * Detach from the ports that were set up for this synthesizer and
119 * destroy the kernel client.
120 */
121void
122snd_emux_detach_seq(snd_emux_t *emu)
123{
124 if (emu->voices)
125 snd_emux_terminate_all(emu);
126
127 down(&emu->register_mutex);
128 if (emu->client >= 0) {
129 snd_seq_delete_kernel_client(emu->client);
130 emu->client = -1;
131 }
132 up(&emu->register_mutex);
133}
134
135
136/*
137 * create a sequencer port and channel_set
138 */
139
140snd_emux_port_t *
141snd_emux_create_port(snd_emux_t *emu, char *name,
142 int max_channels, int oss_port,
143 snd_seq_port_callback_t *callback)
144{
145 snd_emux_port_t *p;
146 int i, type, cap;
147
148 /* Allocate structures for this channel */
149 if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
150 snd_printk("no memory\n");
151 return NULL;
152 }
153 p->chset.channels = kcalloc(max_channels, sizeof(snd_midi_channel_t), GFP_KERNEL);
154 if (p->chset.channels == NULL) {
155 snd_printk("no memory\n");
156 kfree(p);
157 return NULL;
158 }
159 for (i = 0; i < max_channels; i++)
160 p->chset.channels[i].number = i;
161 p->chset.private_data = p;
162 p->chset.max_channels = max_channels;
163 p->emu = emu;
164 p->chset.client = emu->client;
165#ifdef SNDRV_EMUX_USE_RAW_EFFECT
166 snd_emux_create_effect(p);
167#endif
168 callback->private_free = free_port;
169 callback->private_data = p;
170
171 cap = SNDRV_SEQ_PORT_CAP_WRITE;
172 if (oss_port) {
173 type = SNDRV_SEQ_PORT_TYPE_SPECIFIC;
174 } else {
175 type = DEFAULT_MIDI_TYPE;
176 cap |= SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
177 }
178
179 p->chset.port = snd_seq_event_port_attach(emu->client, callback,
180 cap, type, max_channels,
181 emu->max_voices, name);
182
183 return p;
184}
185
186
187/*
188 * release memory block for port
189 */
190static void
191free_port(void *private_data)
192{
193 snd_emux_port_t *p;
194
195 p = private_data;
196 if (p) {
197#ifdef SNDRV_EMUX_USE_RAW_EFFECT
198 snd_emux_delete_effect(p);
199#endif
200 kfree(p->chset.channels);
201 kfree(p);
202 }
203}
204
205
206#define DEFAULT_DRUM_FLAGS (1<<9)
207
208/*
209 * initialize the port specific parameters
210 */
211static void
212snd_emux_init_port(snd_emux_port_t *p)
213{
214 p->drum_flags = DEFAULT_DRUM_FLAGS;
215 p->volume_atten = 0;
216
217 snd_emux_reset_port(p);
218}
219
220
221/*
222 * reset port
223 */
224void
225snd_emux_reset_port(snd_emux_port_t *port)
226{
227 int i;
228
229 /* stop all sounds */
230 snd_emux_sounds_off_all(port);
231
232 snd_midi_channel_set_clear(&port->chset);
233
234#ifdef SNDRV_EMUX_USE_RAW_EFFECT
235 snd_emux_clear_effect(port);
236#endif
237
238 /* set port specific control parameters */
239 port->ctrls[EMUX_MD_DEF_BANK] = 0;
240 port->ctrls[EMUX_MD_DEF_DRUM] = 0;
241 port->ctrls[EMUX_MD_REALTIME_PAN] = 1;
242
243 for (i = 0; i < port->chset.max_channels; i++) {
244 snd_midi_channel_t *chan = port->chset.channels + i;
245 chan->drum_channel = ((port->drum_flags >> i) & 1) ? 1 : 0;
246 }
247}
248
249
250/*
251 * input sequencer event
252 */
253int
254snd_emux_event_input(snd_seq_event_t *ev, int direct, void *private_data,
255 int atomic, int hop)
256{
257 snd_emux_port_t *port;
258
259 port = private_data;
260 snd_assert(port != NULL && ev != NULL, return -EINVAL);
261
262 snd_midi_process_event(&emux_ops, ev, &port->chset);
263
264 return 0;
265}
266
267
268/*
269 * increment usage count
270 */
271int
272snd_emux_inc_count(snd_emux_t *emu)
273{
274 emu->used++;
275 if (!try_module_get(emu->ops.owner))
276 goto __error;
277 if (!try_module_get(emu->card->module)) {
278 module_put(emu->ops.owner);
279 __error:
280 emu->used--;
281 return 0;
282 }
283 return 1;
284}
285
286
287/*
288 * decrease usage count
289 */
290void
291snd_emux_dec_count(snd_emux_t *emu)
292{
293 module_put(emu->card->module);
294 emu->used--;
295 if (emu->used <= 0)
296 snd_emux_terminate_all(emu);
297 module_put(emu->ops.owner);
298}
299
300
301/*
302 * Routine that is called upon a first use of a particular port
303 */
304static int
305snd_emux_use(void *private_data, snd_seq_port_subscribe_t *info)
306{
307 snd_emux_port_t *p;
308 snd_emux_t *emu;
309
310 p = private_data;
311 snd_assert(p != NULL, return -EINVAL);
312 emu = p->emu;
313 snd_assert(emu != NULL, return -EINVAL);
314
315 down(&emu->register_mutex);
316 snd_emux_init_port(p);
317 snd_emux_inc_count(emu);
318 up(&emu->register_mutex);
319 return 0;
320}
321
322/*
323 * Routine that is called upon the last unuse() of a particular port.
324 */
325static int
326snd_emux_unuse(void *private_data, snd_seq_port_subscribe_t *info)
327{
328 snd_emux_port_t *p;
329 snd_emux_t *emu;
330
331 p = private_data;
332 snd_assert(p != NULL, return -EINVAL);
333 emu = p->emu;
334 snd_assert(emu != NULL, return -EINVAL);
335
336 down(&emu->register_mutex);
337 snd_emux_sounds_off_all(p);
338 snd_emux_dec_count(emu);
339 up(&emu->register_mutex);
340 return 0;
341}
342
343
344/*
345 * Create a sequencer client
346 */
347static int
348get_client(snd_card_t *card, int index, char *name)
349{
350 snd_seq_client_callback_t callbacks;
351 snd_seq_client_info_t cinfo;
352 int client;
353
354 memset(&callbacks, 0, sizeof(callbacks));
355 callbacks.private_data = NULL;
356 callbacks.allow_input = 1;
357 callbacks.allow_output = 1;
358
359 /* Find a free client, start from 1 as the MPU expects to use 0 */
360 client = snd_seq_create_kernel_client(card, index, &callbacks);
361 if (client < 0)
362 return client;
363
364 memset(&cinfo, 0, sizeof(cinfo));
365 cinfo.client = client;
366 cinfo.type = KERNEL_CLIENT;
367 strcpy(cinfo.name, name);
368 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
369
370 return client;
371}
372
373
374/*
375 * attach virtual rawmidi devices
376 */
377int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card)
378{
379 int i;
380
381 emu->vmidi = NULL;
382 if (emu->midi_ports <= 0)
383 return 0;
384
385 emu->vmidi = kcalloc(emu->midi_ports, sizeof(snd_rawmidi_t*), GFP_KERNEL);
386 if (emu->vmidi == NULL)
387 return -ENOMEM;
388
389 for (i = 0; i < emu->midi_ports; i++) {
390 snd_rawmidi_t *rmidi;
391 snd_virmidi_dev_t *rdev;
392 if (snd_virmidi_new(card, emu->midi_devidx + i, &rmidi) < 0)
393 goto __error;
394 rdev = rmidi->private_data;
395 sprintf(rmidi->name, "%s Synth MIDI", emu->name);
396 rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH;
397 rdev->client = emu->client;
398 rdev->port = emu->ports[i];
399 if (snd_device_register(card, rmidi) < 0) {
400 snd_device_free(card, rmidi);
401 goto __error;
402 }
403 emu->vmidi[i] = rmidi;
404 //snd_printk("virmidi %d ok\n", i);
405 }
406 return 0;
407
408__error:
409 //snd_printk("error init..\n");
410 snd_emux_delete_virmidi(emu);
411 return -ENOMEM;
412}
413
414int snd_emux_delete_virmidi(snd_emux_t *emu)
415{
416 int i;
417
418 if (emu->vmidi == NULL)
419 return 0;
420
421 for (i = 0; i < emu->midi_ports; i++) {
422 if (emu->vmidi[i])
423 snd_device_free(emu->card, emu->vmidi[i]);
424 }
425 kfree(emu->vmidi);
426 emu->vmidi = NULL;
427 return 0;
428}
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
new file mode 100644
index 000000000000..f13b038329eb
--- /dev/null
+++ b/sound/synth/emux/emux_synth.c
@@ -0,0 +1,963 @@
1/*
2 * Midi synth routines for the Emu8k/Emu10k1
3 *
4 * Copyright (C) 1999 Steve Ratcliffe
5 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
6 *
7 * Contains code based on awe_wave.c by Takashi Iwai
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include "emux_voice.h"
26#include <sound/asoundef.h>
27
28/*
29 * Prototypes
30 */
31
32/*
33 * Ensure a value is between two points
34 * macro evaluates its args more than once, so changed to upper-case.
35 */
36#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
37#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
38
39static int get_zone(snd_emux_t *emu, snd_emux_port_t *port, int *notep, int vel, snd_midi_channel_t *chan, snd_sf_zone_t **table);
40static int get_bank(snd_emux_port_t *port, snd_midi_channel_t *chan);
41static void terminate_note1(snd_emux_t *emu, int note, snd_midi_channel_t *chan, int free);
42static void exclusive_note_off(snd_emux_t *emu, snd_emux_port_t *port, int exclass);
43static void terminate_voice(snd_emux_t *emu, snd_emux_voice_t *vp, int free);
44static void update_voice(snd_emux_t *emu, snd_emux_voice_t *vp, int update);
45static void setup_voice(snd_emux_voice_t *vp);
46static int calc_pan(snd_emux_voice_t *vp);
47static int calc_volume(snd_emux_voice_t *vp);
48static int calc_pitch(snd_emux_voice_t *vp);
49
50
51/*
52 * Start a note.
53 */
54void
55snd_emux_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
56{
57 snd_emux_t *emu;
58 int i, key, nvoices;
59 snd_emux_voice_t *vp;
60 snd_sf_zone_t *table[SNDRV_EMUX_MAX_MULTI_VOICES];
61 unsigned long flags;
62 snd_emux_port_t *port;
63
64 port = p;
65 snd_assert(port != NULL && chan != NULL, return);
66
67 emu = port->emu;
68 snd_assert(emu != NULL, return);
69 snd_assert(emu->ops.get_voice != NULL, return);
70 snd_assert(emu->ops.trigger != NULL, return);
71
72 key = note; /* remember the original note */
73 nvoices = get_zone(emu, port, &note, vel, chan, table);
74 if (! nvoices)
75 return;
76
77 /* exclusive note off */
78 for (i = 0; i < nvoices; i++) {
79 snd_sf_zone_t *zp = table[i];
80 if (zp && zp->v.exclusiveClass)
81 exclusive_note_off(emu, port, zp->v.exclusiveClass);
82 }
83
84#if 0 // seems not necessary
85 /* Turn off the same note on the same channel. */
86 terminate_note1(emu, key, chan, 0);
87#endif
88
89 spin_lock_irqsave(&emu->voice_lock, flags);
90 for (i = 0; i < nvoices; i++) {
91
92 /* set up each voice parameter */
93 /* at this stage, we don't trigger the voice yet. */
94
95 if (table[i] == NULL)
96 continue;
97
98 vp = emu->ops.get_voice(emu, port);
99 if (vp == NULL || vp->ch < 0)
100 continue;
101 snd_assert(vp->emu != NULL && vp->hw != NULL, return);
102 if (STATE_IS_PLAYING(vp->state))
103 emu->ops.terminate(vp);
104
105 vp->time = emu->use_time++;
106 vp->chan = chan;
107 vp->port = port;
108 vp->key = key;
109 vp->note = note;
110 vp->velocity = vel;
111 vp->zone = table[i];
112 if (vp->zone->sample)
113 vp->block = vp->zone->sample->block;
114 else
115 vp->block = NULL;
116
117 setup_voice(vp);
118
119 vp->state = SNDRV_EMUX_ST_STANDBY;
120 if (emu->ops.prepare) {
121 vp->state = SNDRV_EMUX_ST_OFF;
122 if (emu->ops.prepare(vp) >= 0)
123 vp->state = SNDRV_EMUX_ST_STANDBY;
124 }
125 }
126
127 /* start envelope now */
128 for (i = 0; i < emu->max_voices; i++) {
129 vp = &emu->voices[i];
130 if (vp->state == SNDRV_EMUX_ST_STANDBY &&
131 vp->chan == chan) {
132 emu->ops.trigger(vp);
133 vp->state = SNDRV_EMUX_ST_ON;
134 vp->ontime = jiffies; /* remember the trigger timing */
135 }
136 }
137 spin_unlock_irqrestore(&emu->voice_lock, flags);
138
139#ifdef SNDRV_EMUX_USE_RAW_EFFECT
140 if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {
141 /* clear voice position for the next note on this channel */
142 snd_emux_effect_table_t *fx = chan->private;
143 if (fx) {
144 fx->flag[EMUX_FX_SAMPLE_START] = 0;
145 fx->flag[EMUX_FX_COARSE_SAMPLE_START] = 0;
146 }
147 }
148#endif
149}
150
151/*
152 * Release a note in response to a midi note off.
153 */
154void
155snd_emux_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
156{
157 int ch;
158 snd_emux_t *emu;
159 snd_emux_voice_t *vp;
160 unsigned long flags;
161 snd_emux_port_t *port;
162
163 port = p;
164 snd_assert(port != NULL && chan != NULL, return);
165
166 emu = port->emu;
167 snd_assert(emu != NULL, return);
168 snd_assert(emu->ops.release != NULL, return);
169
170 spin_lock_irqsave(&emu->voice_lock, flags);
171 for (ch = 0; ch < emu->max_voices; ch++) {
172 vp = &emu->voices[ch];
173 if (STATE_IS_PLAYING(vp->state) &&
174 vp->chan == chan && vp->key == note) {
175 vp->time = emu->use_time++;
176 vp->state = SNDRV_EMUX_ST_RELEASED;
177 if (vp->ontime == jiffies) {
178 /* if note-off is sent too shortly after
179 * note-on, emuX engine cannot produce the sound
180 * correctly. so we'll release this note
181 * a bit later via timer callback.
182 */
183 vp->state = SNDRV_EMUX_ST_PENDING;
184 if (! emu->timer_active) {
185 emu->tlist.expires = jiffies + 1;
186 add_timer(&emu->tlist);
187 emu->timer_active = 1;
188 }
189 } else
190 /* ok now release the note */
191 emu->ops.release(vp);
192 }
193 }
194 spin_unlock_irqrestore(&emu->voice_lock, flags);
195}
196
197/*
198 * timer callback
199 *
200 * release the pending note-offs
201 */
202void snd_emux_timer_callback(unsigned long data)
203{
204 snd_emux_t *emu = (snd_emux_t*) data;
205 snd_emux_voice_t *vp;
206 int ch, do_again = 0;
207
208 spin_lock(&emu->voice_lock);
209 for (ch = 0; ch < emu->max_voices; ch++) {
210 vp = &emu->voices[ch];
211 if (vp->state == SNDRV_EMUX_ST_PENDING) {
212 if (vp->ontime == jiffies)
213 do_again++; /* release this at the next interrupt */
214 else {
215 emu->ops.release(vp);
216 vp->state = SNDRV_EMUX_ST_RELEASED;
217 }
218 }
219 }
220 if (do_again) {
221 emu->tlist.expires = jiffies + 1;
222 add_timer(&emu->tlist);
223 emu->timer_active = 1;
224 } else
225 emu->timer_active = 0;
226 spin_unlock(&emu->voice_lock);
227}
228
229/*
230 * key pressure change
231 */
232void
233snd_emux_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
234{
235 int ch;
236 snd_emux_t *emu;
237 snd_emux_voice_t *vp;
238 unsigned long flags;
239 snd_emux_port_t *port;
240
241 port = p;
242 snd_assert(port != NULL && chan != NULL, return);
243
244 emu = port->emu;
245 snd_assert(emu != NULL, return);
246 snd_assert(emu->ops.update != NULL, return);
247
248 spin_lock_irqsave(&emu->voice_lock, flags);
249 for (ch = 0; ch < emu->max_voices; ch++) {
250 vp = &emu->voices[ch];
251 if (vp->state == SNDRV_EMUX_ST_ON &&
252 vp->chan == chan && vp->key == note) {
253 vp->velocity = vel;
254 update_voice(emu, vp, SNDRV_EMUX_UPDATE_VOLUME);
255 }
256 }
257 spin_unlock_irqrestore(&emu->voice_lock, flags);
258}
259
260
261/*
262 * Modulate the voices which belong to the channel
263 */
264void
265snd_emux_update_channel(snd_emux_port_t *port, snd_midi_channel_t *chan, int update)
266{
267 snd_emux_t *emu;
268 snd_emux_voice_t *vp;
269 int i;
270 unsigned long flags;
271
272 if (! update)
273 return;
274
275 emu = port->emu;
276 snd_assert(emu != NULL, return);
277 snd_assert(emu->ops.update != NULL, return);
278
279 spin_lock_irqsave(&emu->voice_lock, flags);
280 for (i = 0; i < emu->max_voices; i++) {
281 vp = &emu->voices[i];
282 if (vp->chan == chan)
283 update_voice(emu, vp, update);
284 }
285 spin_unlock_irqrestore(&emu->voice_lock, flags);
286}
287
288/*
289 * Modulate all the voices which belong to the port.
290 */
291void
292snd_emux_update_port(snd_emux_port_t *port, int update)
293{
294 snd_emux_t *emu;
295 snd_emux_voice_t *vp;
296 int i;
297 unsigned long flags;
298
299 if (! update)
300 return;
301
302 emu = port->emu;
303 snd_assert(emu != NULL, return);
304 snd_assert(emu->ops.update != NULL, return);
305
306 spin_lock_irqsave(&emu->voice_lock, flags);
307 for (i = 0; i < emu->max_voices; i++) {
308 vp = &emu->voices[i];
309 if (vp->port == port)
310 update_voice(emu, vp, update);
311 }
312 spin_unlock_irqrestore(&emu->voice_lock, flags);
313}
314
315
316/*
317 * Deal with a controler type event. This includes all types of
318 * control events, not just the midi controllers
319 */
320void
321snd_emux_control(void *p, int type, snd_midi_channel_t *chan)
322{
323 snd_emux_port_t *port;
324
325 port = p;
326 snd_assert(port != NULL && chan != NULL, return);
327
328 switch (type) {
329 case MIDI_CTL_MSB_MAIN_VOLUME:
330 case MIDI_CTL_MSB_EXPRESSION:
331 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_VOLUME);
332 break;
333
334 case MIDI_CTL_MSB_PAN:
335 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN);
336 break;
337
338 case MIDI_CTL_SOFT_PEDAL:
339#ifdef SNDRV_EMUX_USE_RAW_EFFECT
340 /* FIXME: this is an emulation */
341 snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, -160,
342 EMUX_FX_FLAG_ADD);
343#endif
344 break;
345
346 case MIDI_CTL_PITCHBEND:
347 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PITCH);
348 break;
349
350 case MIDI_CTL_MSB_MODWHEEL:
351 case MIDI_CTL_CHAN_PRESSURE:
352 snd_emux_update_channel(port, chan,
353 SNDRV_EMUX_UPDATE_FMMOD |
354 SNDRV_EMUX_UPDATE_FM2FRQ2);
355 break;
356
357 }
358
359 if (port->chset.midi_mode == SNDRV_MIDI_MODE_XG) {
360 snd_emux_xg_control(port, chan, type);
361 }
362}
363
364
365/*
366 * terminate note - if free flag is true, free the terminated voice
367 */
368static void
369terminate_note1(snd_emux_t *emu, int note, snd_midi_channel_t *chan, int free)
370{
371 int i;
372 snd_emux_voice_t *vp;
373 unsigned long flags;
374
375 spin_lock_irqsave(&emu->voice_lock, flags);
376 for (i = 0; i < emu->max_voices; i++) {
377 vp = &emu->voices[i];
378 if (STATE_IS_PLAYING(vp->state) && vp->chan == chan &&
379 vp->key == note)
380 terminate_voice(emu, vp, free);
381 }
382 spin_unlock_irqrestore(&emu->voice_lock, flags);
383}
384
385
386/*
387 * terminate note - exported for midi emulation
388 */
389void
390snd_emux_terminate_note(void *p, int note, snd_midi_channel_t *chan)
391{
392 snd_emux_t *emu;
393 snd_emux_port_t *port;
394
395 port = p;
396 snd_assert(port != NULL && chan != NULL, return);
397
398 emu = port->emu;
399 snd_assert(emu != NULL, return);
400 snd_assert(emu->ops.terminate != NULL, return);
401
402 terminate_note1(emu, note, chan, 1);
403}
404
405
406/*
407 * Terminate all the notes
408 */
409void
410snd_emux_terminate_all(snd_emux_t *emu)
411{
412 int i;
413 snd_emux_voice_t *vp;
414 unsigned long flags;
415
416 spin_lock_irqsave(&emu->voice_lock, flags);
417 for (i = 0; i < emu->max_voices; i++) {
418 vp = &emu->voices[i];
419 if (STATE_IS_PLAYING(vp->state))
420 terminate_voice(emu, vp, 0);
421 if (vp->state == SNDRV_EMUX_ST_OFF) {
422 if (emu->ops.free_voice)
423 emu->ops.free_voice(vp);
424 if (emu->ops.reset)
425 emu->ops.reset(emu, i);
426 }
427 vp->time = 0;
428 }
429 /* initialize allocation time */
430 emu->use_time = 0;
431 spin_unlock_irqrestore(&emu->voice_lock, flags);
432}
433
434
435/*
436 * Terminate all voices associated with the given port
437 */
438void
439snd_emux_sounds_off_all(snd_emux_port_t *port)
440{
441 int i;
442 snd_emux_t *emu;
443 snd_emux_voice_t *vp;
444 unsigned long flags;
445
446 snd_assert(port != NULL, return);
447 emu = port->emu;
448 snd_assert(emu != NULL, return);
449 snd_assert(emu->ops.terminate != NULL, return);
450
451 spin_lock_irqsave(&emu->voice_lock, flags);
452 for (i = 0; i < emu->max_voices; i++) {
453 vp = &emu->voices[i];
454 if (STATE_IS_PLAYING(vp->state) &&
455 vp->port == port)
456 terminate_voice(emu, vp, 0);
457 if (vp->state == SNDRV_EMUX_ST_OFF) {
458 if (emu->ops.free_voice)
459 emu->ops.free_voice(vp);
460 if (emu->ops.reset)
461 emu->ops.reset(emu, i);
462 }
463 }
464 spin_unlock_irqrestore(&emu->voice_lock, flags);
465}
466
467
468/*
469 * Terminate all voices that have the same exclusive class. This
470 * is mainly for drums.
471 */
472static void
473exclusive_note_off(snd_emux_t *emu, snd_emux_port_t *port, int exclass)
474{
475 snd_emux_voice_t *vp;
476 int i;
477 unsigned long flags;
478
479 spin_lock_irqsave(&emu->voice_lock, flags);
480 for (i = 0; i < emu->max_voices; i++) {
481 vp = &emu->voices[i];
482 if (STATE_IS_PLAYING(vp->state) && vp->port == port &&
483 vp->reg.exclusiveClass == exclass) {
484 terminate_voice(emu, vp, 0);
485 }
486 }
487 spin_unlock_irqrestore(&emu->voice_lock, flags);
488}
489
490/*
491 * terminate a voice
492 * if free flag is true, call free_voice after termination
493 */
494static void
495terminate_voice(snd_emux_t *emu, snd_emux_voice_t *vp, int free)
496{
497 emu->ops.terminate(vp);
498 vp->time = emu->use_time++;
499 vp->chan = NULL;
500 vp->port = NULL;
501 vp->zone = NULL;
502 vp->block = NULL;
503 vp->state = SNDRV_EMUX_ST_OFF;
504 if (free && emu->ops.free_voice)
505 emu->ops.free_voice(vp);
506}
507
508
509/*
510 * Modulate the voice
511 */
512static void
513update_voice(snd_emux_t *emu, snd_emux_voice_t *vp, int update)
514{
515 if (!STATE_IS_PLAYING(vp->state))
516 return;
517
518 if (vp->chan == NULL || vp->port == NULL)
519 return;
520 if (update & SNDRV_EMUX_UPDATE_VOLUME)
521 calc_volume(vp);
522 if (update & SNDRV_EMUX_UPDATE_PITCH)
523 calc_pitch(vp);
524 if (update & SNDRV_EMUX_UPDATE_PAN) {
525 if (! calc_pan(vp) && (update == SNDRV_EMUX_UPDATE_PAN))
526 return;
527 }
528 emu->ops.update(vp, update);
529}
530
531
532#if 0 // not used
533/* table for volume target calculation */
534static unsigned short voltarget[16] = {
535 0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58,
536 0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90
537};
538#endif
539
540#define LO_BYTE(v) ((v) & 0xff)
541#define HI_BYTE(v) (((v) >> 8) & 0xff)
542
543/*
544 * Sets up the voice structure by calculating some values that
545 * will be needed later.
546 */
547static void
548setup_voice(snd_emux_voice_t *vp)
549{
550 soundfont_voice_parm_t *parm;
551 int pitch;
552
553 /* copy the original register values */
554 vp->reg = vp->zone->v;
555
556#ifdef SNDRV_EMUX_USE_RAW_EFFECT
557 snd_emux_setup_effect(vp);
558#endif
559
560 /* reset status */
561 vp->apan = -1;
562 vp->avol = -1;
563 vp->apitch = -1;
564
565 calc_volume(vp);
566 calc_pitch(vp);
567 calc_pan(vp);
568
569 parm = &vp->reg.parm;
570
571 /* compute filter target and correct modulation parameters */
572 if (LO_BYTE(parm->modatkhld) >= 0x80 && parm->moddelay >= 0x8000) {
573 parm->moddelay = 0xbfff;
574 pitch = (HI_BYTE(parm->pefe) << 4) + vp->apitch;
575 if (pitch > 0xffff)
576 pitch = 0xffff;
577 /* calculate filter target */
578 vp->ftarget = parm->cutoff + LO_BYTE(parm->pefe);
579 LIMITVALUE(vp->ftarget, 0, 255);
580 vp->ftarget <<= 8;
581 } else {
582 vp->ftarget = parm->cutoff;
583 vp->ftarget <<= 8;
584 pitch = vp->apitch;
585 }
586
587 /* compute pitch target */
588 if (pitch != 0xffff) {
589 vp->ptarget = 1 << (pitch >> 12);
590 if (pitch & 0x800) vp->ptarget += (vp->ptarget*0x102e)/0x2710;
591 if (pitch & 0x400) vp->ptarget += (vp->ptarget*0x764)/0x2710;
592 if (pitch & 0x200) vp->ptarget += (vp->ptarget*0x389)/0x2710;
593 vp->ptarget += (vp->ptarget >> 1);
594 if (vp->ptarget > 0xffff) vp->ptarget = 0xffff;
595 } else
596 vp->ptarget = 0xffff;
597
598 if (LO_BYTE(parm->modatkhld) >= 0x80) {
599 parm->modatkhld &= ~0xff;
600 parm->modatkhld |= 0x7f;
601 }
602
603 /* compute volume target and correct volume parameters */
604 vp->vtarget = 0;
605#if 0 /* FIXME: this leads to some clicks.. */
606 if (LO_BYTE(parm->volatkhld) >= 0x80 && parm->voldelay >= 0x8000) {
607 parm->voldelay = 0xbfff;
608 vp->vtarget = voltarget[vp->avol % 0x10] >> (vp->avol >> 4);
609 }
610#endif
611
612 if (LO_BYTE(parm->volatkhld) >= 0x80) {
613 parm->volatkhld &= ~0xff;
614 parm->volatkhld |= 0x7f;
615 }
616}
617
618/*
619 * calculate pitch parameter
620 */
621static unsigned char pan_volumes[256] = {
6220x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,
6230x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,
6240x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,
6250x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92,
6260x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab,
6270xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0,
6280xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,
6290xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf,
6300xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9,
6310xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1,
6320xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7,
6330xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,
6340xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
6350xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
6360xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
6370xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
638};
639
640static int
641calc_pan(snd_emux_voice_t *vp)
642{
643 snd_midi_channel_t *chan = vp->chan;
644 int pan;
645
646 /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
647 if (vp->reg.fixpan > 0) /* 0-127 */
648 pan = 255 - (int)vp->reg.fixpan * 2;
649 else {
650 pan = chan->control[MIDI_CTL_MSB_PAN] - 64;
651 if (vp->reg.pan >= 0) /* 0-127 */
652 pan += vp->reg.pan - 64;
653 pan = 127 - (int)pan * 2;
654 }
655 LIMITVALUE(pan, 0, 255);
656
657 if (vp->emu->linear_panning) {
658 /* assuming linear volume */
659 if (pan != vp->apan) {
660 vp->apan = pan;
661 if (pan == 0)
662 vp->aaux = 0xff;
663 else
664 vp->aaux = (-pan) & 0xff;
665 return 1;
666 } else
667 return 0;
668 } else {
669 /* using volume table */
670 if (vp->apan != (int)pan_volumes[pan]) {
671 vp->apan = pan_volumes[pan];
672 vp->aaux = pan_volumes[255 - pan];
673 return 1;
674 }
675 return 0;
676 }
677}
678
679
680/*
681 * calculate volume attenuation
682 *
683 * Voice volume is controlled by volume attenuation parameter.
684 * So volume becomes maximum when avol is 0 (no attenuation), and
685 * minimum when 255 (-96dB or silence).
686 */
687
688/* tables for volume->attenuation calculation */
689static unsigned char voltab1[128] = {
690 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
691 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
692 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
693 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
694 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
695 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
696 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
697 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
698 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
699 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
700 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
701 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
702 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
703};
704
705static unsigned char voltab2[128] = {
706 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
707 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
708 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
709 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
710 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
711 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
712 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
713 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
714 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
715 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
716 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
717 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
718 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
719};
720
721static unsigned char expressiontab[128] = {
722 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
723 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
724 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
725 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
726 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
727 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
728 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
729 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
730 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
731 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
732 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
733 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
734 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
735};
736
737/*
738 * Magic to calculate the volume (actually attenuation) from all the
739 * voice and channels parameters.
740 */
741static int
742calc_volume(snd_emux_voice_t *vp)
743{
744 int vol;
745 int main_vol, expression_vol, master_vol;
746 snd_midi_channel_t *chan = vp->chan;
747 snd_emux_port_t *port = vp->port;
748
749 expression_vol = chan->control[MIDI_CTL_MSB_EXPRESSION];
750 LIMITMAX(vp->velocity, 127);
751 LIMITVALUE(expression_vol, 0, 127);
752 if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {
753 /* 0 - 127 */
754 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME];
755 vol = (vp->velocity * main_vol * expression_vol) / (127*127);
756 vol = vol * vp->reg.amplitude / 127;
757
758 LIMITVALUE(vol, 0, 127);
759
760 /* calc to attenuation */
761 vol = snd_sf_vol_table[vol];
762
763 } else {
764 main_vol = chan->control[MIDI_CTL_MSB_MAIN_VOLUME] * vp->reg.amplitude / 127;
765 LIMITVALUE(main_vol, 0, 127);
766
767 vol = voltab1[main_vol] + voltab2[vp->velocity];
768 vol = (vol * 8) / 3;
769 vol += vp->reg.attenuation;
770 vol += ((0x100 - vol) * expressiontab[expression_vol])/128;
771 }
772
773 master_vol = port->chset.gs_master_volume;
774 LIMITVALUE(master_vol, 0, 127);
775 vol += snd_sf_vol_table[master_vol];
776 vol += port->volume_atten;
777
778#ifdef SNDRV_EMUX_USE_RAW_EFFECT
779 if (chan->private) {
780 snd_emux_effect_table_t *fx = chan->private;
781 vol += fx->val[EMUX_FX_ATTEN];
782 }
783#endif
784
785 LIMITVALUE(vol, 0, 255);
786 if (vp->avol == vol)
787 return 0; /* value unchanged */
788
789 vp->avol = vol;
790 if (!SF_IS_DRUM_BANK(get_bank(port, chan))
791 && LO_BYTE(vp->reg.parm.volatkhld) < 0x7d) {
792 int atten;
793 if (vp->velocity < 70)
794 atten = 70;
795 else
796 atten = vp->velocity;
797 vp->acutoff = (atten * vp->reg.parm.cutoff + 0xa0) >> 7;
798 } else {
799 vp->acutoff = vp->reg.parm.cutoff;
800 }
801
802 return 1; /* value changed */
803}
804
805/*
806 * calculate pitch offset
807 *
808 * 0xE000 is no pitch offset at 44100Hz sample.
809 * Every 4096 is one octave.
810 */
811
812static int
813calc_pitch(snd_emux_voice_t *vp)
814{
815 snd_midi_channel_t *chan = vp->chan;
816 int offset;
817
818 /* calculate offset */
819 if (vp->reg.fixkey >= 0) {
820 offset = (vp->reg.fixkey - vp->reg.root) * 4096 / 12;
821 } else {
822 offset = (vp->note - vp->reg.root) * 4096 / 12;
823 }
824 offset = (offset * vp->reg.scaleTuning) / 100;
825 offset += vp->reg.tune * 4096 / 1200;
826 if (chan->midi_pitchbend != 0) {
827 /* (128 * 8192: 1 semitone) ==> (4096: 12 semitones) */
828 offset += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 3072;
829 }
830
831 /* tuning via RPN:
832 * coarse = -8192 to 8192 (100 cent per 128)
833 * fine = -8192 to 8192 (max=100cent)
834 */
835 /* 4096 = 1200 cents in emu8000 parameter */
836 offset += chan->gm_rpn_coarse_tuning * 4096 / (12 * 128);
837 offset += chan->gm_rpn_fine_tuning / 24;
838
839#ifdef SNDRV_EMUX_USE_RAW_EFFECT
840 /* add initial pitch correction */
841 if (chan->private) {
842 snd_emux_effect_table_t *fx = chan->private;
843 if (fx->flag[EMUX_FX_INIT_PITCH])
844 offset += fx->val[EMUX_FX_INIT_PITCH];
845 }
846#endif
847
848 /* 0xe000: root pitch */
849 offset += 0xe000 + vp->reg.rate_offset;
850 offset += vp->emu->pitch_shift;
851 LIMITVALUE(offset, 0, 0xffff);
852 if (offset == vp->apitch)
853 return 0; /* unchanged */
854 vp->apitch = offset;
855 return 1; /* value changed */
856}
857
858/*
859 * Get the bank number assigned to the channel
860 */
861static int
862get_bank(snd_emux_port_t *port, snd_midi_channel_t *chan)
863{
864 int val;
865
866 switch (port->chset.midi_mode) {
867 case SNDRV_MIDI_MODE_XG:
868 val = chan->control[MIDI_CTL_MSB_BANK];
869 if (val == 127)
870 return 128; /* return drum bank */
871 return chan->control[MIDI_CTL_LSB_BANK];
872
873 case SNDRV_MIDI_MODE_GS:
874 if (chan->drum_channel)
875 return 128;
876 /* ignore LSB (bank map) */
877 return chan->control[MIDI_CTL_MSB_BANK];
878
879 default:
880 if (chan->drum_channel)
881 return 128;
882 return chan->control[MIDI_CTL_MSB_BANK];
883 }
884}
885
886
887/* Look for the zones matching with the given note and velocity.
888 * The resultant zones are stored on table.
889 */
890static int
891get_zone(snd_emux_t *emu, snd_emux_port_t *port,
892 int *notep, int vel, snd_midi_channel_t *chan, snd_sf_zone_t **table)
893{
894 int preset, bank, def_preset, def_bank;
895
896 bank = get_bank(port, chan);
897 preset = chan->midi_program;
898
899 if (SF_IS_DRUM_BANK(bank)) {
900 def_preset = port->ctrls[EMUX_MD_DEF_DRUM];
901 def_bank = bank;
902 } else {
903 def_preset = preset;
904 def_bank = port->ctrls[EMUX_MD_DEF_BANK];
905 }
906
907 return snd_soundfont_search_zone(emu->sflist, notep, vel, preset, bank,
908 def_preset, def_bank,
909 table, SNDRV_EMUX_MAX_MULTI_VOICES);
910}
911
912/*
913 */
914void
915snd_emux_init_voices(snd_emux_t *emu)
916{
917 snd_emux_voice_t *vp;
918 int i;
919 unsigned long flags;
920
921 spin_lock_irqsave(&emu->voice_lock, flags);
922 for (i = 0; i < emu->max_voices; i++) {
923 vp = &emu->voices[i];
924 vp->ch = -1; /* not used */
925 vp->state = SNDRV_EMUX_ST_OFF;
926 vp->chan = NULL;
927 vp->port = NULL;
928 vp->time = 0;
929 vp->emu = emu;
930 vp->hw = emu->hw;
931 }
932 spin_unlock_irqrestore(&emu->voice_lock, flags);
933}
934
935/*
936 */
937void snd_emux_lock_voice(snd_emux_t *emu, int voice)
938{
939 unsigned long flags;
940
941 spin_lock_irqsave(&emu->voice_lock, flags);
942 if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF)
943 emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED;
944 else
945 snd_printk("invalid voice for lock %d (state = %x)\n",
946 voice, emu->voices[voice].state);
947 spin_unlock_irqrestore(&emu->voice_lock, flags);
948}
949
950/*
951 */
952void snd_emux_unlock_voice(snd_emux_t *emu, int voice)
953{
954 unsigned long flags;
955
956 spin_lock_irqsave(&emu->voice_lock, flags);
957 if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED)
958 emu->voices[voice].state = SNDRV_EMUX_ST_OFF;
959 else
960 snd_printk("invalid voice for unlock %d (state = %x)\n",
961 voice, emu->voices[voice].state);
962 spin_unlock_irqrestore(&emu->voice_lock, flags);
963}
diff --git a/sound/synth/emux/emux_voice.h b/sound/synth/emux/emux_voice.h
new file mode 100644
index 000000000000..67eb55348cdf
--- /dev/null
+++ b/sound/synth/emux/emux_voice.h
@@ -0,0 +1,88 @@
1#ifndef __EMUX_VOICE_H
2#define __EMUX_VOICE_H
3
4/*
5 * A structure to keep track of each hardware voice
6 *
7 * Copyright (C) 1999 Steve Ratcliffe
8 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <sound/driver.h>
26#include <linux/wait.h>
27#include <linux/sched.h>
28#include <sound/core.h>
29#include <sound/emux_synth.h>
30
31/* Prototypes for emux_seq.c */
32int snd_emux_init_seq(snd_emux_t *emu, snd_card_t *card, int index);
33void snd_emux_detach_seq(snd_emux_t *emu);
34snd_emux_port_t *snd_emux_create_port(snd_emux_t *emu, char *name, int max_channels, int type, snd_seq_port_callback_t *callback);
35void snd_emux_reset_port(snd_emux_port_t *port);
36int snd_emux_event_input(snd_seq_event_t *ev, int direct, void *private, int atomic, int hop);
37int snd_emux_inc_count(snd_emux_t *emu);
38void snd_emux_dec_count(snd_emux_t *emu);
39int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card);
40int snd_emux_delete_virmidi(snd_emux_t *emu);
41
42/* Prototypes for emux_synth.c */
43void snd_emux_init_voices(snd_emux_t *emu);
44
45void snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan);
46void snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan);
47void snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan);
48void snd_emux_terminate_note(void *p, int note, snd_midi_channel_t *chan);
49void snd_emux_control(void *p, int type, struct snd_midi_channel *chan);
50
51void snd_emux_sounds_off_all(snd_emux_port_t *port);
52void snd_emux_update_channel(snd_emux_port_t *port, snd_midi_channel_t *chan, int update);
53void snd_emux_update_port(snd_emux_port_t *port, int update);
54
55void snd_emux_timer_callback(unsigned long data);
56
57/* emux_effect.c */
58#ifdef SNDRV_EMUX_USE_RAW_EFFECT
59void snd_emux_create_effect(snd_emux_port_t *p);
60void snd_emux_delete_effect(snd_emux_port_t *p);
61void snd_emux_clear_effect(snd_emux_port_t *p);
62void snd_emux_setup_effect(snd_emux_voice_t *vp);
63void snd_emux_send_effect_oss(snd_emux_port_t *port, snd_midi_channel_t *chan, int type, int val);
64void snd_emux_send_effect(snd_emux_port_t *port, snd_midi_channel_t *chan, int type, int val, int mode);
65#endif
66
67/* emux_nrpn.c */
68void snd_emux_sysex(void *private_data, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
69int snd_emux_xg_control(snd_emux_port_t *port, snd_midi_channel_t *chan, int param);
70void snd_emux_nrpn(void *private_data, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset);
71
72/* emux_oss.c */
73void snd_emux_init_seq_oss(snd_emux_t *emu);
74void snd_emux_detach_seq_oss(snd_emux_t *emu);
75
76/* emux_proc.c */
77#ifdef CONFIG_PROC_FS
78void snd_emux_proc_init(snd_emux_t *emu, snd_card_t *card, int device);
79void snd_emux_proc_free(snd_emux_t *emu);
80#endif
81
82#define STATE_IS_PLAYING(s) ((s) & SNDRV_EMUX_ST_ON)
83
84/* emux_hwdep.c */
85int snd_emux_init_hwdep(snd_emux_t *emu);
86void snd_emux_delete_hwdep(snd_emux_t *emu);
87
88#endif
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
new file mode 100644
index 000000000000..901a7db05bde
--- /dev/null
+++ b/sound/synth/emux/soundfont.c
@@ -0,0 +1,1462 @@
1/*
2 * Soundfont generic routines.
3 * It is intended that these should be used by any driver that is willing
4 * to accept soundfont patches.
5 *
6 * Copyright (C) 1999 Steve Ratcliffe
7 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23/*
24 * Deal with reading in of a soundfont. Code follows the OSS way
25 * of doing things so that the old sfxload utility can be used.
26 * Everything may change when there is an alsa way of doing things.
27 */
28#include <sound/driver.h>
29#include <asm/uaccess.h>
30#include <linux/slab.h>
31#include <sound/core.h>
32#include <sound/soundfont.h>
33#include <sound/seq_oss_legacy.h>
34
35/* Prototypes for static functions */
36
37static int open_patch(snd_sf_list_t *sflist, const char __user *data, int count, int client);
38static snd_soundfont_t *newsf(snd_sf_list_t *sflist, int type, char *name);
39static int is_identical_font(snd_soundfont_t *sf, int type, unsigned char *name);
40static int close_patch(snd_sf_list_t *sflist);
41static int probe_data(snd_sf_list_t *sflist, int sample_id);
42static void set_zone_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_zone_t *zp);
43static snd_sf_zone_t *sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf);
44static void set_sample_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp);
45static snd_sf_sample_t *sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf);
46static void sf_sample_delete(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp);
47static int load_map(snd_sf_list_t *sflist, const void __user *data, int count);
48static int load_info(snd_sf_list_t *sflist, const void __user *data, long count);
49static int remove_info(snd_sf_list_t *sflist, snd_soundfont_t *sf, int bank, int instr);
50static void init_voice_info(soundfont_voice_info_t *avp);
51static void init_voice_parm(soundfont_voice_parm_t *pp);
52static snd_sf_sample_t *set_sample(snd_soundfont_t *sf, soundfont_voice_info_t *avp);
53static snd_sf_sample_t *find_sample(snd_soundfont_t *sf, int sample_id);
54static int load_data(snd_sf_list_t *sflist, const void __user *data, long count);
55static void rebuild_presets(snd_sf_list_t *sflist);
56static void add_preset(snd_sf_list_t *sflist, snd_sf_zone_t *cur);
57static void delete_preset(snd_sf_list_t *sflist, snd_sf_zone_t *zp);
58static snd_sf_zone_t *search_first_zone(snd_sf_list_t *sflist, int bank, int preset, int key);
59static int search_zones(snd_sf_list_t *sflist, int *notep, int vel, int preset, int bank, snd_sf_zone_t **table, int max_layers, int level);
60static int get_index(int bank, int instr, int key);
61static void snd_sf_init(snd_sf_list_t *sflist);
62static void snd_sf_clear(snd_sf_list_t *sflist);
63
64/*
65 * lock access to sflist
66 */
67static void
68lock_preset(snd_sf_list_t *sflist)
69{
70 unsigned long flags;
71 down(&sflist->presets_mutex);
72 spin_lock_irqsave(&sflist->lock, flags);
73 sflist->presets_locked = 1;
74 spin_unlock_irqrestore(&sflist->lock, flags);
75}
76
77
78/*
79 * remove lock
80 */
81static void
82unlock_preset(snd_sf_list_t *sflist)
83{
84 unsigned long flags;
85 spin_lock_irqsave(&sflist->lock, flags);
86 sflist->presets_locked = 0;
87 spin_unlock_irqrestore(&sflist->lock, flags);
88 up(&sflist->presets_mutex);
89}
90
91
92/*
93 * close the patch if the patch was opened by this client.
94 */
95int
96snd_soundfont_close_check(snd_sf_list_t *sflist, int client)
97{
98 unsigned long flags;
99 spin_lock_irqsave(&sflist->lock, flags);
100 if (sflist->open_client == client) {
101 spin_unlock_irqrestore(&sflist->lock, flags);
102 return close_patch(sflist);
103 }
104 spin_unlock_irqrestore(&sflist->lock, flags);
105 return 0;
106}
107
108
109/*
110 * Deal with a soundfont patch. Any driver could use these routines
111 * although it was designed for the AWE64.
112 *
113 * The sample_write and callargs pararameters allow a callback into
114 * the actual driver to write sample data to the board or whatever
115 * it wants to do with it.
116 */
117int
118snd_soundfont_load(snd_sf_list_t *sflist, const void __user *data, long count, int client)
119{
120 soundfont_patch_info_t patch;
121 unsigned long flags;
122 int rc;
123
124 if (count < (long)sizeof(patch)) {
125 snd_printk("patch record too small %ld\n", count);
126 return -EINVAL;
127 }
128 if (copy_from_user(&patch, data, sizeof(patch)))
129 return -EFAULT;
130
131 count -= sizeof(patch);
132 data += sizeof(patch);
133
134 if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) {
135 snd_printk("'The wrong kind of patch' %x\n", patch.key);
136 return -EINVAL;
137 }
138 if (count < patch.len) {
139 snd_printk("Patch too short %ld, need %d\n", count, patch.len);
140 return -EINVAL;
141 }
142 if (patch.len < 0) {
143 snd_printk("poor length %d\n", patch.len);
144 return -EINVAL;
145 }
146
147 if (patch.type == SNDRV_SFNT_OPEN_PATCH) {
148 /* grab sflist to open */
149 lock_preset(sflist);
150 rc = open_patch(sflist, data, count, client);
151 unlock_preset(sflist);
152 return rc;
153 }
154
155 /* check if other client already opened patch */
156 spin_lock_irqsave(&sflist->lock, flags);
157 if (sflist->open_client != client) {
158 spin_unlock_irqrestore(&sflist->lock, flags);
159 return -EBUSY;
160 }
161 spin_unlock_irqrestore(&sflist->lock, flags);
162
163 lock_preset(sflist);
164 rc = -EINVAL;
165 switch (patch.type) {
166 case SNDRV_SFNT_LOAD_INFO:
167 rc = load_info(sflist, data, count);
168 break;
169 case SNDRV_SFNT_LOAD_DATA:
170 rc = load_data(sflist, data, count);
171 break;
172 case SNDRV_SFNT_CLOSE_PATCH:
173 rc = close_patch(sflist);
174 break;
175 case SNDRV_SFNT_REPLACE_DATA:
176 /*rc = replace_data(&patch, data, count);*/
177 break;
178 case SNDRV_SFNT_MAP_PRESET:
179 rc = load_map(sflist, data, count);
180 break;
181 case SNDRV_SFNT_PROBE_DATA:
182 rc = probe_data(sflist, patch.optarg);
183 break;
184 case SNDRV_SFNT_REMOVE_INFO:
185 /* patch must be opened */
186 if (sflist->currsf) {
187 snd_printk("soundfont: remove_info: patch not opened\n");
188 rc = -EINVAL;
189 } else {
190 int bank, instr;
191 bank = ((unsigned short)patch.optarg >> 8) & 0xff;
192 instr = (unsigned short)patch.optarg & 0xff;
193 if (! remove_info(sflist, sflist->currsf, bank, instr))
194 rc = -EINVAL;
195 else
196 rc = 0;
197 }
198 break;
199 }
200 unlock_preset(sflist);
201
202 return rc;
203}
204
205
206/* check if specified type is special font (GUS or preset-alias) */
207static inline int
208is_special_type(int type)
209{
210 type &= 0x0f;
211 return (type == SNDRV_SFNT_PAT_TYPE_GUS ||
212 type == SNDRV_SFNT_PAT_TYPE_MAP);
213}
214
215
216/* open patch; create sf list */
217static int
218open_patch(snd_sf_list_t *sflist, const char __user *data, int count, int client)
219{
220 soundfont_open_parm_t parm;
221 snd_soundfont_t *sf;
222 unsigned long flags;
223
224 spin_lock_irqsave(&sflist->lock, flags);
225 if (sflist->open_client >= 0 || sflist->currsf) {
226 spin_unlock_irqrestore(&sflist->lock, flags);
227 return -EBUSY;
228 }
229 spin_unlock_irqrestore(&sflist->lock, flags);
230
231 if (copy_from_user(&parm, data, sizeof(parm)))
232 return -EFAULT;
233
234 if (is_special_type(parm.type)) {
235 parm.type |= SNDRV_SFNT_PAT_SHARED;
236 sf = newsf(sflist, parm.type, NULL);
237 } else
238 sf = newsf(sflist, parm.type, parm.name);
239 if (sf == NULL) {
240 return -ENOMEM;
241 }
242
243 spin_lock_irqsave(&sflist->lock, flags);
244 sflist->open_client = client;
245 sflist->currsf = sf;
246 spin_unlock_irqrestore(&sflist->lock, flags);
247
248 return 0;
249}
250
251/*
252 * Allocate a new soundfont structure.
253 */
254static snd_soundfont_t *
255newsf(snd_sf_list_t *sflist, int type, char *name)
256{
257 snd_soundfont_t *sf;
258
259 /* check the shared fonts */
260 if (type & SNDRV_SFNT_PAT_SHARED) {
261 for (sf = sflist->fonts; sf; sf = sf->next) {
262 if (is_identical_font(sf, type, name)) {
263 return sf;
264 }
265 }
266 }
267
268 /* not found -- create a new one */
269 sf = kcalloc(1, sizeof(*sf), GFP_KERNEL);
270 if (sf == NULL)
271 return NULL;
272 sf->id = sflist->fonts_size;
273 sflist->fonts_size++;
274
275 /* prepend this record */
276 sf->next = sflist->fonts;
277 sflist->fonts = sf;
278
279 sf->type = type;
280 sf->zones = NULL;
281 sf->samples = NULL;
282 if (name)
283 memcpy(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN);
284
285 return sf;
286}
287
288/* check if the given name matches to the existing list */
289static int
290is_identical_font(snd_soundfont_t *sf, int type, unsigned char *name)
291{
292 return ((sf->type & SNDRV_SFNT_PAT_SHARED) &&
293 (sf->type & 0x0f) == (type & 0x0f) &&
294 (name == NULL ||
295 memcmp(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN) == 0));
296}
297
298/*
299 * Close the current patch.
300 */
301static int
302close_patch(snd_sf_list_t *sflist)
303{
304 unsigned long flags;
305
306 spin_lock_irqsave(&sflist->lock, flags);
307 sflist->currsf = NULL;
308 sflist->open_client = -1;
309 spin_unlock_irqrestore(&sflist->lock, flags);
310
311 rebuild_presets(sflist);
312
313 return 0;
314
315}
316
317/* probe sample in the current list -- nothing to be loaded */
318static int
319probe_data(snd_sf_list_t *sflist, int sample_id)
320{
321 /* patch must be opened */
322 if (sflist->currsf) {
323 /* search the specified sample by optarg */
324 if (find_sample(sflist->currsf, sample_id))
325 return 0;
326 }
327 return -EINVAL;
328}
329
330/*
331 * increment zone counter
332 */
333static void
334set_zone_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_zone_t *zp)
335{
336 zp->counter = sflist->zone_counter++;
337 if (sf->type & SNDRV_SFNT_PAT_LOCKED)
338 sflist->zone_locked = sflist->zone_counter;
339}
340
341/*
342 * allocate a new zone record
343 */
344static snd_sf_zone_t *
345sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
346{
347 snd_sf_zone_t *zp;
348
349 if ((zp = kcalloc(1, sizeof(*zp), GFP_KERNEL)) == NULL)
350 return NULL;
351 zp->next = sf->zones;
352 sf->zones = zp;
353
354 init_voice_info(&zp->v);
355
356 set_zone_counter(sflist, sf, zp);
357 return zp;
358}
359
360
361/*
362 * increment sample couter
363 */
364static void
365set_sample_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp)
366{
367 sp->counter = sflist->sample_counter++;
368 if (sf->type & SNDRV_SFNT_PAT_LOCKED)
369 sflist->sample_locked = sflist->sample_counter;
370}
371
372/*
373 * allocate a new sample list record
374 */
375static snd_sf_sample_t *
376sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
377{
378 snd_sf_sample_t *sp;
379
380 if ((sp = kcalloc(1, sizeof(*sp), GFP_KERNEL)) == NULL)
381 return NULL;
382
383 sp->next = sf->samples;
384 sf->samples = sp;
385
386 set_sample_counter(sflist, sf, sp);
387 return sp;
388}
389
390/*
391 * delete sample list -- this is an exceptional job.
392 * only the last allocated sample can be deleted.
393 */
394static void
395sf_sample_delete(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp)
396{
397 /* only last sample is accepted */
398 if (sp == sf->samples) {
399 sf->samples = sp->next;
400 kfree(sp);
401 }
402}
403
404
405/* load voice map */
406static int
407load_map(snd_sf_list_t *sflist, const void __user *data, int count)
408{
409 snd_sf_zone_t *zp, *prevp;
410 snd_soundfont_t *sf;
411 soundfont_voice_map_t map;
412
413 /* get the link info */
414 if (count < (int)sizeof(map))
415 return -EINVAL;
416 if (copy_from_user(&map, data, sizeof(map)))
417 return -EFAULT;
418
419 if (map.map_instr < 0 || map.map_instr >= SF_MAX_INSTRUMENTS)
420 return -EINVAL;
421
422 sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_MAP|SNDRV_SFNT_PAT_SHARED, NULL);
423 if (sf == NULL)
424 return -ENOMEM;
425
426 prevp = NULL;
427 for (zp = sf->zones; zp; prevp = zp, zp = zp->next) {
428 if (zp->mapped &&
429 zp->instr == map.map_instr &&
430 zp->bank == map.map_bank &&
431 zp->v.low == map.map_key &&
432 zp->v.start == map.src_instr &&
433 zp->v.end == map.src_bank &&
434 zp->v.fixkey == map.src_key) {
435 /* the same mapping is already present */
436 /* relink this record to the link head */
437 if (prevp) {
438 prevp->next = zp->next;
439 zp->next = sf->zones;
440 sf->zones = zp;
441 }
442 /* update the counter */
443 set_zone_counter(sflist, sf, zp);
444 return 0;
445 }
446 }
447
448 /* create a new zone */
449 if ((zp = sf_zone_new(sflist, sf)) == NULL)
450 return -ENOMEM;
451
452 zp->bank = map.map_bank;
453 zp->instr = map.map_instr;
454 zp->mapped = 1;
455 if (map.map_key >= 0) {
456 zp->v.low = map.map_key;
457 zp->v.high = map.map_key;
458 }
459 zp->v.start = map.src_instr;
460 zp->v.end = map.src_bank;
461 zp->v.fixkey = map.src_key;
462 zp->v.sf_id = sf->id;
463
464 add_preset(sflist, zp);
465
466 return 0;
467}
468
469
470/* remove the present instrument layers */
471static int
472remove_info(snd_sf_list_t *sflist, snd_soundfont_t *sf, int bank, int instr)
473{
474 snd_sf_zone_t *prev, *next, *p;
475 int removed = 0;
476
477 prev = NULL;
478 for (p = sf->zones; p; p = next) {
479 next = p->next;
480 if (! p->mapped &&
481 p->bank == bank && p->instr == instr) {
482 /* remove this layer */
483 if (prev)
484 prev->next = next;
485 else
486 sf->zones = next;
487 removed++;
488 kfree(p);
489 } else
490 prev = p;
491 }
492 if (removed)
493 rebuild_presets(sflist);
494 return removed;
495}
496
497
498/*
499 * Read an info record from the user buffer and save it on the current
500 * open soundfont.
501 */
502static int
503load_info(snd_sf_list_t *sflist, const void __user *data, long count)
504{
505 snd_soundfont_t *sf;
506 snd_sf_zone_t *zone;
507 soundfont_voice_rec_hdr_t hdr;
508 int i;
509
510 /* patch must be opened */
511 if ((sf = sflist->currsf) == NULL)
512 return -EINVAL;
513
514 if (is_special_type(sf->type))
515 return -EINVAL;
516
517 if (count < (long)sizeof(hdr)) {
518 printk("Soundfont error: invalid patch zone length\n");
519 return -EINVAL;
520 }
521 if (copy_from_user((char*)&hdr, data, sizeof(hdr)))
522 return -EFAULT;
523
524 data += sizeof(hdr);
525 count -= sizeof(hdr);
526
527 if (hdr.nvoices <= 0 || hdr.nvoices >= 100) {
528 printk("Soundfont error: Illegal voice number %d\n", hdr.nvoices);
529 return -EINVAL;
530 }
531
532 if (count < (long)sizeof(soundfont_voice_info_t)*hdr.nvoices) {
533 printk("Soundfont Error: patch length(%ld) is smaller than nvoices(%d)\n",
534 count, hdr.nvoices);
535 return -EINVAL;
536 }
537
538 switch (hdr.write_mode) {
539 case SNDRV_SFNT_WR_EXCLUSIVE:
540 /* exclusive mode - if the instrument already exists,
541 return error */
542 for (zone = sf->zones; zone; zone = zone->next) {
543 if (!zone->mapped &&
544 zone->bank == hdr.bank &&
545 zone->instr == hdr.instr)
546 return -EINVAL;
547 }
548 break;
549 case SNDRV_SFNT_WR_REPLACE:
550 /* replace mode - remove the instrument if it already exists */
551 remove_info(sflist, sf, hdr.bank, hdr.instr);
552 break;
553 }
554
555 for (i = 0; i < hdr.nvoices; i++) {
556 snd_sf_zone_t tmpzone;
557
558 /* copy awe_voice_info parameters */
559 if (copy_from_user(&tmpzone.v, data, sizeof(tmpzone.v))) {
560 return -EFAULT;
561 }
562
563 data += sizeof(tmpzone.v);
564 count -= sizeof(tmpzone.v);
565
566 tmpzone.bank = hdr.bank;
567 tmpzone.instr = hdr.instr;
568 tmpzone.mapped = 0;
569 tmpzone.v.sf_id = sf->id;
570 if (tmpzone.v.mode & SNDRV_SFNT_MODE_INIT_PARM)
571 init_voice_parm(&tmpzone.v.parm);
572
573 /* create a new zone */
574 if ((zone = sf_zone_new(sflist, sf)) == NULL) {
575 return -ENOMEM;
576 }
577
578 /* copy the temporary data */
579 zone->bank = tmpzone.bank;
580 zone->instr = tmpzone.instr;
581 zone->v = tmpzone.v;
582
583 /* look up the sample */
584 zone->sample = set_sample(sf, &zone->v);
585 }
586
587 return 0;
588}
589
590
591/* initialize voice_info record */
592static void
593init_voice_info(soundfont_voice_info_t *avp)
594{
595 memset(avp, 0, sizeof(*avp));
596
597 avp->root = 60;
598 avp->high = 127;
599 avp->velhigh = 127;
600 avp->fixkey = -1;
601 avp->fixvel = -1;
602 avp->fixpan = -1;
603 avp->pan = -1;
604 avp->amplitude = 127;
605 avp->scaleTuning = 100;
606
607 init_voice_parm(&avp->parm);
608}
609
610/* initialize voice_parm record:
611 * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0.
612 * Vibrato and Tremolo effects are zero.
613 * Cutoff is maximum.
614 * Chorus and Reverb effects are zero.
615 */
616static void
617init_voice_parm(soundfont_voice_parm_t *pp)
618{
619 memset(pp, 0, sizeof(*pp));
620
621 pp->moddelay = 0x8000;
622 pp->modatkhld = 0x7f7f;
623 pp->moddcysus = 0x7f7f;
624 pp->modrelease = 0x807f;
625
626 pp->voldelay = 0x8000;
627 pp->volatkhld = 0x7f7f;
628 pp->voldcysus = 0x7f7f;
629 pp->volrelease = 0x807f;
630
631 pp->lfo1delay = 0x8000;
632 pp->lfo2delay = 0x8000;
633
634 pp->cutoff = 0xff;
635}
636
637/* search the specified sample */
638static snd_sf_sample_t *
639set_sample(snd_soundfont_t *sf, soundfont_voice_info_t *avp)
640{
641 snd_sf_sample_t *sample;
642
643 sample = find_sample(sf, avp->sample);
644 if (sample == NULL)
645 return NULL;
646
647 /* add in the actual sample offsets:
648 * The voice_info addresses define only the relative offset
649 * from sample pointers. Here we calculate the actual DRAM
650 * offset from sample pointers.
651 */
652 avp->start += sample->v.start;
653 avp->end += sample->v.end;
654 avp->loopstart += sample->v.loopstart;
655 avp->loopend += sample->v.loopend;
656
657 /* copy mode flags */
658 avp->sample_mode = sample->v.mode_flags;
659
660 return sample;
661}
662
663/* find the sample pointer with the given id in the soundfont */
664static snd_sf_sample_t *
665find_sample(snd_soundfont_t *sf, int sample_id)
666{
667 snd_sf_sample_t *p;
668
669 if (sf == NULL)
670 return NULL;
671
672 for (p = sf->samples; p; p = p->next) {
673 if (p->v.sample == sample_id)
674 return p;
675 }
676 return NULL;
677}
678
679
680/*
681 * Load sample information, this can include data to be loaded onto
682 * the soundcard. It can also just be a pointer into soundcard ROM.
683 * If there is data it will be written to the soundcard via the callback
684 * routine.
685 */
686static int
687load_data(snd_sf_list_t *sflist, const void __user *data, long count)
688{
689 snd_soundfont_t *sf;
690 soundfont_sample_info_t sample_info;
691 snd_sf_sample_t *sp;
692 long off;
693
694 /* patch must be opened */
695 if ((sf = sflist->currsf) == NULL)
696 return -EINVAL;
697
698 if (is_special_type(sf->type))
699 return -EINVAL;
700
701 if (copy_from_user(&sample_info, data, sizeof(sample_info)))
702 return -EFAULT;
703
704 off = sizeof(sample_info);
705
706 if (sample_info.size != (count-off)/2)
707 return -EINVAL;
708
709 /* Check for dup */
710 if (find_sample(sf, sample_info.sample)) {
711 /* if shared sample, skip this data */
712 if (sf->type & SNDRV_SFNT_PAT_SHARED)
713 return 0;
714 return -EINVAL;
715 }
716
717 /* Allocate a new sample structure */
718 if ((sp = sf_sample_new(sflist, sf)) == NULL)
719 return -ENOMEM;
720
721 sp->v = sample_info;
722 sp->v.sf_id = sf->id;
723 sp->v.dummy = 0;
724 sp->v.truesize = sp->v.size;
725
726 /*
727 * If there is wave data then load it.
728 */
729 if (sp->v.size > 0) {
730 int rc;
731 rc = sflist->callback.sample_new
732 (sflist->callback.private_data, sp, sflist->memhdr,
733 data + off, count - off);
734 if (rc < 0) {
735 sf_sample_delete(sflist, sf, sp);
736 return rc;
737 }
738 sflist->mem_used += sp->v.truesize;
739 }
740
741 return count;
742}
743
744
745/* log2_tbl[i] = log2(i+128) * 0x10000 */
746static int log_tbl[129] = {
747 0x70000, 0x702df, 0x705b9, 0x7088e, 0x70b5d, 0x70e26, 0x710eb, 0x713aa,
748 0x71663, 0x71918, 0x71bc8, 0x71e72, 0x72118, 0x723b9, 0x72655, 0x728ed,
749 0x72b80, 0x72e0e, 0x73098, 0x7331d, 0x7359e, 0x7381b, 0x73a93, 0x73d08,
750 0x73f78, 0x741e4, 0x7444c, 0x746b0, 0x74910, 0x74b6c, 0x74dc4, 0x75019,
751 0x75269, 0x754b6, 0x75700, 0x75946, 0x75b88, 0x75dc7, 0x76002, 0x7623a,
752 0x7646e, 0x766a0, 0x768cd, 0x76af8, 0x76d1f, 0x76f43, 0x77164, 0x77382,
753 0x7759d, 0x777b4, 0x779c9, 0x77bdb, 0x77dea, 0x77ff5, 0x781fe, 0x78404,
754 0x78608, 0x78808, 0x78a06, 0x78c01, 0x78df9, 0x78fef, 0x791e2, 0x793d2,
755 0x795c0, 0x797ab, 0x79993, 0x79b79, 0x79d5d, 0x79f3e, 0x7a11d, 0x7a2f9,
756 0x7a4d3, 0x7a6ab, 0x7a880, 0x7aa53, 0x7ac24, 0x7adf2, 0x7afbe, 0x7b188,
757 0x7b350, 0x7b515, 0x7b6d8, 0x7b899, 0x7ba58, 0x7bc15, 0x7bdd0, 0x7bf89,
758 0x7c140, 0x7c2f5, 0x7c4a7, 0x7c658, 0x7c807, 0x7c9b3, 0x7cb5e, 0x7cd07,
759 0x7ceae, 0x7d053, 0x7d1f7, 0x7d398, 0x7d538, 0x7d6d6, 0x7d872, 0x7da0c,
760 0x7dba4, 0x7dd3b, 0x7ded0, 0x7e063, 0x7e1f4, 0x7e384, 0x7e512, 0x7e69f,
761 0x7e829, 0x7e9b3, 0x7eb3a, 0x7ecc0, 0x7ee44, 0x7efc7, 0x7f148, 0x7f2c8,
762 0x7f446, 0x7f5c2, 0x7f73d, 0x7f8b7, 0x7fa2f, 0x7fba5, 0x7fd1a, 0x7fe8d,
763 0x80000,
764};
765
766/* convert from linear to log value
767 *
768 * conversion: value = log2(amount / base) * ratio
769 *
770 * argument:
771 * amount = linear value (unsigned, 32bit max)
772 * offset = base offset (:= log2(base) * 0x10000)
773 * ratio = division ratio
774 *
775 */
776int
777snd_sf_linear_to_log(unsigned int amount, int offset, int ratio)
778{
779 int v;
780 int s, low, bit;
781
782 if (amount < 2)
783 return 0;
784 for (bit = 0; ! (amount & 0x80000000L); bit++)
785 amount <<= 1;
786 s = (amount >> 24) & 0x7f;
787 low = (amount >> 16) & 0xff;
788 /* linear approxmimation by lower 8 bit */
789 v = (log_tbl[s + 1] * low + log_tbl[s] * (0x100 - low)) >> 8;
790 v -= offset;
791 v = (v * ratio) >> 16;
792 v += (24 - bit) * ratio;
793 return v;
794}
795
796#define OFFSET_MSEC 653117 /* base = 1000 */
797#define OFFSET_ABSCENT 851781 /* base = 8176 */
798#define OFFSET_SAMPLERATE 1011119 /* base = 44100 */
799
800#define ABSCENT_RATIO 1200
801#define TIMECENT_RATIO 1200
802#define SAMPLERATE_RATIO 4096
803
804/*
805 * mHz to abscent
806 * conversion: abscent = log2(MHz / 8176) * 1200
807 */
808static int
809freq_to_note(int mhz)
810{
811 return snd_sf_linear_to_log(mhz, OFFSET_ABSCENT, ABSCENT_RATIO);
812}
813
814/* convert Hz to AWE32 rate offset:
815 * sample pitch offset for the specified sample rate
816 * rate=44100 is no offset, each 4096 is 1 octave (twice).
817 * eg, when rate is 22050, this offset becomes -4096.
818 *
819 * conversion: offset = log2(Hz / 44100) * 4096
820 */
821static int
822calc_rate_offset(int hz)
823{
824 return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
825}
826
827
828/* calculate GUS envelope time */
829static int
830calc_gus_envelope_time(int rate, int start, int end)
831{
832 int r, p, t;
833 r = (3 - ((rate >> 6) & 3)) * 3;
834 p = rate & 0x3f;
835 t = end - start;
836 if (t < 0) t = -t;
837 if (13 > r)
838 t = t << (13 - r);
839 else
840 t = t >> (r - 13);
841 return (t * 10) / (p * 441);
842}
843
844/* convert envelope time parameter to soundfont parameters */
845
846/* attack & decay/release time table (msec) */
847static short attack_time_tbl[128] = {
84832767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
849707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
850361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
851180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
85290, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
85345, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
85422, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
85511, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
856};
857
858static short decay_time_tbl[128] = {
85932767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
8602828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
8611443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
862691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
863345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
864172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
86586, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
86643, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
867};
868
869/* delay time = 0x8000 - msec/92 */
870int
871snd_sf_calc_parm_hold(int msec)
872{
873 int val = (0x7f * 92 - msec) / 92;
874 if (val < 1) val = 1;
875 if (val >= 126) val = 126;
876 return val;
877}
878
879/* search an index for specified time from given time table */
880static int
881calc_parm_search(int msec, short *table)
882{
883 int left = 1, right = 127, mid;
884 while (left < right) {
885 mid = (left + right) / 2;
886 if (msec < (int)table[mid])
887 left = mid + 1;
888 else
889 right = mid;
890 }
891 return left;
892}
893
894/* attack time: search from time table */
895int
896snd_sf_calc_parm_attack(int msec)
897{
898 return calc_parm_search(msec, attack_time_tbl);
899}
900
901/* decay/release time: search from time table */
902int
903snd_sf_calc_parm_decay(int msec)
904{
905 return calc_parm_search(msec, decay_time_tbl);
906}
907
908int snd_sf_vol_table[128] = {
909 255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49,
910 47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32,
911 31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22,
912 22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16,
913 15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10,
914 10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6,
915 6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3,
916 2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
917};
918
919
920#define calc_gus_sustain(val) (0x7f - snd_sf_vol_table[(val)/2])
921#define calc_gus_attenuation(val) snd_sf_vol_table[(val)/2]
922
923/* load GUS patch */
924static int
925load_guspatch(snd_sf_list_t *sflist, const char __user *data, long count, int client)
926{
927 struct patch_info patch;
928 snd_soundfont_t *sf;
929 snd_sf_zone_t *zone;
930 snd_sf_sample_t *smp;
931 int note, sample_id;
932 int rc;
933
934 if (count < (long)sizeof(patch)) {
935 snd_printk("patch record too small %ld\n", count);
936 return -EINVAL;
937 }
938 if (copy_from_user(&patch, data, sizeof(patch)))
939 return -EFAULT;
940
941 count -= sizeof(patch);
942 data += sizeof(patch);
943
944 sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL);
945 if (sf == NULL)
946 return -ENOMEM;
947 if ((smp = sf_sample_new(sflist, sf)) == NULL)
948 return -ENOMEM;
949 sample_id = sflist->sample_counter;
950 smp->v.sample = sample_id;
951 smp->v.start = 0;
952 smp->v.end = patch.len;
953 smp->v.loopstart = patch.loop_start;
954 smp->v.loopend = patch.loop_end;
955 smp->v.size = patch.len;
956
957 /* set up mode flags */
958 smp->v.mode_flags = 0;
959 if (!(patch.mode & WAVE_16_BITS))
960 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_8BITS;
961 if (patch.mode & WAVE_UNSIGNED)
962 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_UNSIGNED;
963 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_NO_BLANK;
964 if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK)))
965 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_SINGLESHOT;
966 if (patch.mode & WAVE_BIDIR_LOOP)
967 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_BIDIR_LOOP;
968 if (patch.mode & WAVE_LOOP_BACK)
969 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_REVERSE_LOOP;
970
971 if (patch.mode & WAVE_16_BITS) {
972 /* convert to word offsets */
973 smp->v.size /= 2;
974 smp->v.end /= 2;
975 smp->v.loopstart /= 2;
976 smp->v.loopend /= 2;
977 }
978 /*smp->v.loopend++;*/
979
980 smp->v.dummy = 0;
981 smp->v.truesize = 0;
982 smp->v.sf_id = sf->id;
983
984 /* set up voice info */
985 if ((zone = sf_zone_new(sflist, sf)) == NULL) {
986 sf_sample_delete(sflist, sf, smp);
987 return -ENOMEM;
988 }
989
990 /*
991 * load wave data
992 */
993 if (sflist->callback.sample_new) {
994 rc = sflist->callback.sample_new
995 (sflist->callback.private_data, smp, sflist->memhdr, data, count);
996 if (rc < 0) {
997 sf_sample_delete(sflist, sf, smp);
998 return rc;
999 }
1000 /* memory offset is updated after */
1001 }
1002
1003 /* update the memory offset here */
1004 sflist->mem_used += smp->v.truesize;
1005
1006 zone->v.sample = sample_id; /* the last sample */
1007 zone->v.rate_offset = calc_rate_offset(patch.base_freq);
1008 note = freq_to_note(patch.base_note);
1009 zone->v.root = note / 100;
1010 zone->v.tune = -(note % 100);
1011 zone->v.low = (freq_to_note(patch.low_note) + 99) / 100;
1012 zone->v.high = freq_to_note(patch.high_note) / 100;
1013 /* panning position; -128 - 127 => 0-127 */
1014 zone->v.pan = (patch.panning + 128) / 2;
1015#if 0
1016 snd_printk("gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n",
1017 (int)patch.base_freq, zone->v.rate_offset,
1018 zone->v.root, zone->v.tune, zone->v.low, zone->v.high);
1019#endif
1020
1021 /* detuning is ignored */
1022 /* 6points volume envelope */
1023 if (patch.mode & WAVE_ENVELOPES) {
1024 int attack, hold, decay, release;
1025 attack = calc_gus_envelope_time
1026 (patch.env_rate[0], 0, patch.env_offset[0]);
1027 hold = calc_gus_envelope_time
1028 (patch.env_rate[1], patch.env_offset[0],
1029 patch.env_offset[1]);
1030 decay = calc_gus_envelope_time
1031 (patch.env_rate[2], patch.env_offset[1],
1032 patch.env_offset[2]);
1033 release = calc_gus_envelope_time
1034 (patch.env_rate[3], patch.env_offset[1],
1035 patch.env_offset[4]);
1036 release += calc_gus_envelope_time
1037 (patch.env_rate[4], patch.env_offset[3],
1038 patch.env_offset[4]);
1039 release += calc_gus_envelope_time
1040 (patch.env_rate[5], patch.env_offset[4],
1041 patch.env_offset[5]);
1042 zone->v.parm.volatkhld =
1043 (snd_sf_calc_parm_hold(hold) << 8) |
1044 snd_sf_calc_parm_attack(attack);
1045 zone->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
1046 snd_sf_calc_parm_decay(decay);
1047 zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release);
1048 zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);
1049#if 0
1050 snd_printk("gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n",
1051 zone->v.parm.volatkhld,
1052 zone->v.parm.voldcysus,
1053 zone->v.parm.volrelease,
1054 zone->v.attenuation);
1055#endif
1056 }
1057
1058 /* fast release */
1059 if (patch.mode & WAVE_FAST_RELEASE) {
1060 zone->v.parm.volrelease = 0x807f;
1061 }
1062
1063 /* tremolo effect */
1064 if (patch.mode & WAVE_TREMOLO) {
1065 int rate = (patch.tremolo_rate * 1000 / 38) / 42;
1066 zone->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
1067 }
1068 /* vibrato effect */
1069 if (patch.mode & WAVE_VIBRATO) {
1070 int rate = (patch.vibrato_rate * 1000 / 38) / 42;
1071 zone->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
1072 }
1073
1074 /* scale_freq, scale_factor, volume, and fractions not implemented */
1075
1076 if (!(smp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT))
1077 zone->v.mode = SNDRV_SFNT_MODE_LOOPING;
1078 else
1079 zone->v.mode = 0;
1080
1081 /* append to the tail of the list */
1082 /*zone->bank = ctrls[AWE_MD_GUS_BANK];*/
1083 zone->bank = 0;
1084 zone->instr = patch.instr_no;
1085 zone->mapped = 0;
1086 zone->v.sf_id = sf->id;
1087
1088 zone->sample = set_sample(sf, &zone->v);
1089
1090 /* rebuild preset now */
1091 add_preset(sflist, zone);
1092
1093 return 0;
1094}
1095
1096/* load GUS patch */
1097int
1098snd_soundfont_load_guspatch(snd_sf_list_t *sflist, const char __user *data,
1099 long count, int client)
1100{
1101 int rc;
1102 lock_preset(sflist);
1103 rc = load_guspatch(sflist, data, count, client);
1104 unlock_preset(sflist);
1105 return rc;
1106}
1107
1108
1109/*
1110 * Rebuild the preset table. This is like a hash table in that it allows
1111 * quick access to the zone information. For each preset there are zone
1112 * structures linked by next_instr and by next_zone. Former is the whole
1113 * link for this preset, and latter is the link for zone (i.e. instrument/
1114 * bank/key combination).
1115 */
1116static void
1117rebuild_presets(snd_sf_list_t *sflist)
1118{
1119 snd_soundfont_t *sf;
1120 snd_sf_zone_t *cur;
1121
1122 /* clear preset table */
1123 memset(sflist->presets, 0, sizeof(sflist->presets));
1124
1125 /* search all fonts and insert each font */
1126 for (sf = sflist->fonts; sf; sf = sf->next) {
1127 for (cur = sf->zones; cur; cur = cur->next) {
1128 if (! cur->mapped && cur->sample == NULL) {
1129 /* try again to search the corresponding sample */
1130 cur->sample = set_sample(sf, &cur->v);
1131 if (cur->sample == NULL)
1132 continue;
1133 }
1134
1135 add_preset(sflist, cur);
1136 }
1137 }
1138}
1139
1140
1141/*
1142 * add the given zone to preset table
1143 */
1144static void
1145add_preset(snd_sf_list_t *sflist, snd_sf_zone_t *cur)
1146{
1147 snd_sf_zone_t *zone;
1148 int index;
1149
1150 zone = search_first_zone(sflist, cur->bank, cur->instr, cur->v.low);
1151 if (zone && zone->v.sf_id != cur->v.sf_id) {
1152 /* different instrument was already defined */
1153 snd_sf_zone_t *p;
1154 /* compare the allocated time */
1155 for (p = zone; p; p = p->next_zone) {
1156 if (p->counter > cur->counter)
1157 /* the current is older.. skipped */
1158 return;
1159 }
1160 /* remove old zones */
1161 delete_preset(sflist, zone);
1162 zone = NULL; /* do not forget to clear this! */
1163 }
1164
1165 /* prepend this zone */
1166 if ((index = get_index(cur->bank, cur->instr, cur->v.low)) < 0)
1167 return;
1168 cur->next_zone = zone; /* zone link */
1169 cur->next_instr = sflist->presets[index]; /* preset table link */
1170 sflist->presets[index] = cur;
1171}
1172
1173/*
1174 * delete the given zones from preset_table
1175 */
1176static void
1177delete_preset(snd_sf_list_t *sflist, snd_sf_zone_t *zp)
1178{
1179 int index;
1180 snd_sf_zone_t *p;
1181
1182 if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0)
1183 return;
1184 for (p = sflist->presets[index]; p; p = p->next_instr) {
1185 while (p->next_instr == zp) {
1186 p->next_instr = zp->next_instr;
1187 zp = zp->next_zone;
1188 if (zp == NULL)
1189 return;
1190 }
1191 }
1192}
1193
1194
1195/*
1196 * Search matching zones from preset table.
1197 * The note can be rewritten by preset mapping (alias).
1198 * The found zones are stored on 'table' array. max_layers defines
1199 * the maximum number of elements in this array.
1200 * This function returns the number of found zones. 0 if not found.
1201 */
1202int
1203snd_soundfont_search_zone(snd_sf_list_t *sflist, int *notep, int vel,
1204 int preset, int bank,
1205 int def_preset, int def_bank,
1206 snd_sf_zone_t **table, int max_layers)
1207{
1208 int nvoices;
1209 unsigned long flags;
1210
1211 /* this function is supposed to be called atomically,
1212 * so we check the lock. if it's busy, just returns 0 to
1213 * tell the caller the busy state
1214 */
1215 spin_lock_irqsave(&sflist->lock, flags);
1216 if (sflist->presets_locked) {
1217 spin_unlock_irqrestore(&sflist->lock, flags);
1218 return 0;
1219 }
1220 nvoices = search_zones(sflist, notep, vel, preset, bank, table, max_layers, 0);
1221 if (! nvoices) {
1222 if (preset != def_preset || bank != def_bank)
1223 nvoices = search_zones(sflist, notep, vel, def_preset, def_bank, table, max_layers, 0);
1224 }
1225 spin_unlock_irqrestore(&sflist->lock, flags);
1226 return nvoices;
1227}
1228
1229
1230/*
1231 * search the first matching zone
1232 */
1233static snd_sf_zone_t *
1234search_first_zone(snd_sf_list_t *sflist, int bank, int preset, int key)
1235{
1236 int index;
1237 snd_sf_zone_t *zp;
1238
1239 if ((index = get_index(bank, preset, key)) < 0)
1240 return NULL;
1241 for (zp = sflist->presets[index]; zp; zp = zp->next_instr) {
1242 if (zp->instr == preset && zp->bank == bank)
1243 return zp;
1244 }
1245 return NULL;
1246}
1247
1248
1249/*
1250 * search matching zones from sflist. can be called recursively.
1251 */
1252static int
1253search_zones(snd_sf_list_t *sflist, int *notep, int vel, int preset, int bank, snd_sf_zone_t **table, int max_layers, int level)
1254{
1255 snd_sf_zone_t *zp;
1256 int nvoices;
1257
1258 zp = search_first_zone(sflist, bank, preset, *notep);
1259 nvoices = 0;
1260 for (; zp; zp = zp->next_zone) {
1261 if (*notep >= zp->v.low && *notep <= zp->v.high &&
1262 vel >= zp->v.vellow && vel <= zp->v.velhigh) {
1263 if (zp->mapped) {
1264 /* search preset mapping (aliasing) */
1265 int key = zp->v.fixkey;
1266 preset = zp->v.start;
1267 bank = zp->v.end;
1268
1269 if (level > 5) /* too deep alias level */
1270 return 0;
1271 if (key < 0)
1272 key = *notep;
1273 nvoices = search_zones(sflist, &key, vel,
1274 preset, bank, table,
1275 max_layers, level + 1);
1276 if (nvoices > 0)
1277 *notep = key;
1278 break;
1279 }
1280 table[nvoices++] = zp;
1281 if (nvoices >= max_layers)
1282 break;
1283 }
1284 }
1285
1286 return nvoices;
1287}
1288
1289
1290/* calculate the index of preset table:
1291 * drums are mapped from 128 to 255 according to its note key.
1292 * other instruments are mapped from 0 to 127.
1293 * if the index is out of range, return -1.
1294 */
1295static int
1296get_index(int bank, int instr, int key)
1297{
1298 int index;
1299 if (SF_IS_DRUM_BANK(bank))
1300 index = key + SF_MAX_INSTRUMENTS;
1301 else
1302 index = instr;
1303 index = index % SF_MAX_PRESETS;
1304 if (index < 0)
1305 return -1;
1306 return index;
1307}
1308
1309/*
1310 * Initialise the sflist structure.
1311 */
1312static void
1313snd_sf_init(snd_sf_list_t *sflist)
1314{
1315 memset(sflist->presets, 0, sizeof(sflist->presets));
1316
1317 sflist->mem_used = 0;
1318 sflist->currsf = NULL;
1319 sflist->open_client = -1;
1320 sflist->fonts = NULL;
1321 sflist->fonts_size = 0;
1322 sflist->zone_counter = 0;
1323 sflist->sample_counter = 0;
1324 sflist->zone_locked = 0;
1325 sflist->sample_locked = 0;
1326}
1327
1328/*
1329 * Release all list records
1330 */
1331static void
1332snd_sf_clear(snd_sf_list_t *sflist)
1333{
1334 snd_soundfont_t *sf, *nextsf;
1335 snd_sf_zone_t *zp, *nextzp;
1336 snd_sf_sample_t *sp, *nextsp;
1337
1338 for (sf = sflist->fonts; sf; sf = nextsf) {
1339 nextsf = sf->next;
1340 for (zp = sf->zones; zp; zp = nextzp) {
1341 nextzp = zp->next;
1342 kfree(zp);
1343 }
1344 for (sp = sf->samples; sp; sp = nextsp) {
1345 nextsp = sp->next;
1346 if (sflist->callback.sample_free)
1347 sflist->callback.sample_free(sflist->callback.private_data, sp, sflist->memhdr);
1348 kfree(sp);
1349 }
1350 kfree(sf);
1351 }
1352
1353 snd_sf_init(sflist);
1354}
1355
1356
1357/*
1358 * Create a new sflist structure
1359 */
1360snd_sf_list_t *
1361snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr)
1362{
1363 snd_sf_list_t *sflist;
1364
1365 if ((sflist = kcalloc(1, sizeof(*sflist), GFP_KERNEL)) == NULL)
1366 return NULL;
1367
1368 init_MUTEX(&sflist->presets_mutex);
1369 spin_lock_init(&sflist->lock);
1370 sflist->memhdr = hdr;
1371
1372 if (callback)
1373 sflist->callback = *callback;
1374
1375 snd_sf_init(sflist);
1376 return sflist;
1377}
1378
1379
1380/*
1381 * Free everything allocated off the sflist structure.
1382 */
1383void
1384snd_sf_free(snd_sf_list_t *sflist)
1385{
1386 if (sflist == NULL)
1387 return;
1388
1389 lock_preset(sflist);
1390 if (sflist->callback.sample_reset)
1391 sflist->callback.sample_reset(sflist->callback.private_data);
1392 snd_sf_clear(sflist);
1393 unlock_preset(sflist);
1394
1395 kfree(sflist);
1396}
1397
1398/*
1399 * Remove all samples
1400 * The soundcard should be silet before calling this function.
1401 */
1402int
1403snd_soundfont_remove_samples(snd_sf_list_t *sflist)
1404{
1405 lock_preset(sflist);
1406 if (sflist->callback.sample_reset)
1407 sflist->callback.sample_reset(sflist->callback.private_data);
1408 snd_sf_clear(sflist);
1409 unlock_preset(sflist);
1410
1411 return 0;
1412}
1413
1414/*
1415 * Remove unlocked samples.
1416 * The soundcard should be silent before calling this function.
1417 */
1418int
1419snd_soundfont_remove_unlocked(snd_sf_list_t *sflist)
1420{
1421 snd_soundfont_t *sf;
1422 snd_sf_zone_t *zp, *nextzp;
1423 snd_sf_sample_t *sp, *nextsp;
1424
1425 lock_preset(sflist);
1426
1427 if (sflist->callback.sample_reset)
1428 sflist->callback.sample_reset(sflist->callback.private_data);
1429
1430 /* to be sure */
1431 memset(sflist->presets, 0, sizeof(sflist->presets));
1432
1433 for (sf = sflist->fonts; sf; sf = sf->next) {
1434 for (zp = sf->zones; zp; zp = nextzp) {
1435 if (zp->counter < sflist->zone_locked)
1436 break;
1437 nextzp = zp->next;
1438 sf->zones = nextzp;
1439 kfree(zp);
1440 }
1441
1442 for (sp = sf->samples; sp; sp = nextsp) {
1443 if (sp->counter < sflist->sample_locked)
1444 break;
1445 nextsp = sp->next;
1446 sf->samples = nextsp;
1447 sflist->mem_used -= sp->v.truesize;
1448 if (sflist->callback.sample_free)
1449 sflist->callback.sample_free(sflist->callback.private_data, sp, sflist->memhdr);
1450 kfree(sp);
1451 }
1452 }
1453
1454 sflist->zone_counter = sflist->zone_locked;
1455 sflist->sample_counter = sflist->sample_locked;
1456
1457 rebuild_presets(sflist);
1458
1459 unlock_preset(sflist);
1460 return 0;
1461}
1462
diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c
new file mode 100644
index 000000000000..8b131a11e549
--- /dev/null
+++ b/sound/synth/util_mem.c
@@ -0,0 +1,207 @@
1/*
2 * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
3 *
4 * Generic memory management routines for soundcard memory allocation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include <sound/util_mem.h>
26
27MODULE_AUTHOR("Takashi Iwai");
28MODULE_DESCRIPTION("Generic memory management routines for soundcard memory allocation");
29MODULE_LICENSE("GPL");
30
31#define get_memblk(p) list_entry(p, snd_util_memblk_t, list)
32
33/*
34 * create a new memory manager
35 */
36snd_util_memhdr_t *
37snd_util_memhdr_new(int memsize)
38{
39 snd_util_memhdr_t *hdr;
40
41 hdr = kcalloc(1, sizeof(*hdr), GFP_KERNEL);
42 if (hdr == NULL)
43 return NULL;
44 hdr->size = memsize;
45 init_MUTEX(&hdr->block_mutex);
46 INIT_LIST_HEAD(&hdr->block);
47
48 return hdr;
49}
50
51/*
52 * free a memory manager
53 */
54void snd_util_memhdr_free(snd_util_memhdr_t *hdr)
55{
56 struct list_head *p;
57
58 snd_assert(hdr != NULL, return);
59 /* release all blocks */
60 while ((p = hdr->block.next) != &hdr->block) {
61 list_del(p);
62 kfree(get_memblk(p));
63 }
64 kfree(hdr);
65}
66
67/*
68 * allocate a memory block (without mutex)
69 */
70snd_util_memblk_t *
71__snd_util_mem_alloc(snd_util_memhdr_t *hdr, int size)
72{
73 snd_util_memblk_t *blk;
74 snd_util_unit_t units, prev_offset;
75 struct list_head *p;
76
77 snd_assert(hdr != NULL, return NULL);
78 snd_assert(size > 0, return NULL);
79
80 /* word alignment */
81 units = size;
82 if (units & 1)
83 units++;
84 if (units > hdr->size)
85 return NULL;
86
87 /* look for empty block */
88 prev_offset = 0;
89 list_for_each(p, &hdr->block) {
90 blk = get_memblk(p);
91 if (blk->offset - prev_offset >= units)
92 goto __found;
93 prev_offset = blk->offset + blk->size;
94 }
95 if (hdr->size - prev_offset < units)
96 return NULL;
97
98__found:
99 return __snd_util_memblk_new(hdr, units, p->prev);
100}
101
102
103/*
104 * create a new memory block with the given size
105 * the block is linked next to prev
106 */
107snd_util_memblk_t *
108__snd_util_memblk_new(snd_util_memhdr_t *hdr, snd_util_unit_t units,
109 struct list_head *prev)
110{
111 snd_util_memblk_t *blk;
112
113 blk = kmalloc(sizeof(snd_util_memblk_t) + hdr->block_extra_size, GFP_KERNEL);
114 if (blk == NULL)
115 return NULL;
116
117 if (! prev || prev == &hdr->block)
118 blk->offset = 0;
119 else {
120 snd_util_memblk_t *p = get_memblk(prev);
121 blk->offset = p->offset + p->size;
122 }
123 blk->size = units;
124 list_add(&blk->list, prev);
125 hdr->nblocks++;
126 hdr->used += units;
127 return blk;
128}
129
130
131/*
132 * allocate a memory block (with mutex)
133 */
134snd_util_memblk_t *
135snd_util_mem_alloc(snd_util_memhdr_t *hdr, int size)
136{
137 snd_util_memblk_t *blk;
138 down(&hdr->block_mutex);
139 blk = __snd_util_mem_alloc(hdr, size);
140 up(&hdr->block_mutex);
141 return blk;
142}
143
144
145/*
146 * remove the block from linked-list and free resource
147 * (without mutex)
148 */
149void
150__snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk)
151{
152 list_del(&blk->list);
153 hdr->nblocks--;
154 hdr->used -= blk->size;
155 kfree(blk);
156}
157
158/*
159 * free a memory block (with mutex)
160 */
161int snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk)
162{
163 snd_assert(hdr && blk, return -EINVAL);
164
165 down(&hdr->block_mutex);
166 __snd_util_mem_free(hdr, blk);
167 up(&hdr->block_mutex);
168 return 0;
169}
170
171/*
172 * return available memory size
173 */
174int snd_util_mem_avail(snd_util_memhdr_t *hdr)
175{
176 unsigned int size;
177 down(&hdr->block_mutex);
178 size = hdr->size - hdr->used;
179 up(&hdr->block_mutex);
180 return size;
181}
182
183
184EXPORT_SYMBOL(snd_util_memhdr_new);
185EXPORT_SYMBOL(snd_util_memhdr_free);
186EXPORT_SYMBOL(snd_util_mem_alloc);
187EXPORT_SYMBOL(snd_util_mem_free);
188EXPORT_SYMBOL(snd_util_mem_avail);
189EXPORT_SYMBOL(__snd_util_mem_alloc);
190EXPORT_SYMBOL(__snd_util_mem_free);
191EXPORT_SYMBOL(__snd_util_memblk_new);
192
193/*
194 * INIT part
195 */
196
197static int __init alsa_util_mem_init(void)
198{
199 return 0;
200}
201
202static void __exit alsa_util_mem_exit(void)
203{
204}
205
206module_init(alsa_util_mem_init)
207module_exit(alsa_util_mem_exit)