- 根目录:
- sound
- isa
- sb
- emu8000_callback.c
#include "emu8000_local.h"
#include <sound/asoundef.h>
static struct snd_emux_voice *get_voice(struct snd_emux *emu,
struct snd_emux_port *port);
static int start_voice(struct snd_emux_voice *vp);
static void trigger_voice(struct snd_emux_voice *vp);
static void release_voice(struct snd_emux_voice *vp);
static void update_voice(struct snd_emux_voice *vp, int update);
static void reset_voice(struct snd_emux *emu, int ch);
static void terminate_voice(struct snd_emux_voice *vp);
static void sysex(struct snd_emux *emu, char *buf, int len, int parsed,
struct snd_midi_channel_set *chset);
#ifdef CONFIG_SND_SEQUENCER_OSS
static int oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2);
#endif
static int load_fx(struct snd_emux *emu, int type, int mode,
const void __user *buf, long len);
static void set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
static void set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
static void set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
static void set_fmmod(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
static void set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
static void set_fm2frq2(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
static void set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
static void snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int ch);
#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
static struct snd_emux_operators emu8000_ops = {
.owner = THIS_MODULE,
.get_voice = get_voice,
.prepare = start_voice,
.trigger = trigger_voice,
.release = release_voice,
.update = update_voice,
.terminate = terminate_voice,
.reset = reset_voice,
.sample_new = snd_emu8000_sample_new,
.sample_free = snd_emu8000_sample_free,
.sample_reset = snd_emu8000_sample_reset,
.load_fx = load_fx,
.sysex = sysex,
#ifdef CONFIG_SND_SEQUENCER_OSS
.oss_ioctl = oss_ioctl,
#endif
};
void
snd_emu8000_ops_setup(struct snd_emu8000 *hw)
{
hw->emu->ops = emu8000_ops;
}
static void
release_voice(struct snd_emux_voice *vp)
{
int dcysusv;
struct snd_emu8000 *hw;
hw = vp->hw;
dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
EMU8000_DCYSUS_WRITE(hw, vp->ch, dcysusv);
dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease;
EMU8000_DCYSUSV_WRITE(hw, vp->ch, dcysusv);
}
static void
terminate_voice(struct snd_emux_voice *vp)
{
struct snd_emu8000 *hw;
hw = vp->hw;
EMU8000_DCYSUSV_WRITE(hw, vp->ch, 0x807F);
}
static void
update_voice(struct snd_emux_voice *vp, int update)
{
struct snd_emu8000 *hw;
hw = vp->hw;
if (update & SNDRV_EMUX_UPDATE_VOLUME)
set_volume(hw, vp);
if (update & SNDRV_EMUX_UPDATE_PITCH)
set_pitch(hw, vp);
if ((update & SNDRV_EMUX_UPDATE_PAN) &&
vp->port->ctrls[EMUX_MD_REALTIME_PAN])
set_pan(hw, vp);
if (update & SNDRV_EMUX_UPDATE_FMMOD)
set_fmmod(hw, vp);
if (update & SNDRV_EMUX_UPDATE_TREMFREQ)
set_tremfreq(hw, vp);
if (update & SNDRV_EMUX_UPDATE_FM2FRQ2)
set_fm2frq2(hw, vp);
if (update & SNDRV_EMUX_UPDATE_Q)
set_filterQ(hw, vp);
}
static struct snd_emux_voice *
get_voice(struct snd_emux *emu, struct snd_emux_port *port)
{
int i;
struct snd_emux_voice *vp;
struct snd_emu8000 *hw;
enum {
OFF=0, RELEASED, PLAYING, END
};
struct best {
unsigned int time;
int voice;
} best[END];
struct best *bp;
hw = emu->hw;
for (i = 0; i < END; i++) {
best[i].time = (unsigned int)(-1); ;
best[i].voice = -1;
}
for (i = 0; i < emu->max_voices; i++) {
int state, val;
vp = &emu->voices[i];
state = vp->state;
if (state == SNDRV_EMUX_ST_OFF)
bp = best + OFF;
else if (state == SNDRV_EMUX_ST_RELEASED ||
state == SNDRV_EMUX_ST_PENDING) {
bp = best + RELEASED;
val = (EMU8000_CVCF_READ(hw, vp->ch) >> 16) & 0xffff;
if (! val)
bp = best + OFF;
}
else if (state & SNDRV_EMUX_ST_ON)
bp = best + PLAYING;
else
continue;
if (state != SNDRV_EMUX_ST_OFF &&
(vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
val = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff;
if (val >= vp->reg.loopstart)
bp = best + OFF;
}
if (vp->time < bp->time) {
bp->time = vp->time;
bp->voice = i;
}
}
for (i = 0; i < END; i++) {
if (best[i].voice >= 0) {
vp = &emu->voices[best[i].voice];
vp->ch = best[i].voice;
return vp;
}
}
return NULL;
}
static int
start_voice(struct snd_emux_voice *vp)
{
unsigned int temp;
int ch;
int addr;
struct snd_midi_channel *chan;
struct snd_emu8000 *hw;
hw = vp->hw;
ch = vp->ch;
chan = vp->chan;
EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080);
EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF);
EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF);
EMU8000_PTRX_WRITE(hw, ch, 0);
EMU8000_CPF_WRITE(hw, ch, 0);
set_pitch(hw, vp);
EMU8000_ENVVAL_WRITE(hw, ch, vp->reg.parm.moddelay);
EMU8000_ATKHLD_WRITE(hw, ch, vp->reg.parm.modatkhld);
EMU8000_DCYSUS_WRITE(hw, ch, vp->reg.parm.moddcysus);
EMU8000_ENVVOL_WRITE(hw, ch, vp->reg.parm.voldelay);
EMU8000_ATKHLDV_WRITE(hw, ch, vp->reg.parm.volatkhld);
set_volume(hw, vp);
EMU8000_PEFE_WRITE(hw, ch, vp->reg.parm.pefe);
EMU8000_LFO1VAL_WRITE(hw, ch, vp->reg.parm.lfo1delay);
EMU8000_LFO2VAL_WRITE(hw, ch, vp->reg.parm.lfo2delay);
set_fmmod(hw, vp);
set_tremfreq(hw, vp);
set_fm2frq2(hw, vp);
set_pan(hw, vp);
addr = vp->reg.loopend - 1;
temp = vp->reg.parm.chorus;
temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10;
LIMITMAX(temp, 255);
temp = (temp <<24) | (unsigned int)addr;
EMU8000_CSL_WRITE(hw, ch, temp);
addr = vp->reg.start - 1;
temp = vp->reg.parm.filterQ;
temp = (temp<<28) | (unsigned int)addr;
EMU8000_CCCA_WRITE(hw, ch, temp);
EMU8000_00A0_WRITE(hw, ch, 0);
EMU8000_0080_WRITE(hw, ch, 0);
temp = vp->vtarget << 16;
EMU8000_VTFT_WRITE(hw, ch, temp | vp->ftarget);
EMU8000_CVCF_WRITE(hw, ch, temp | 0xff00);
return 0;
}
static void
trigger_voice(struct snd_emux_voice *vp)
{
int ch = vp->ch;
unsigned int temp;
struct snd_emu8000 *hw;
hw = vp->hw;
temp = vp->reg.parm.reverb;
temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10;
LIMITMAX(temp, 255);
temp = (temp << 8) | (vp->ptarget << 16) | vp->aaux;
EMU8000_PTRX_WRITE(hw, ch, temp);
EMU8000_CPF_WRITE(hw, ch, vp->ptarget << 16);
EMU8000_DCYSUSV_WRITE(hw, ch, vp->reg.parm.voldcysus);
}
static void
reset_voice(struct snd_emux *emu, int ch)
{
struct snd_emu8000 *hw;
hw = emu->hw;
EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
snd_emu8000_tweak_voice(hw, ch);
}
static void
set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
EMU8000_IP_WRITE(hw, vp->ch, vp->apitch);
}
static void
set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
int ifatn;
ifatn = (unsigned char)vp->acutoff;
ifatn = (ifatn << 8);
ifatn |= (unsigned char)vp->avol;
EMU8000_IFATN_WRITE(hw, vp->ch, ifatn);
}
static void
set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
unsigned int temp;
temp = ((unsigned int)vp->apan<<24) | ((unsigned int)vp->reg.loopstart - 1);
EMU8000_PSST_WRITE(hw, vp->ch, temp);
}
#define MOD_SENSE 18
static void
set_fmmod(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
unsigned short fmmod;
short pitch;
unsigned char cutoff;
int modulation;
pitch = (char)(vp->reg.parm.fmmod>>8);
cutoff = (vp->reg.parm.fmmod & 0xff);
modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
pitch += (MOD_SENSE * modulation) / 1200;
LIMITVALUE(pitch, -128, 127);
fmmod = ((unsigned char)pitch<<8) | cutoff;
EMU8000_FMMOD_WRITE(hw, vp->ch, fmmod);
}
static void
set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
EMU8000_TREMFRQ_WRITE(hw, vp->ch, vp->reg.parm.tremfrq);
}
static void
set_fm2frq2(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
unsigned short fm2frq2;
short pitch;
unsigned char freq;
int modulation;
pitch = (char)(vp->reg.parm.fm2frq2>>8);
freq = vp->reg.parm.fm2frq2 & 0xff;
modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
pitch += (MOD_SENSE * modulation) / 1200;
LIMITVALUE(pitch, -128, 127);
fm2frq2 = ((unsigned char)pitch<<8) | freq;
EMU8000_FM2FRQ2_WRITE(hw, vp->ch, fm2frq2);
}
static void
set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
unsigned int addr;
addr = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff;
addr |= (vp->reg.parm.filterQ << 28);
EMU8000_CCCA_WRITE(hw, vp->ch, addr);
}
static void
snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int i)
{
EMU8000_ENVVOL_WRITE(emu, i, 0x8000);
EMU8000_ENVVAL_WRITE(emu, i, 0x8000);
EMU8000_DCYSUS_WRITE(emu, i, 0x7F7F);
EMU8000_ATKHLDV_WRITE(emu, i, 0x7F7F);
EMU8000_ATKHLD_WRITE(emu, i, 0x7F7F);
EMU8000_PEFE_WRITE(emu, i, 0);
EMU8000_LFO1VAL_WRITE(emu, i, 0x8000);
EMU8000_LFO2VAL_WRITE(emu, i, 0x8000);
EMU8000_IP_WRITE(emu, i, 0xE000);
EMU8000_IFATN_WRITE(emu, i, 0xFF00);
EMU8000_FMMOD_WRITE(emu, i, 0);
EMU8000_TREMFRQ_WRITE(emu, i, 0);
EMU8000_FM2FRQ2_WRITE(emu, i, 0);
}
static void
sysex(struct snd_emux *emu, char *buf, int len, int parsed, struct snd_midi_channel_set *chset)
{
struct snd_emu8000 *hw;
hw = emu->hw;
switch (parsed) {
case SNDRV_MIDI_SYSEX_GS_CHORUS_MODE:
hw->chorus_mode = chset->gs_chorus_mode;
snd_emu8000_update_chorus_mode(hw);
break;
case SNDRV_MIDI_SYSEX_GS_REVERB_MODE:
hw->reverb_mode = chset->gs_reverb_mode;
snd_emu8000_update_reverb_mode(hw);
break;
}
}
#ifdef CONFIG_SND_SEQUENCER_OSS
static int
oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2)
{
struct snd_emu8000 *hw;
hw = emu->hw;
switch (cmd) {
case _EMUX_OSS_REVERB_MODE:
hw->reverb_mode = p1;
snd_emu8000_update_reverb_mode(hw);
break;
case _EMUX_OSS_CHORUS_MODE:
hw->chorus_mode = p1;
snd_emu8000_update_chorus_mode(hw);
break;
case _EMUX_OSS_INITIALIZE_CHIP:
break;
case _EMUX_OSS_EQUALIZER:
hw->bass_level = p1;
hw->treble_level = p2;
snd_emu8000_update_equalizer(hw);
break;
}
return 0;
}
#endif
#define SNDRV_EMU8000_LOAD_CHORUS_FX 0x10
#define SNDRV_EMU8000_LOAD_REVERB_FX 0x11
static int
load_fx(struct snd_emux *emu, int type, int mode, const void __user *buf, long len)
{
struct snd_emu8000 *hw;
hw = emu->hw;
buf += 16;
len -= 16;
switch (type) {
case SNDRV_EMU8000_LOAD_CHORUS_FX:
return snd_emu8000_load_chorus_fx(hw, mode, buf, len);
case SNDRV_EMU8000_LOAD_REVERB_FX:
return snd_emu8000_load_reverb_fx(hw, mode, buf, len);
}
return -EINVAL;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439
- 440
- 441
- 442
- 443
- 444
- 445
- 446
- 447
- 448
- 449
- 450
- 451
- 452
- 453
- 454
- 455
- 456
- 457
- 458
- 459
- 460
- 461
- 462
- 463
- 464
- 465
- 466
- 467
- 468
- 469
- 470
- 471
- 472
- 473
- 474
- 475
- 476
- 477
- 478
- 479
- 480
- 481
- 482
- 483
- 484
- 485
- 486
- 487
- 488
- 489
- 490
- 491
- 492
- 493
- 494
- 495
- 496
- 497
- 498
- 499
- 500
- 501
- 502
- 503
- 504
- 505
- 506
- 507
- 508
- 509
- 510
- 511
- 512
- 513
- 514
- 515
- 516
- 517
- 518
- 519
- 520
- 521
- 522
- 523
- 524
- 525
- 526
- 527
- 528
- 529
- 530
- 531
- 532
- 533
- 534
- 535
- 536
- 537
- 538
- 539
- 540
- 541
- 542
- 543
- 544
- 545
- 546