OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [synth/] [emux/] [emux_effect.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
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(struct soundfont_voice_parm *, 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
 
51
static 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 */
99
static void
100
effect_set_byte(unsigned char *valp, struct snd_midi_channel *chan, int type)
101
{
102
        short effect;
103
        struct snd_emux_effect_table *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 */
120
static void
121
effect_set_word(unsigned short *valp, struct snd_midi_channel *chan, int type)
122
{
123
        int effect;
124
        struct snd_emux_effect_table *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 */
137
static int
138
effect_get_offset(struct snd_midi_channel *chan, int lo, int hi, int mode)
139
{
140
        int addr = 0;
141
        struct snd_emux_effect_table *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 */
155
void
156
snd_emux_send_effect_oss(struct snd_emux_port *port,
157
                         struct snd_midi_channel *chan, int type, int val)
158
{
159
        int mode;
160
 
161
        if (type & 0x40)
162
                mode = EMUX_FX_FLAG_OFF;
163
        else if (type & 0x80)
164
                mode = EMUX_FX_FLAG_ADD;
165
        else
166
                mode = EMUX_FX_FLAG_SET;
167
        type &= 0x3f;
168
 
169
        snd_emux_send_effect(port, chan, type, val, mode);
170
}
171
#endif
172
 
173
/* Modify the effect value.
174
 * if update is necessary, call emu8000_control
175
 */
176
void
177
snd_emux_send_effect(struct snd_emux_port *port, struct snd_midi_channel *chan,
178
                     int type, int val, int mode)
179
{
180
        int i;
181
        int offset;
182
        unsigned char *srcp, *origp;
183
        struct snd_emux *emu;
184
        struct snd_emux_effect_table *fx;
185
        unsigned long flags;
186
 
187
        emu = port->emu;
188
        fx = chan->private;
189
        if (emu == NULL || fx == NULL)
190
                return;
191
        if (type < 0 || type >= EMUX_NUM_EFFECTS)
192
                return;
193
 
194
        fx->val[type] = val;
195
        fx->flag[type] = mode;
196
 
197
        /* do we need to modify the register in realtime ? */
198
        if (! parm_defs[type].update || (offset = parm_defs[type].offset) < 0)
199
                return;
200
 
201
#ifdef SNDRV_LITTLE_ENDIAN
202
        if (parm_defs[type].type & PARM_IS_ALIGN_HI)
203
                offset++;
204
#else
205
        if (parm_defs[type].type & PARM_IS_ALIGN_LO)
206
                offset++;
207
#endif
208
        /* modify the register values */
209
        spin_lock_irqsave(&emu->voice_lock, flags);
210
        for (i = 0; i < emu->max_voices; i++) {
211
                struct snd_emux_voice *vp = &emu->voices[i];
212
                if (!STATE_IS_PLAYING(vp->state) || vp->chan != chan)
213
                        continue;
214
                srcp = (unsigned char*)&vp->reg.parm + offset;
215
                origp = (unsigned char*)&vp->zone->v.parm + offset;
216
                if (parm_defs[i].type & PARM_IS_BYTE) {
217
                        *srcp = *origp;
218
                        effect_set_byte(srcp, chan, type);
219
                } else {
220
                        *(unsigned short*)srcp = *(unsigned short*)origp;
221
                        effect_set_word((unsigned short*)srcp, chan, type);
222
                }
223
        }
224
        spin_unlock_irqrestore(&emu->voice_lock, flags);
225
 
226
        /* activate them */
227
        snd_emux_update_channel(port, chan, parm_defs[type].update);
228
}
229
 
230
 
231
/* copy wavetable registers to voice table */
232
void
233
snd_emux_setup_effect(struct snd_emux_voice *vp)
234
{
235
        struct snd_midi_channel *chan = vp->chan;
236
        struct snd_emux_effect_table *fx;
237
        unsigned char *srcp;
238
        int i;
239
 
240
        if (! (fx = chan->private))
241
                return;
242
 
243
        /* modify the register values via effect table */
244
        for (i = 0; i < EMUX_FX_END; i++) {
245
                int offset;
246
                if (! fx->flag[i] || (offset = parm_defs[i].offset) < 0)
247
                        continue;
248
#ifdef SNDRV_LITTLE_ENDIAN
249
                if (parm_defs[i].type & PARM_IS_ALIGN_HI)
250
                        offset++;
251
#else
252
                if (parm_defs[i].type & PARM_IS_ALIGN_LO)
253
                        offset++;
254
#endif
255
                srcp = (unsigned char*)&vp->reg.parm + offset;
256
                if (parm_defs[i].type & PARM_IS_BYTE)
257
                        effect_set_byte(srcp, chan, i);
258
                else
259
                        effect_set_word((unsigned short*)srcp, chan, i);
260
        }
261
 
262
        /* correct sample and loop points */
263
        vp->reg.start += effect_get_offset(chan, EMUX_FX_SAMPLE_START,
264
                                           EMUX_FX_COARSE_SAMPLE_START,
265
                                           vp->reg.sample_mode);
266
 
267
        vp->reg.loopstart += effect_get_offset(chan, EMUX_FX_LOOP_START,
268
                                               EMUX_FX_COARSE_LOOP_START,
269
                                               vp->reg.sample_mode);
270
 
271
        vp->reg.loopend += effect_get_offset(chan, EMUX_FX_LOOP_END,
272
                                             EMUX_FX_COARSE_LOOP_END,
273
                                             vp->reg.sample_mode);
274
}
275
 
276
/*
277
 * effect table
278
 */
279
void
280
snd_emux_create_effect(struct snd_emux_port *p)
281
{
282
        int i;
283
        p->effect = kcalloc(p->chset.max_channels,
284
                            sizeof(struct snd_emux_effect_table), GFP_KERNEL);
285
        if (p->effect) {
286
                for (i = 0; i < p->chset.max_channels; i++)
287
                        p->chset.channels[i].private = p->effect + i;
288
        } else {
289
                for (i = 0; i < p->chset.max_channels; i++)
290
                        p->chset.channels[i].private = NULL;
291
        }
292
}
293
 
294
void
295
snd_emux_delete_effect(struct snd_emux_port *p)
296
{
297
        kfree(p->effect);
298
        p->effect = NULL;
299
}
300
 
301
void
302
snd_emux_clear_effect(struct snd_emux_port *p)
303
{
304
        if (p->effect) {
305
                memset(p->effect, 0, sizeof(struct snd_emux_effect_table) *
306
                       p->chset.max_channels);
307
        }
308
}
309
 
310
#endif /* SNDRV_EMUX_USE_RAW_EFFECT */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.