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

📄 voice.c

📁 linux-2.6.15.6
💻 C
字号:
/* *  Copyright (c) by Jaroslav Kysela <perex@suse.cz> *                   Creative Labs, Inc. *                   Lee Revell <rlrevell@joe-job.com> *  Routines for control of EMU10K1 chips - voice manager * *  Rewrote voice allocator for multichannel support - rlrevell 12/2004 *  *  BUGS: *    -- * *  TODO: *    -- * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */#include <sound/driver.h>#include <linux/time.h>#include <sound/core.h>#include <sound/emu10k1.h>/* Previously the voice allocator started at 0 every time.  The new voice  * allocator uses a round robin scheme.  The next free voice is tracked in  * the card record and each allocation begins where the last left off.  The  * hardware requires stereo interleaved voices be aligned to an even/odd  * boundary.  For multichannel voice allocation we ensure than the block of  * voices does not cross the 32 voice boundary.  This simplifies the  * multichannel support and ensures we can use a single write to the  * (set|clear)_loop_stop registers.  Otherwise (for example) the voices would  * get out of sync when pausing/resuming a stream. *							--rlrevell */static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice){	emu10k1_voice_t *voice;	int i, j, k, first_voice, last_voice, skip;	*rvoice = NULL;	first_voice = last_voice = 0;	for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) {		// printk("i %d j %d next free %d!\n", i, j, emu->next_free_voice);		i %= NUM_G;		/* stereo voices must be even/odd */		if ((number == 2) && (i % 2)) {			i++;			continue;		}					skip = 0;		for (k = 0; k < number; k++) {			voice = &emu->voices[(i+k) % NUM_G];			if (voice->use) {				skip = 1;				break;			}		}		if (!skip) {			// printk("allocated voice %d\n", i);			first_voice = i;			last_voice = (i + number) % NUM_G;			emu->next_free_voice = last_voice;			break;		}	}		if (first_voice == last_voice)		return -ENOMEM;		for (i=0; i < number; i++) {		voice = &emu->voices[(first_voice + i) % NUM_G];		// printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number);		voice->use = 1;		switch (type) {		case EMU10K1_PCM:			voice->pcm = 1;			break;		case EMU10K1_SYNTH:			voice->synth = 1;			break;		case EMU10K1_MIDI:			voice->midi = 1;			break;		case EMU10K1_EFX:			voice->efx = 1;			break;		}	}	*rvoice = &emu->voices[first_voice];	return 0;}int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice){	unsigned long flags;	int result;	snd_assert(rvoice != NULL, return -EINVAL);	snd_assert(number, return -EINVAL);	spin_lock_irqsave(&emu->voice_lock, flags);	for (;;) {		result = voice_alloc(emu, type, number, rvoice);		if (result == 0 || type == EMU10K1_SYNTH || type == EMU10K1_MIDI)			break;		/* free a voice from synth */		if (emu->get_synth_voice) {			result = emu->get_synth_voice(emu);			if (result >= 0) {				emu10k1_voice_t *pvoice = &emu->voices[result];				pvoice->interrupt = NULL;				pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;				pvoice->epcm = NULL;			}		}		if (result < 0)			break;	}	spin_unlock_irqrestore(&emu->voice_lock, flags);	return result;}int snd_emu10k1_voice_free(emu10k1_t *emu, emu10k1_voice_t *pvoice){	unsigned long flags;	snd_assert(pvoice != NULL, return -EINVAL);	spin_lock_irqsave(&emu->voice_lock, flags);	pvoice->interrupt = NULL;	pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;	pvoice->epcm = NULL;	snd_emu10k1_voice_init(emu, pvoice->number);	spin_unlock_irqrestore(&emu->voice_lock, flags);	return 0;}

⌨️ 快捷键说明

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