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

📄 soundfont.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	/*smp->v.loopend++;*/	smp->v.dummy = 0;	smp->v.truesize = 0;	smp->v.sf_id = sf->id;	/* set up voice info */	if ((zone = sf_zone_new(sflist, sf)) == NULL) {		sf_sample_delete(sflist, sf, smp);		return -ENOMEM;	}	/*	 * load wave data	 */	if (sflist->callback.sample_new) {		rc = sflist->callback.sample_new			(sflist->callback.private_data, smp, sflist->memhdr, data, count);		if (rc < 0) {			sf_sample_delete(sflist, sf, smp);			return rc;		}		/* memory offset is updated after */	}	/* update the memory offset here */	sflist->mem_used += smp->v.truesize;	zone->v.sample = sample_id; /* the last sample */	zone->v.rate_offset = calc_rate_offset(patch.base_freq);	note = freq_to_note(patch.base_note);	zone->v.root = note / 100;	zone->v.tune = -(note % 100);	zone->v.low = (freq_to_note(patch.low_note) + 99) / 100;	zone->v.high = freq_to_note(patch.high_note) / 100;	/* panning position; -128 - 127 => 0-127 */	zone->v.pan = (patch.panning + 128) / 2;#if 0	snd_printk("gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n",		   (int)patch.base_freq, zone->v.rate_offset,		   zone->v.root, zone->v.tune, zone->v.low, zone->v.high);#endif	/* detuning is ignored */	/* 6points volume envelope */	if (patch.mode & WAVE_ENVELOPES) {		int attack, hold, decay, release;		attack = calc_gus_envelope_time			(patch.env_rate[0], 0, patch.env_offset[0]);		hold = calc_gus_envelope_time			(patch.env_rate[1], patch.env_offset[0],			 patch.env_offset[1]);		decay = calc_gus_envelope_time			(patch.env_rate[2], patch.env_offset[1],			 patch.env_offset[2]);		release = calc_gus_envelope_time			(patch.env_rate[3], patch.env_offset[1],			 patch.env_offset[4]);		release += calc_gus_envelope_time			(patch.env_rate[4], patch.env_offset[3],			 patch.env_offset[4]);		release += calc_gus_envelope_time			(patch.env_rate[5], patch.env_offset[4],			 patch.env_offset[5]);		zone->v.parm.volatkhld = 			(snd_sf_calc_parm_hold(hold) << 8) |			snd_sf_calc_parm_attack(attack);		zone->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |			snd_sf_calc_parm_decay(decay);		zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release);		zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);#if 0		snd_printk("gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n",			   zone->v.parm.volatkhld,			   zone->v.parm.voldcysus,			   zone->v.parm.volrelease,			   zone->v.attenuation);#endif	}	/* fast release */	if (patch.mode & WAVE_FAST_RELEASE) {		zone->v.parm.volrelease = 0x807f;	}	/* tremolo effect */	if (patch.mode & WAVE_TREMOLO) {		int rate = (patch.tremolo_rate * 1000 / 38) / 42;		zone->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;	}	/* vibrato effect */	if (patch.mode & WAVE_VIBRATO) {		int rate = (patch.vibrato_rate * 1000 / 38) / 42;		zone->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;	}		/* scale_freq, scale_factor, volume, and fractions not implemented */	if (!(smp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT))		zone->v.mode = SNDRV_SFNT_MODE_LOOPING;	else		zone->v.mode = 0;	/* append to the tail of the list */	/*zone->bank = ctrls[AWE_MD_GUS_BANK];*/	zone->bank = 0;	zone->instr = patch.instr_no;	zone->mapped = 0;	zone->v.sf_id = sf->id;	zone->sample = set_sample(sf, &zone->v);	/* rebuild preset now */	add_preset(sflist, zone);	return 0;}/* load GUS patch */intsnd_soundfont_load_guspatch(snd_sf_list_t *sflist, const char __user *data,			    long count, int client){	int rc;	lock_preset(sflist);	rc = load_guspatch(sflist, data, count, client);	unlock_preset(sflist);	return rc;}/* * Rebuild the preset table.  This is like a hash table in that it allows * quick access to the zone information.  For each preset there are zone * structures linked by next_instr and by next_zone.  Former is the whole * link for this preset, and latter is the link for zone (i.e. instrument/ * bank/key combination). */static voidrebuild_presets(snd_sf_list_t *sflist){	snd_soundfont_t *sf;	snd_sf_zone_t *cur;	/* clear preset table */	memset(sflist->presets, 0, sizeof(sflist->presets));	/* search all fonts and insert each font */	for (sf = sflist->fonts; sf; sf = sf->next) {		for (cur = sf->zones; cur; cur = cur->next) {			if (! cur->mapped && cur->sample == NULL) {				/* try again to search the corresponding sample */				cur->sample = set_sample(sf, &cur->v);				if (cur->sample == NULL)					continue;			}			add_preset(sflist, cur);		}	}}/* * add the given zone to preset table */static voidadd_preset(snd_sf_list_t *sflist, snd_sf_zone_t *cur){	snd_sf_zone_t *zone;	int index;	zone = search_first_zone(sflist, cur->bank, cur->instr, cur->v.low);	if (zone && zone->v.sf_id != cur->v.sf_id) {		/* different instrument was already defined */		snd_sf_zone_t *p;		/* compare the allocated time */		for (p = zone; p; p = p->next_zone) {			if (p->counter > cur->counter)				/* the current is older.. skipped */				return;		}		/* remove old zones */		delete_preset(sflist, zone);		zone = NULL; /* do not forget to clear this! */	}	/* prepend this zone */	if ((index = get_index(cur->bank, cur->instr, cur->v.low)) < 0)		return;	cur->next_zone = zone; /* zone link */	cur->next_instr = sflist->presets[index]; /* preset table link */	sflist->presets[index] = cur;}/* * delete the given zones from preset_table */static voiddelete_preset(snd_sf_list_t *sflist, snd_sf_zone_t *zp){	int index;	snd_sf_zone_t *p;	if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0)		return;	for (p = sflist->presets[index]; p; p = p->next_instr) {		while (p->next_instr == zp) {			p->next_instr = zp->next_instr;			zp = zp->next_zone;			if (zp == NULL)				return;		}	}}/* * Search matching zones from preset table. * The note can be rewritten by preset mapping (alias). * The found zones are stored on 'table' array.  max_layers defines * the maximum number of elements in this array. * This function returns the number of found zones.  0 if not found. */intsnd_soundfont_search_zone(snd_sf_list_t *sflist, int *notep, int vel,			  int preset, int bank,			  int def_preset, int def_bank,			  snd_sf_zone_t **table, int max_layers){	int nvoices;	unsigned long flags;	/* this function is supposed to be called atomically,	 * so we check the lock.  if it's busy, just returns 0 to	 * tell the caller the busy state	 */	spin_lock_irqsave(&sflist->lock, flags);	if (sflist->presets_locked) {		spin_unlock_irqrestore(&sflist->lock, flags);		return 0;	}	nvoices = search_zones(sflist, notep, vel, preset, bank, table, max_layers, 0);	if (! nvoices) {		if (preset != def_preset || bank != def_bank)			nvoices = search_zones(sflist, notep, vel, def_preset, def_bank, table, max_layers, 0);	}	spin_unlock_irqrestore(&sflist->lock, flags);	return nvoices;}/* * search the first matching zone */static snd_sf_zone_t *search_first_zone(snd_sf_list_t *sflist, int bank, int preset, int key){	int index;	snd_sf_zone_t *zp;	if ((index = get_index(bank, preset, key)) < 0)		return NULL;	for (zp = sflist->presets[index]; zp; zp = zp->next_instr) {		if (zp->instr == preset && zp->bank == bank)			return zp;	}	return NULL;}/* * search matching zones from sflist.  can be called recursively. */static intsearch_zones(snd_sf_list_t *sflist, int *notep, int vel, int preset, int bank, snd_sf_zone_t **table, int max_layers, int level){	snd_sf_zone_t *zp;	int nvoices;	zp = search_first_zone(sflist, bank, preset, *notep);	nvoices = 0;	for (; zp; zp = zp->next_zone) {		if (*notep >= zp->v.low && *notep <= zp->v.high &&		    vel >= zp->v.vellow && vel <= zp->v.velhigh) {			if (zp->mapped) {				/* search preset mapping (aliasing) */				int key = zp->v.fixkey;				preset = zp->v.start;				bank = zp->v.end;				if (level > 5) /* too deep alias level */					return 0;				if (key < 0)					key = *notep;				nvoices = search_zones(sflist, &key, vel,						       preset, bank, table,						       max_layers, level + 1);				if (nvoices > 0)					*notep = key;				break;			}			table[nvoices++] = zp;			if (nvoices >= max_layers)				break;		}	}	return nvoices;}/* calculate the index of preset table: * drums are mapped from 128 to 255 according to its note key. * other instruments are mapped from 0 to 127. * if the index is out of range, return -1. */static intget_index(int bank, int instr, int key){	int index;	if (SF_IS_DRUM_BANK(bank))		index = key + SF_MAX_INSTRUMENTS;	else		index = instr;	index = index % SF_MAX_PRESETS;	if (index < 0)		return -1;	return index;}/* * Initialise the sflist structure. */static voidsnd_sf_init(snd_sf_list_t *sflist){	memset(sflist->presets, 0, sizeof(sflist->presets));	sflist->mem_used = 0;	sflist->currsf = NULL;	sflist->open_client = -1;	sflist->fonts = NULL;	sflist->fonts_size = 0;	sflist->zone_counter = 0;	sflist->sample_counter = 0;	sflist->zone_locked = 0;	sflist->sample_locked = 0;}/* * Release all list records */static voidsnd_sf_clear(snd_sf_list_t *sflist){	snd_soundfont_t *sf, *nextsf;	snd_sf_zone_t *zp, *nextzp;	snd_sf_sample_t *sp, *nextsp;	for (sf = sflist->fonts; sf; sf = nextsf) {		nextsf = sf->next;		for (zp = sf->zones; zp; zp = nextzp) {			nextzp = zp->next;			kfree(zp);		}		for (sp = sf->samples; sp; sp = nextsp) {			nextsp = sp->next;			if (sflist->callback.sample_free)				sflist->callback.sample_free(sflist->callback.private_data, sp, sflist->memhdr);			kfree(sp);		}		kfree(sf);	}	snd_sf_init(sflist);}/* * Create a new sflist structure */snd_sf_list_t *snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr){	snd_sf_list_t *sflist;	if ((sflist = kcalloc(1, sizeof(*sflist), GFP_KERNEL)) == NULL)		return NULL;	init_MUTEX(&sflist->presets_mutex);	spin_lock_init(&sflist->lock);	sflist->memhdr = hdr;	if (callback)		sflist->callback = *callback;	snd_sf_init(sflist);	return sflist;}/* * Free everything allocated off the sflist structure. */voidsnd_sf_free(snd_sf_list_t *sflist){	if (sflist == NULL)		return;		lock_preset(sflist);	if (sflist->callback.sample_reset)		sflist->callback.sample_reset(sflist->callback.private_data);	snd_sf_clear(sflist);	unlock_preset(sflist);	kfree(sflist);}/* * Remove all samples * The soundcard should be silet before calling this function. */intsnd_soundfont_remove_samples(snd_sf_list_t *sflist){	lock_preset(sflist);	if (sflist->callback.sample_reset)		sflist->callback.sample_reset(sflist->callback.private_data);	snd_sf_clear(sflist);	unlock_preset(sflist);	return 0;}/* * Remove unlocked samples. * The soundcard should be silent before calling this function. */intsnd_soundfont_remove_unlocked(snd_sf_list_t *sflist){	snd_soundfont_t *sf;	snd_sf_zone_t *zp, *nextzp;	snd_sf_sample_t *sp, *nextsp;	lock_preset(sflist);	if (sflist->callback.sample_reset)		sflist->callback.sample_reset(sflist->callback.private_data);	/* to be sure */	memset(sflist->presets, 0, sizeof(sflist->presets));	for (sf = sflist->fonts; sf; sf = sf->next) {		for (zp = sf->zones; zp; zp = nextzp) {			if (zp->counter < sflist->zone_locked)				break;			nextzp = zp->next;			sf->zones = nextzp;			kfree(zp);		}		for (sp = sf->samples; sp; sp = nextsp) {			if (sp->counter < sflist->sample_locked)				break;			nextsp = sp->next;			sf->samples = nextsp;			sflist->mem_used -= sp->v.truesize;			if (sflist->callback.sample_free)				sflist->callback.sample_free(sflist->callback.private_data, sp, sflist->memhdr);			kfree(sp);		}	}	sflist->zone_counter = sflist->zone_locked;	sflist->sample_counter = sflist->sample_locked;	rebuild_presets(sflist);	unlock_preset(sflist);	return 0;}

⌨️ 快捷键说明

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