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

📄 sequencer.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * sound/sequencer.c * * The sequencer personality manager. *//* * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. *//* * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed) * Alan Cox	   : reformatted and fixed a pair of null pointer bugs */#include <linux/kmod.h>#define SEQUENCER_C#include "sound_config.h"#include "midi_ctrl.h"static int      sequencer_ok = 0;static struct sound_timer_operations *tmr;static int      tmr_no = -1;	/* Currently selected timer */static int      pending_timer = -1;	/* For timer change operation */extern unsigned long seq_time;static int      obsolete_api_used = 0;/* * Local counts for number of synth and MIDI devices. These are initialized * by the sequencer_open. */static int      max_mididev = 0;static int      max_synthdev = 0;/* * The seq_mode gives the operating mode of the sequencer: *      1 = level1 (the default) *      2 = level2 (extended capabilities) */#define SEQ_1	1#define SEQ_2	2static int      seq_mode = SEQ_1;static DECLARE_WAIT_QUEUE_HEAD(seq_sleeper);static DECLARE_WAIT_QUEUE_HEAD(midi_sleeper);static int      midi_opened[MAX_MIDI_DEV] = {	0};static int      midi_written[MAX_MIDI_DEV] = {	0};static unsigned long prev_input_time = 0;static int      prev_event_time;#include "tuning.h"#define EV_SZ	8#define IEV_SZ	8static unsigned char *queue = NULL;static unsigned char *iqueue = NULL;static volatile int qhead = 0, qtail = 0, qlen = 0;static volatile int iqhead = 0, iqtail = 0, iqlen = 0;static volatile int seq_playing = 0;static volatile int sequencer_busy = 0;static int      output_threshold;static long     pre_event_timeout;static unsigned synth_open_mask;static int      seq_queue(unsigned char *note, char nonblock);static void     seq_startplay(void);static int      seq_sync(void);static void     seq_reset(void);#if MAX_SYNTH_DEV > 15#error Too many synthesizer devices enabled.#endifint sequencer_read(int dev, struct file *file, char *buf, int count){	int c = count, p = 0;	int ev_len;	unsigned long flags;	dev = dev >> 4;	ev_len = seq_mode == SEQ_1 ? 4 : 8;	save_flags(flags);	cli();	if (!iqlen)	{ 		if (file->f_flags & O_NONBLOCK) {  			restore_flags(flags);  			return -EAGAIN;  		} 		interruptible_sleep_on_timeout(&midi_sleeper,					       pre_event_timeout);		if (!iqlen)		{			restore_flags(flags);			return 0;		}	}	while (iqlen && c >= ev_len)	{		char *fixit = (char *) &iqueue[iqhead * IEV_SZ];		copy_to_user(&(buf)[p], fixit, ev_len);		p += ev_len;		c -= ev_len;		iqhead = (iqhead + 1) % SEQ_MAX_QUEUE;		iqlen--;	}	restore_flags(flags);	return count - c;}static void sequencer_midi_output(int dev){	/*	 * Currently NOP	 */}void seq_copy_to_input(unsigned char *event_rec, int len){	unsigned long flags;	/*	 * Verify that the len is valid for the current mode.	 */	if (len != 4 && len != 8)		return;	if ((seq_mode == SEQ_1) != (len == 4))		return;	if (iqlen >= (SEQ_MAX_QUEUE - 1))		return;		/* Overflow */	save_flags(flags);	cli();	memcpy(&iqueue[iqtail * IEV_SZ], event_rec, len);	iqlen++;	iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;	wake_up(&midi_sleeper);	restore_flags(flags);}static void sequencer_midi_input(int dev, unsigned char data){	unsigned int tstamp;	unsigned char event_rec[4];	if (data == 0xfe)	/* Ignore active sensing */		return;	tstamp = jiffies - seq_time;	if (tstamp != prev_input_time)	{		tstamp = (tstamp << 8) | SEQ_WAIT;		seq_copy_to_input((unsigned char *) &tstamp, 4);		prev_input_time = tstamp;	}	event_rec[0] = SEQ_MIDIPUTC;	event_rec[1] = data;	event_rec[2] = dev;	event_rec[3] = 0;	seq_copy_to_input(event_rec, 4);}void seq_input_event(unsigned char *event_rec, int len){	unsigned long this_time;	if (seq_mode == SEQ_2)		this_time = tmr->get_time(tmr_no);	else		this_time = jiffies - seq_time;	if (this_time != prev_input_time)	{		unsigned char   tmp_event[8];		tmp_event[0] = EV_TIMING;		tmp_event[1] = TMR_WAIT_ABS;		tmp_event[2] = 0;		tmp_event[3] = 0;		*(unsigned int *) &tmp_event[4] = this_time;		seq_copy_to_input(tmp_event, 8);		prev_input_time = this_time;	}	seq_copy_to_input(event_rec, len);}int sequencer_write(int dev, struct file *file, const char *buf, int count){	unsigned char event_rec[EV_SZ], ev_code;	int p = 0, c, ev_size;	int err;	int mode = translate_mode(file);	dev = dev >> 4;	DEB(printk("sequencer_write(dev=%d, count=%d)\n", dev, count));	if (mode == OPEN_READ)		return -EIO;	c = count;	while (c >= 4)	{		copy_from_user((char *) event_rec, &(buf)[p], 4);		ev_code = event_rec[0];		if (ev_code == SEQ_FULLSIZE)		{			int err, fmt;			dev = *(unsigned short *) &event_rec[2];			if (dev < 0 || dev >= max_synthdev || synth_devs[dev] == NULL)				return -ENXIO;			if (!(synth_open_mask & (1 << dev)))				return -ENXIO;			fmt = (*(short *) &event_rec[0]) & 0xffff;			err = synth_devs[dev]->load_patch(dev, fmt, buf, p + 4, c, 0);			if (err < 0)				return err;			return err;		}		if (ev_code >= 128)		{			if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED)			{				printk(KERN_WARNING "Sequencer: Invalid level 2 event %x\n", ev_code);				return -EINVAL;			}			ev_size = 8;			if (c < ev_size)			{				if (!seq_playing)					seq_startplay();				return count - c;			}			copy_from_user((char *) &event_rec[4], &(buf)[p + 4], 4);		}		else		{			if (seq_mode == SEQ_2)			{				printk(KERN_WARNING "Sequencer: 4 byte event in level 2 mode\n");				return -EINVAL;			}			ev_size = 4;			if (event_rec[0] != SEQ_MIDIPUTC)				obsolete_api_used = 1;		}		if (event_rec[0] == SEQ_MIDIPUTC)		{			if (!midi_opened[event_rec[2]])			{				int mode;				int dev = event_rec[2];				if (dev >= max_mididev || midi_devs[dev]==NULL)				{					/*printk("Sequencer Error: Nonexistent MIDI device %d\n", dev);*/					return -ENXIO;				}				mode = translate_mode(file);				if ((err = midi_devs[dev]->open(dev, mode,								sequencer_midi_input, sequencer_midi_output)) < 0)				{					seq_reset();					printk(KERN_WARNING "Sequencer Error: Unable to open Midi #%d\n", dev);					return err;				}				midi_opened[dev] = 1;			}		}		if (!seq_queue(event_rec, (file->f_flags & (O_NONBLOCK) ? 1 : 0)))		{			int processed = count - c;			if (!seq_playing)				seq_startplay();			if (!processed && (file->f_flags & O_NONBLOCK))				return -EAGAIN;			else				return processed;		}		p += ev_size;		c -= ev_size;	}	if (!seq_playing)		seq_startplay();	return count;}static int seq_queue(unsigned char *note, char nonblock){	/*	 * Test if there is space in the queue	 */	if (qlen >= SEQ_MAX_QUEUE)		if (!seq_playing)			seq_startplay();	/*						 * Give chance to drain the queue						 */	if (!nonblock && qlen >= SEQ_MAX_QUEUE && !waitqueue_active(&seq_sleeper)) {		/*		 * Sleep until there is enough space on the queue		 */		interruptible_sleep_on(&seq_sleeper);	}	if (qlen >= SEQ_MAX_QUEUE)	{		return 0;	/*				 * To be sure				 */	}	memcpy(&queue[qtail * EV_SZ], note, EV_SZ);	qtail = (qtail + 1) % SEQ_MAX_QUEUE;	qlen++;	return 1;}static int extended_event(unsigned char *q){	int dev = q[2];	if (dev < 0 || dev >= max_synthdev)		return -ENXIO;	if (!(synth_open_mask & (1 << dev)))		return -ENXIO;	switch (q[1])	{		case SEQ_NOTEOFF:			synth_devs[dev]->kill_note(dev, q[3], q[4], q[5]);			break;		case SEQ_NOTEON:			if (q[4] > 127 && q[4] != 255)				return 0;			if (q[5] == 0)			{				synth_devs[dev]->kill_note(dev, q[3], q[4], q[5]);				break;			}			synth_devs[dev]->start_note(dev, q[3], q[4], q[5]);			break;		case SEQ_PGMCHANGE:			synth_devs[dev]->set_instr(dev, q[3], q[4]);			break;		case SEQ_AFTERTOUCH:			synth_devs[dev]->aftertouch(dev, q[3], q[4]);			break;		case SEQ_BALANCE:			synth_devs[dev]->panning(dev, q[3], (char) q[4]);			break;		case SEQ_CONTROLLER:			synth_devs[dev]->controller(dev, q[3], q[4], (short) (q[5] | (q[6] << 8)));			break;		case SEQ_VOLMODE:			if (synth_devs[dev]->volume_method != NULL)				synth_devs[dev]->volume_method(dev, q[3]);			break;		default:			return -EINVAL;	}	return 0;}static int find_voice(int dev, int chn, int note){	unsigned short key;	int i;	key = (chn << 8) | (note + 1);	for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++)		if (synth_devs[dev]->alloc.map[i] == key)			return i;	return -1;}static int alloc_voice(int dev, int chn, int note){	unsigned short  key;	int voice;	key = (chn << 8) | (note + 1);	voice = synth_devs[dev]->alloc_voice(dev, chn, note,					     &synth_devs[dev]->alloc);	synth_devs[dev]->alloc.map[voice] = key;	synth_devs[dev]->alloc.alloc_times[voice] =			synth_devs[dev]->alloc.timestamp++;	return voice;}static void seq_chn_voice_event(unsigned char *event_rec){#define dev event_rec[1]#define cmd event_rec[2]#define chn event_rec[3]#define note event_rec[4]#define parm event_rec[5]	int voice = -1;	if ((int) dev > max_synthdev || synth_devs[dev] == NULL)		return;	if (!(synth_open_mask & (1 << dev)))		return;	if (!synth_devs[dev])		return;	if (seq_mode == SEQ_2)	{		if (synth_devs[dev]->alloc_voice)			voice = find_voice(dev, chn, note);		if (cmd == MIDI_NOTEON && parm == 0)		{			cmd = MIDI_NOTEOFF;			parm = 64;		}	}	switch (cmd)	{		case MIDI_NOTEON:			if (note > 127 && note != 255)	/* Not a seq2 feature */				return;			if (voice == -1 && seq_mode == SEQ_2 && synth_devs[dev]->alloc_voice)			{				/* Internal synthesizer (FM, GUS, etc) */				voice = alloc_voice(dev, chn, note);			}			if (voice == -1)				voice = chn;			if (seq_mode == SEQ_2 && (int) dev < num_synths)			{				/*				 * The MIDI channel 10 is a percussive channel. Use the note				 * number to select the proper patch (128 to 255) to play.				 */				if (chn == 9)				{					synth_devs[dev]->set_instr(dev, voice, 128 + note);					synth_devs[dev]->chn_info[chn].pgm_num = 128 + note;				}				synth_devs[dev]->setup_voice(dev, voice, chn);			}			synth_devs[dev]->start_note(dev, voice, note, parm);			break;		case MIDI_NOTEOFF:			if (voice == -1)				voice = chn;			synth_devs[dev]->kill_note(dev, voice, note, parm);			break;		case MIDI_KEY_PRESSURE:			if (voice == -1)				voice = chn;			synth_devs[dev]->aftertouch(dev, voice, parm);			break;		default:;	}#undef dev#undef cmd#undef chn#undef note#undef parm}static void seq_chn_common_event(unsigned char *event_rec){	unsigned char dev = event_rec[1];	unsigned char cmd = event_rec[2];	unsigned char chn = event_rec[3];	unsigned char p1 = event_rec[4];	/* unsigned char p2 = event_rec[5]; */	unsigned short w14 = *(short *) &event_rec[6];	if ((int) dev > max_synthdev || synth_devs[dev] == NULL)		return;	if (!(synth_open_mask & (1 << dev)))		return;	if (!synth_devs[dev])		return;	switch (cmd)	{		case MIDI_PGM_CHANGE:			if (seq_mode == SEQ_2)			{				synth_devs[dev]->chn_info[chn].pgm_num = p1;				if ((int) dev >= num_synths)					synth_devs[dev]->set_instr(dev, chn, p1);			}			else				synth_devs[dev]->set_instr(dev, chn, p1);			break;		case MIDI_CTL_CHANGE:			if (seq_mode == SEQ_2)			{				if (chn > 15 || p1 > 127)					break;				synth_devs[dev]->chn_info[chn].controllers[p1] = w14 & 0x7f;				if (p1 < 32)	/* Setting MSB should clear LSB to 0 */					synth_devs[dev]->chn_info[chn].controllers[p1 + 32] = 0;				if ((int) dev < num_synths)				{

⌨️ 快捷键说明

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