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

📄 sequencer.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	DEB(printk("sequencer_release(dev=%d)\n", dev));	/*	 * Wait until the queue is empty (if we don't have nonblock)	 */	if (mode != OPEN_READ && !(file->f_flags & O_NONBLOCK))	{		while (!signal_pending(current) && qlen > 0)		{  			seq_sync(); 			interruptible_sleep_on_timeout(&seq_sleeper,						       3*HZ); 			/* Extra delay */		}	}	if (mode != OPEN_READ)		seq_drain_midi_queues();	/*						 * Ensure the output queues are empty						 */	seq_reset();	if (mode != OPEN_READ)		seq_drain_midi_queues();	/*						 * Flush the all notes off messages						 */	for (i = 0; i < max_synthdev; i++)	{		if (synth_open_mask & (1 << i))	/*						 * Actually opened						 */			if (synth_devs[i])			{				synth_devs[i]->close(i);				if (synth_devs[i]->owner)					__MOD_DEC_USE_COUNT (synth_devs[i]->owner);				if (synth_devs[i]->midi_dev)					midi_opened[synth_devs[i]->midi_dev] = 0;			}	}	for (i = 0; i < max_mididev; i++)	{		if (midi_opened[i]) {			midi_devs[i]->close(i);			if (midi_devs[i]->owner)				__MOD_DEC_USE_COUNT (midi_devs[i]->owner);		}	}	if (seq_mode == SEQ_2) {		tmr->close(tmr_no);		if (tmr->owner)			__MOD_DEC_USE_COUNT (tmr->owner);	}	if (obsolete_api_used)		printk(KERN_WARNING "/dev/music: Obsolete (4 byte) API was used by %s\n", current->comm);	sequencer_busy = 0;}static int seq_sync(void){	unsigned long flags;	if (qlen && !seq_playing && !signal_pending(current))		seq_startplay();	save_flags(flags);	cli(); 	if (qlen > 0) 		interruptible_sleep_on_timeout(&seq_sleeper, HZ);	restore_flags(flags);	return qlen;}static void midi_outc(int dev, unsigned char data){	/*	 * NOTE! Calls sleep(). Don't call this from interrupt.	 */	int n;	unsigned long flags;	/*	 * This routine sends one byte to the Midi channel.	 * If the output FIFO is full, it waits until there	 * is space in the queue	 */	n = 3 * HZ;		/* Timeout */	save_flags(flags);	cli(); 	while (n && !midi_devs[dev]->outputc(dev, data)) { 		interruptible_sleep_on_timeout(&seq_sleeper, HZ/25);  		n--;  	}	restore_flags(flags);}static void seq_reset(void){	/*	 * NOTE! Calls sleep(). Don't call this from interrupt.	 */	int i;	int chn;	unsigned long flags;	sound_stop_timer();	seq_time = jiffies;	prev_input_time = 0;	prev_event_time = 0;	qlen = qhead = qtail = 0;	iqlen = iqhead = iqtail = 0;	for (i = 0; i < max_synthdev; i++)		if (synth_open_mask & (1 << i))			if (synth_devs[i])				synth_devs[i]->reset(i);	if (seq_mode == SEQ_2)	{		for (chn = 0; chn < 16; chn++)			for (i = 0; i < max_synthdev; i++)				if (synth_open_mask & (1 << i))					if (synth_devs[i])					{						synth_devs[i]->controller(i, chn, 123, 0);	/* All notes off */						synth_devs[i]->controller(i, chn, 121, 0);	/* Reset all ctl */						synth_devs[i]->bender(i, chn, 1 << 13);	/* Bender off */					}	}	else	/* seq_mode == SEQ_1 */	{		for (i = 0; i < max_mididev; i++)			if (midi_written[i])	/*						 * Midi used. Some notes may still be playing						 */			{				/*				 *      Sending just a ACTIVE SENSING message should be enough to stop all				 *      playing notes. Since there are devices not recognizing the				 *      active sensing, we have to send some all notes off messages also.				 */				midi_outc(i, 0xfe);				for (chn = 0; chn < 16; chn++)				{					midi_outc(i, (unsigned char) (0xb0 + (chn & 0x0f)));		/* control change */					midi_outc(i, 0x7b);	/* All notes off */					midi_outc(i, 0);	/* Dummy parameter */				}				midi_devs[i]->close(i);				midi_written[i] = 0;				midi_opened[i] = 0;			}	}	seq_playing = 0;	save_flags(flags);	cli();	if (waitqueue_active(&seq_sleeper)) {		/*      printk( "Sequencer Warning: Unexpected sleeping process - Waking up\n"); */		wake_up(&seq_sleeper);	}	restore_flags(flags);}static void seq_panic(void){	/*	 * This routine is called by the application in case the user	 * wants to reset the system to the default state.	 */	seq_reset();	/*	 * Since some of the devices don't recognize the active sensing and	 * all notes off messages, we have to shut all notes manually.	 *	 *      TO BE IMPLEMENTED LATER	 */	/*	 * Also return the controllers to their default states	 */}int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg){	int midi_dev, orig_dev, val, err;	int mode = translate_mode(file);	struct synth_info inf;	struct seq_event_rec event_rec;	unsigned long flags;	orig_dev = dev = dev >> 4;	switch (cmd)	{		case SNDCTL_TMR_TIMEBASE:		case SNDCTL_TMR_TEMPO:		case SNDCTL_TMR_START:		case SNDCTL_TMR_STOP:		case SNDCTL_TMR_CONTINUE:		case SNDCTL_TMR_METRONOME:		case SNDCTL_TMR_SOURCE:			if (seq_mode != SEQ_2)				return -EINVAL;			return tmr->ioctl(tmr_no, cmd, arg);		case SNDCTL_TMR_SELECT:			if (seq_mode != SEQ_2)				return -EINVAL;			if (get_user(pending_timer, (int *)arg))				return -EFAULT;			if (pending_timer < 0 || pending_timer >= num_sound_timers || sound_timer_devs[pending_timer] == NULL)			{				pending_timer = -1;				return -EINVAL;			}			val = pending_timer;			break;		case SNDCTL_SEQ_PANIC:			seq_panic();			return -EINVAL;		case SNDCTL_SEQ_SYNC:			if (mode == OPEN_READ)				return 0;			while (qlen > 0 && !signal_pending(current))				seq_sync();			return qlen ? -EINTR : 0;		case SNDCTL_SEQ_RESET:			seq_reset();			return 0;		case SNDCTL_SEQ_TESTMIDI:			if (__get_user(midi_dev, (int *)arg))				return -EFAULT;			if (midi_dev < 0 || midi_dev >= max_mididev || !midi_devs[midi_dev])				return -ENXIO;			if (!midi_opened[midi_dev] &&				(err = midi_devs[midi_dev]->open(midi_dev, mode, sequencer_midi_input,						     sequencer_midi_output)) < 0)				return err;			midi_opened[midi_dev] = 1;			return 0;		case SNDCTL_SEQ_GETINCOUNT:			if (mode == OPEN_WRITE)				return 0;			val = iqlen;			break;		case SNDCTL_SEQ_GETOUTCOUNT:			if (mode == OPEN_READ)				return 0;			val = SEQ_MAX_QUEUE - qlen;			break;		case SNDCTL_SEQ_GETTIME:			if (seq_mode == SEQ_2)				return tmr->ioctl(tmr_no, cmd, arg);			val = jiffies - seq_time;			break;		case SNDCTL_SEQ_CTRLRATE:			/*			 * If *arg == 0, just return the current rate			 */			if (seq_mode == SEQ_2)				return tmr->ioctl(tmr_no, cmd, arg);			if (get_user(val, (int *)arg))				return -EFAULT;			if (val != 0)				return -EINVAL;			val = HZ;			break;		case SNDCTL_SEQ_RESETSAMPLES:		case SNDCTL_SYNTH_REMOVESAMPLE:		case SNDCTL_SYNTH_CONTROL:			if (get_user(dev, (int *)arg))				return -EFAULT;			if (dev < 0 || dev >= num_synths || synth_devs[dev] == NULL)				return -ENXIO;			if (!(synth_open_mask & (1 << dev)) && !orig_dev)				return -EBUSY;			return synth_devs[dev]->ioctl(dev, cmd, arg);		case SNDCTL_SEQ_NRSYNTHS:			val = max_synthdev;			break;		case SNDCTL_SEQ_NRMIDIS:			val = max_mididev;			break;		case SNDCTL_SYNTH_MEMAVL:			if (get_user(dev, (int *)arg))				return -EFAULT;			if (dev < 0 || dev >= num_synths || synth_devs[dev] == NULL)				return -ENXIO;			if (!(synth_open_mask & (1 << dev)) && !orig_dev)				return -EBUSY;			val = synth_devs[dev]->ioctl(dev, cmd, arg);			break;		case SNDCTL_FM_4OP_ENABLE:			if (get_user(dev, (int *)arg))				return -EFAULT;			if (dev < 0 || dev >= num_synths || synth_devs[dev] == NULL)				return -ENXIO;			if (!(synth_open_mask & (1 << dev)))				return -ENXIO;			synth_devs[dev]->ioctl(dev, cmd, arg);			return 0;		case SNDCTL_SYNTH_INFO:			if (get_user(dev, (int *)(&(((struct synth_info *)arg)->device))))				return -EFAULT;			if (dev < 0 || dev >= max_synthdev)				return -ENXIO;			if (!(synth_open_mask & (1 << dev)) && !orig_dev)				return -EBUSY;			return synth_devs[dev]->ioctl(dev, cmd, arg);		/* Like SYNTH_INFO but returns ID in the name field */		case SNDCTL_SYNTH_ID:			if (get_user(dev, (int *)(&(((struct synth_info *)arg)->device))))				return -EFAULT;			if (dev < 0 || dev >= max_synthdev)				return -ENXIO;			if (!(synth_open_mask & (1 << dev)) && !orig_dev)				return -EBUSY;			memcpy(&inf, synth_devs[dev]->info, sizeof(inf));			strncpy(inf.name, synth_devs[dev]->id, sizeof(inf.name));			inf.device = dev;			return copy_to_user(arg, &inf, sizeof(inf))?-EFAULT:0;		case SNDCTL_SEQ_OUTOFBAND:			if (copy_from_user(&event_rec, arg, sizeof(event_rec)))				return -EFAULT;			save_flags(flags);			cli();			play_event(event_rec.arr);			restore_flags(flags);			return 0;		case SNDCTL_MIDI_INFO:			if (get_user(dev, (int *)(&(((struct midi_info *)arg)->device))))				return -EFAULT;			if (dev < 0 || dev >= max_mididev || !midi_devs[dev])				return -ENXIO;			midi_devs[dev]->info.device = dev;			return copy_to_user(arg, &midi_devs[dev]->info, sizeof(struct midi_info))?-EFAULT:0;		case SNDCTL_SEQ_THRESHOLD:			if (get_user(val, (int *)arg))				return -EFAULT;			if (val < 1)				val = 1;			if (val >= SEQ_MAX_QUEUE)				val = SEQ_MAX_QUEUE - 1;			output_threshold = val;			return 0;		case SNDCTL_MIDI_PRETIME:			if (get_user(val, (int *)arg))				return -EFAULT;			if (val < 0)				val = 0;			val = (HZ * val) / 10;			pre_event_timeout = val;			break;		default:			if (mode == OPEN_READ)				return -EIO;			if (!synth_devs[0])				return -ENXIO;			if (!(synth_open_mask & (1 << 0)))				return -ENXIO;			if (!synth_devs[0]->ioctl)				return -EINVAL;			return synth_devs[0]->ioctl(0, cmd, arg);	}	return put_user(val, (int *)arg);}/* No kernel lock - we're using the global irq lock here */unsigned int sequencer_poll(int dev, struct file *file, poll_table * wait){	unsigned long flags;	unsigned int mask = 0;	dev = dev >> 4;	save_flags(flags);	cli();	/* input */	poll_wait(file, &midi_sleeper, wait);	if (iqlen)		mask |= POLLIN | POLLRDNORM;	/* output */	poll_wait(file, &seq_sleeper, wait);	if ((SEQ_MAX_QUEUE - qlen) >= output_threshold)		mask |= POLLOUT | POLLWRNORM;	restore_flags(flags);	return mask;}void sequencer_timer(unsigned long dummy){	seq_startplay();}int note_to_freq(int note_num){	/*	 * This routine converts a midi note to a frequency (multiplied by 1000)	 */	int note, octave, note_freq;	static int notes[] =	{		261632, 277189, 293671, 311132, 329632, 349232,		369998, 391998, 415306, 440000, 466162, 493880	};#define BASE_OCTAVE	5	octave = note_num / 12;	note = note_num % 12;	note_freq = notes[note];	if (octave < BASE_OCTAVE)		note_freq >>= (BASE_OCTAVE - octave);	else if (octave > BASE_OCTAVE)		note_freq <<= (octave - BASE_OCTAVE);	/*	 * note_freq >>= 1;	 */	return note_freq;}unsigned long compute_finetune(unsigned long base_freq, int bend, int range,		 int vibrato_cents){	unsigned long amount;	int negative, semitones, cents, multiplier = 1;	if (!bend)		return base_freq;	if (!range)		return base_freq;	if (!base_freq)		return base_freq;	if (range >= 8192)		range = 8192;	bend = bend * range / 8192;	/* Convert to cents */	bend += vibrato_cents;	if (!bend)		return base_freq;	negative = bend < 0 ? 1 : 0;	if (bend < 0)		bend *= -1;	if (bend > range)		bend = range;	/*	   if (bend > 2399)	   bend = 2399;	 */	while (bend > 2399)	{		multiplier *= 4;		bend -= 2400;	}	semitones = bend / 100;	if (semitones > 99)		semitones = 99;	cents = bend % 100;	amount = (int) (semitone_tuning[semitones] * multiplier * cent_tuning[cents]) / 10000;	if (negative)		return (base_freq * 10000) / amount;	/* Bend down */	else		return (base_freq * amount) / 10000;	/* Bend up */}void sequencer_init(void){	/* drag in sequencer_syms.o */	{		extern char sequencer_syms_symbol;		sequencer_syms_symbol = 0;	}	if (sequencer_ok)		return;	MIDIbuf_init();	queue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * EV_SZ);	if (queue == NULL)	{		printk(KERN_ERR "sequencer: Can't allocate memory for sequencer output queue\n");		return;	}	iqueue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * IEV_SZ);	if (iqueue == NULL)	{		printk(KERN_ERR "sequencer: Can't allocate memory for sequencer input queue\n");		vfree(queue);		return;	}	sequencer_ok = 1;}void sequencer_unload(void){	if(queue)	{		vfree(queue);		queue=NULL;	}	if(iqueue)	{		vfree(iqueue);		iqueue=NULL;	}}

⌨️ 快捷键说明

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