⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 seq_midi_emul.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
			ops->control(drv, control, chan);		break;	}}/* * initialize the MIDI status */voidsnd_midi_channel_set_clear(snd_midi_channel_set_t *chset){	int i;	chset->midi_mode = SNDRV_MIDI_MODE_GM;	chset->gs_master_volume = 127;	for (i = 0; i < chset->max_channels; i++) {		snd_midi_channel_t *chan = chset->channels + i;		memset(chan->note, 0, sizeof(chan->note));		chan->midi_aftertouch = 0;		chan->midi_pressure = 0;		chan->midi_program = 0;		chan->midi_pitchbend = 0;		snd_midi_reset_controllers(chan);		chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */		chan->gm_rpn_fine_tuning = 0;		chan->gm_rpn_coarse_tuning = 0;		if (i == 9)			chan->drum_channel = 1;		else			chan->drum_channel = 0;	}}/* * Process a rpn message. */static voidrpn(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan,    snd_midi_channel_set_t *chset){	int type;	int val;	if (chset->midi_mode != SNDRV_MIDI_MODE_NONE) {		type = (chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB] << 8) |			chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB];		val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) |			chan->control[MIDI_CTL_LSB_DATA_ENTRY];		switch (type) {		case 0x0000: /* Pitch bend sensitivity */			/* MSB only / 1 semitone per 128 */			chan->gm_rpn_pitch_bend_range = val;			break;							case 0x0001: /* fine tuning: */			/* MSB/LSB, 8192=center, 100/8192 cent step */			chan->gm_rpn_fine_tuning = val - 8192;			break;		case 0x0002: /* coarse tuning */			/* MSB only / 8192=center, 1 semitone per 128 */			chan->gm_rpn_coarse_tuning = val - 8192;			break;		case 0x7F7F: /* "lock-in" RPN */			/* ignored */			break;		}	}	/* should call nrpn or rpn callback here.. */}/* * Process an nrpn message. */static voidnrpn(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan,     snd_midi_channel_set_t *chset){	/* parse XG NRPNs here if possible */	if (ops->nrpn)		ops->nrpn(drv, chan, chset);}/* * convert channel parameter in GS sysex */static intget_channel(unsigned char cmd){	int p = cmd & 0x0f;	if (p == 0)		p = 9;	else if (p < 10)		p--;	return p;}/* * Process a sysex message. */static voidsysex(snd_midi_op_t *ops, void *private, unsigned char *buf, int len, snd_midi_channel_set_t *chset){	/* GM on */	static unsigned char gm_on_macro[] = {		0x7e,0x7f,0x09,0x01,	};	/* XG on */	static unsigned char xg_on_macro[] = {		0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,	};	/* GS prefix	 * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off	 * reverb mode: XX=0x01, YY=0x30, ZZ=0-7	 * chorus mode: XX=0x01, YY=0x38, ZZ=0-7	 * master vol:  XX=0x00, YY=0x04, ZZ=0-127	 */	static unsigned char gs_pfx_macro[] = {		0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/	};	int parsed = SNDRV_MIDI_SYSEX_NOT_PARSED;	if (len <= 0 || buf[0] != 0xf0)		return;	/* skip first byte */	buf++;	len--;	/* GM on */	if (len >= (int)sizeof(gm_on_macro) &&	    memcmp(buf, gm_on_macro, sizeof(gm_on_macro)) == 0) {		if (chset->midi_mode != SNDRV_MIDI_MODE_GS &&		    chset->midi_mode != SNDRV_MIDI_MODE_XG) {			chset->midi_mode = SNDRV_MIDI_MODE_GM;			reset_all_channels(chset);			parsed = SNDRV_MIDI_SYSEX_GM_ON;		}	}	/* GS macros */	else if (len >= 8 &&		 memcmp(buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) {		if (chset->midi_mode != SNDRV_MIDI_MODE_GS &&		    chset->midi_mode != SNDRV_MIDI_MODE_XG)			chset->midi_mode = SNDRV_MIDI_MODE_GS;		if (buf[5] == 0x00 && buf[6] == 0x7f && buf[7] == 0x00) {			/* GS reset */			parsed = SNDRV_MIDI_SYSEX_GS_RESET;			reset_all_channels(chset);		}		else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x15) {			/* drum pattern */			int p = get_channel(buf[5]);			if (p < chset->max_channels) {				parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL;				if (buf[7])					chset->channels[p].drum_channel = 1;				else					chset->channels[p].drum_channel = 0;			}		} else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x21) {			/* program */			int p = get_channel(buf[5]);			if (p < chset->max_channels &&			    ! chset->channels[p].drum_channel) {				parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL;				chset->channels[p].midi_program = buf[7];			}		} else if (buf[5] == 0x01 && buf[6] == 0x30) {			/* reverb mode */			parsed = SNDRV_MIDI_SYSEX_GS_REVERB_MODE;			chset->gs_reverb_mode = buf[7];		} else if (buf[5] == 0x01 && buf[6] == 0x38) {			/* chorus mode */			parsed = SNDRV_MIDI_SYSEX_GS_CHORUS_MODE;			chset->gs_chorus_mode = buf[7];		} else if (buf[5] == 0x00 && buf[6] == 0x04) {			/* master volume */			parsed = SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME;			chset->gs_master_volume = buf[7];		}	}	/* XG on */	else if (len >= (int)sizeof(xg_on_macro) &&		 memcmp(buf, xg_on_macro, sizeof(xg_on_macro)) == 0) {		int i;		chset->midi_mode = SNDRV_MIDI_MODE_XG;		parsed = SNDRV_MIDI_SYSEX_XG_ON;		/* reset CC#0 for drums */		for (i = 0; i < chset->max_channels; i++) {			if (chset->channels[i].drum_channel)				chset->channels[i].control[MIDI_CTL_MSB_BANK] = 127;			else				chset->channels[i].control[MIDI_CTL_MSB_BANK] = 0;		}	}	if (ops->sysex)		ops->sysex(private, buf - 1, len + 1, parsed, chset);}/* * all sound off */static voidall_sounds_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan){	int n;	if (! ops->note_terminate)		return;	for (n = 0; n < 128; n++) {		if (chan->note[n]) {			ops->note_terminate(drv, n, chan);			chan->note[n] = 0;		}	}}/* * all notes off */static voidall_notes_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan){	int n;	if (! ops->note_off)		return;	for (n = 0; n < 128; n++) {		if (chan->note[n] == SNDRV_MIDI_NOTE_ON)			note_off(ops, drv, chan, n, 0);	}}/* * Initialise a single midi channel control block. */static void snd_midi_channel_init(snd_midi_channel_t *p, int n){	if (p == NULL)		return;	memset(p, 0, sizeof(snd_midi_channel_t));	p->private = NULL;	p->number = n;	snd_midi_reset_controllers(p);	p->gm_rpn_pitch_bend_range = 256; /* 2 semitones */	p->gm_rpn_fine_tuning = 0;	p->gm_rpn_coarse_tuning = 0;	if (n == 9)		p->drum_channel = 1;	/* Default ch 10 as drums */}/* * Allocate and initialise a set of midi channel control blocks. */static snd_midi_channel_t *snd_midi_channel_init_set(int n){	snd_midi_channel_t *chan;	int  i;	chan = kmalloc(n * sizeof(snd_midi_channel_t), GFP_KERNEL);	if (chan) {		for (i = 0; i < n; i++)			snd_midi_channel_init(chan+i, i);	}	return chan;}/* * reset all midi channels */static voidreset_all_channels(snd_midi_channel_set_t *chset){	int ch;	for (ch = 0; ch < chset->max_channels; ch++) {		snd_midi_channel_t *chan = chset->channels + ch;		snd_midi_reset_controllers(chan);		chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */		chan->gm_rpn_fine_tuning = 0;		chan->gm_rpn_coarse_tuning = 0;		if (ch == 9)			chan->drum_channel = 1;		else			chan->drum_channel = 0;	}}/* * Allocate and initialise a midi channel set. */snd_midi_channel_set_t *snd_midi_channel_alloc_set(int n){	snd_midi_channel_set_t *chset;	chset = kmalloc(sizeof(*chset), GFP_KERNEL);	if (chset) {		chset->channels = snd_midi_channel_init_set(n);		chset->private_data = NULL;		chset->max_channels = n;	}	return chset;}/* * Reset the midi controllers on a particular channel to default values. */static void snd_midi_reset_controllers(snd_midi_channel_t *chan){	memset(chan->control, 0, sizeof(chan->control));	chan->gm_volume = 127;	chan->gm_expression = 127;	chan->gm_pan = 64;}/* * Free a midi channel set. */void snd_midi_channel_free_set(snd_midi_channel_set_t *chset){	if (chset == NULL)		return;	kfree(chset->channels);	kfree(chset);}static int __init alsa_seq_midi_emul_init(void){	return 0;}static void __exit alsa_seq_midi_emul_exit(void){}module_init(alsa_seq_midi_emul_init)module_exit(alsa_seq_midi_emul_exit)EXPORT_SYMBOL(snd_midi_process_event);EXPORT_SYMBOL(snd_midi_channel_set_clear);EXPORT_SYMBOL(snd_midi_channel_alloc_set);EXPORT_SYMBOL(snd_midi_channel_free_set);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -