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

📄 sndfont.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 4 页
字号:
/*    TiMidity++ -- MIDI to WAVE converter and player    Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>    Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>*//* This code from awesfx * Modified by Masanao Izumo <mo@goice.co.jp> *//*================================================================ * parsesf.c *	parse SoundFonr layers and convert it to AWE driver patch * * Copyright (C) 1996,1997 Takashi Iwai * * 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 *================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include <stdlib.h>#include <math.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "timidity.h"#include "common.h"#include "tables.h"#include "instrum.h"#include "playmidi.h"#include "controls.h"#include "sffile.h"#include "sflayer.h"#include "sfitem.h"#include "output.h"#include "filter.h"#include "resample.h"#define FILENAME_NORMALIZE(fname) url_expand_home_dir(fname)#define FILENAME_REDUCED(fname)   url_unexpand_home_dir(fname)#define SFMalloc(rec, count)      new_segment(&(rec)->pool, count)#define SFStrdup(rec, s)          strdup_mblock(&(rec)->pool, s)/*---------------------------------------------------------------- * compile flags *----------------------------------------------------------------*/#ifdef CFG_FOR_SF#define SF_SUPPRESS_ENVELOPE#define SF_SUPPRESS_TREMOLO#define SF_SUPPRESS_VIBRATO#else#define SF_CLOSE_EACH_FILE/*#define SF_SUPPRESS_ENVELOPE*//*#define SF_SUPPRESS_TREMOLO*//*#define SF_SUPPRESS_VIBRATO*/#endif /* CFG_FOR_SF *//* return value */#define AWE_RET_OK		0	/* successfully loaded */#define AWE_RET_ERR		1	/* some fatal error occurs */#define AWE_RET_SKIP		2	/* some fonts are skipped */#define AWE_RET_NOMEM		3	/* out or memory; not all fonts loaded */#define AWE_RET_NOT_FOUND	4	/* the file is not found *//*---------------------------------------------------------------- * local parameters *----------------------------------------------------------------*/typedef struct _SFPatchRec {	int preset, bank, keynote; /* -1 = matches all */} SFPatchRec;typedef struct _SampleList {	Sample v;	struct _SampleList *next;	int32 start;	int32 len;	int32 cutoff_freq;	int16 resonance;	int16 root, tune;	char low, high;		/* key note range */	int8 reverb_send, chorus_send;	/* Depend on play_mode->rate */	int32 vibrato_freq;	int32 attack;	int32 hold;	int32 sustain;	int32 decay;	int32 release;	int32 modattack;	int32 modhold;	int32 modsustain;	int32 moddecay;	int32 modrelease;	int bank, keynote;	/* for drum instruments */} SampleList;typedef struct _InstList {	SFPatchRec pat;	int pr_idx;	int samples;	int order;	SampleList *slist;	struct _InstList *next;} InstList;typedef struct _SFExclude {	SFPatchRec pat;	struct _SFExclude *next;} SFExclude;typedef struct _SFOrder {	SFPatchRec pat;	int order;	struct _SFOrder *next;} SFOrder;#define INSTHASHSIZE 127#define INSTHASH(bank, preset, keynote) \	((int)(((unsigned)bank ^ (unsigned)preset ^ (unsigned)keynote) % INSTHASHSIZE))typedef struct _SFInsts {	struct timidity_file *tf;	char *fname;	int8 def_order, def_cutoff_allowed, def_resonance_allowed;	uint16 version, minorversion;	int32 samplepos, samplesize;	InstList *instlist[INSTHASHSIZE];	char **inst_namebuf;	SFExclude *sfexclude;	SFOrder *sforder;	struct _SFInsts *next;	FLOAT_T amptune;	MBlockList pool;} SFInsts;/*----------------------------------------------------------------*//* prototypes */#define P_GLOBAL	1#define P_LAYER		2#ifndef FALSE#define FALSE 0#endif /* FALSE */#ifndef TRUE#define TRUE 1#endif /* TRUE */static SFInsts *find_soundfont(char *sf_file);static SFInsts *new_soundfont(char *sf_file);static void init_sf(SFInsts *rec);static void end_soundfont(SFInsts *rec);static Instrument *try_load_soundfont(SFInsts *rec, int order, int bank,				      int preset, int keynote);static Instrument *load_from_file(SFInsts *rec, InstList *ip);static int is_excluded(SFInsts *rec, int bank, int preset, int keynote);static int is_ordered(SFInsts *rec, int bank, int preset, int keynote);static int load_font(SFInfo *sf, int pridx);static int parse_layer(SFInfo *sf, int pridx, LayerTable *tbl, int level);static int is_global(SFGenLayer *layer);static void clear_table(LayerTable *tbl);static void set_to_table(SFInfo *sf, LayerTable *tbl, SFGenLayer *lay, int level);static void add_item_to_table(LayerTable *tbl, int oper, int amount, int level);static void merge_table(SFInfo *sf, LayerTable *dst, LayerTable *src);static void init_and_merge_table(SFInfo *sf, LayerTable *dst, LayerTable *src);static int sanity_range(LayerTable *tbl);static int make_patch(SFInfo *sf, int pridx, LayerTable *tbl);static void make_info(SFInfo *sf, SampleList *vp, LayerTable *tbl);static FLOAT_T calc_volume(LayerTable *tbl);static void set_sample_info(SFInfo *sf, SampleList *vp, LayerTable *tbl);static void set_init_info(SFInfo *sf, SampleList *vp, LayerTable *tbl);static int abscent_to_Hz(int abscents);static void set_rootkey(SFInfo *sf, SampleList *vp, LayerTable *tbl);static void set_rootfreq(SampleList *vp);static int32 to_offset(int32 offset);static int32 to_rate(int32 diff, int timecent);static int32 calc_rate(int32 diff, double msec);static double to_msec(int timecent);static int32 calc_sustain(int sust_cB);static void convert_volume_envelope(SampleList *vp, LayerTable *tbl);static void convert_tremolo(SampleList *vp, LayerTable *tbl);static void convert_vibrato(SampleList *vp, LayerTable *tbl);/*----------------------------------------------------------------*/static SFInsts *sfrecs = NULL;static SFInsts *current_sfrec = NULL;#define def_drum_inst 0static SFInsts *find_soundfont(char *sf_file){    SFInsts *sf;    sf_file = FILENAME_NORMALIZE(sf_file);    for(sf = sfrecs; sf != NULL; sf = sf->next)	if(sf->fname != NULL && strcmp(sf->fname, sf_file) == 0)	    return sf;    return NULL;}static SFInsts *new_soundfont(char *sf_file){    SFInsts *sf;    sf_file = FILENAME_NORMALIZE(sf_file);    for(sf = sfrecs; sf != NULL; sf = sf->next)	if(sf->fname == NULL)	    break;    if(sf == NULL)	sf = (SFInsts *)safe_malloc(sizeof(SFInsts));    memset(sf, 0, sizeof(SFInsts));    init_mblock(&sf->pool);    sf->fname = SFStrdup(sf, FILENAME_NORMALIZE(sf_file));    sf->def_order = DEFAULT_SOUNDFONT_ORDER;    sf->amptune = 1.0;    return sf;}void add_soundfont(char *sf_file,		   int sf_order, int sf_cutoff, int sf_resonance,		   int amp){    SFInsts *sf;    if((sf = find_soundfont(sf_file)) == NULL)    {        sf = new_soundfont(sf_file);        sf->next = sfrecs;        sfrecs = sf;    }    if(sf_order >= 0)        sf->def_order = sf_order;    if(sf_cutoff >= 0)        sf->def_cutoff_allowed = sf_cutoff;    if(sf_resonance >= 0)        sf->def_resonance_allowed = sf_resonance;    if(amp >= 0)        sf->amptune = (FLOAT_T)amp * 0.01;    current_sfrec = sf;}void remove_soundfont(char *sf_file){    SFInsts *sf;    if((sf = find_soundfont(sf_file)) != NULL)	end_soundfont(sf);}char *soundfont_preset_name(int bank, int preset, int keynote,			    char **sndfile){    SFInsts *rec;    if(sndfile != NULL)	*sndfile = NULL;    for(rec = sfrecs; rec != NULL; rec = rec->next)	if(rec->fname != NULL)	{	    int addr;	    InstList *ip;	    addr = INSTHASH(bank, preset, keynote);	    for(ip = rec->instlist[addr]; ip; ip = ip->next)		if(ip->pat.bank == bank && ip->pat.preset == preset &&		   (keynote < 0 || keynote == ip->pat.keynote))		    break;	    if(ip != NULL)	    {		if(sndfile != NULL)		    *sndfile = rec->fname;		return rec->inst_namebuf[ip->pr_idx];	    }	}    return NULL;}static void init_sf(SFInsts *rec){	SFInfo sfinfo;	int i;	ctl->cmsg(CMSG_INFO, VERB_NOISY, "Init soundfonts `%s'",		  FILENAME_REDUCED(rec->fname));	if ((rec->tf = open_file(rec->fname, 1, OF_VERBOSE)) == NULL) {		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,			  "Can't open soundfont file %s",			  FILENAME_REDUCED(rec->fname));		end_soundfont(rec);		return;	}	if(load_soundfont(&sfinfo, rec->tf))	{	    end_soundfont(rec);	    return;	}	correct_samples(&sfinfo);	current_sfrec = rec;	for (i = 0; i < sfinfo.npresets; i++) {		int bank = sfinfo.preset[i].bank;		int preset = sfinfo.preset[i].preset;		if (bank == 128)		    /* FIXME: why not allow exclusion of drumsets? */		    alloc_instrument_bank(1, preset);		else {			if (is_excluded(rec, bank, preset, -1))				continue;			alloc_instrument_bank(0, bank);		}		load_font(&sfinfo, i);	}	/* copy header info */	rec->version = sfinfo.version;	rec->minorversion = sfinfo.minorversion;	rec->samplepos = sfinfo.samplepos;	rec->samplesize = sfinfo.samplesize;	rec->inst_namebuf =	    (char **)SFMalloc(rec, sfinfo.npresets * sizeof(char *));	for(i = 0; i < sfinfo.npresets; i++)	    rec->inst_namebuf[i] =		(char *)SFStrdup(rec, sfinfo.preset[i].hdr.name);	free_soundfont(&sfinfo);#ifndef SF_CLOSE_EACH_FILE	if(!IS_URL_SEEK_SAFE(rec->tf->url))#endif	{	    close_file(rec->tf);	    rec->tf = NULL;	}}void init_load_soundfont(void){    SFInsts *rec;    for(rec = sfrecs; rec != NULL; rec = rec->next)	if(rec->fname != NULL)	    init_sf(rec);}static void end_soundfont(SFInsts *rec){	if (rec->tf) {		close_file(rec->tf);		rec->tf = NULL;	}	rec->fname = NULL;	rec->inst_namebuf = NULL;	rec->sfexclude = NULL;	rec->sforder = NULL;	reuse_mblock(&rec->pool);}Instrument *extract_soundfont(char *sf_file, int bank, int preset,			      int keynote){    SFInsts *sf;    if((sf = find_soundfont(sf_file)) != NULL)	return try_load_soundfont(sf, -1, bank, preset, keynote);    sf = new_soundfont(sf_file);    sf->next = sfrecs;    sf->def_order = 2;    sfrecs = sf;    init_sf(sf);    return try_load_soundfont(sf, -1, bank, preset, keynote);}/*---------------------------------------------------------------- * get converted instrument info and load the wave data from file *----------------------------------------------------------------*/static Instrument *try_load_soundfont(SFInsts *rec, int order, int bank,				      int preset, int keynote){	InstList *ip;	Instrument *inst = NULL;	int addr;	if (rec->tf == NULL) {		if (rec->fname == NULL)			return NULL;		if ((rec->tf = open_file(rec->fname, 1, OF_VERBOSE)) == NULL) {			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,				  "Can't open soundfont file %s",				  FILENAME_REDUCED(rec->fname));			end_soundfont(rec);			return NULL;		}#ifndef SF_CLOSE_EACH_FILE		if(!IS_URL_SEEK_SAFE(rec->tf->url))		    rec->tf->url = url_cache_open(rec->tf->url, 1);#endif /* SF_CLOSE_EACH_FILE */	}	addr = INSTHASH(bank, preset, keynote);	for (ip = rec->instlist[addr]; ip; ip = ip->next) {		if (ip->pat.bank == bank && ip->pat.preset == preset &&		    (keynote < 0 || ip->pat.keynote == keynote) &&		    (order < 0 || ip->order == order))			break;	}	if (ip && ip->samples)		inst = load_from_file(rec, ip);#ifdef SF_CLOSE_EACH_FILE	close_file(rec->tf);	rec->tf = NULL;#endif	return inst;}Instrument *load_soundfont_inst(int order,				int bank, int preset, int keynote){    SFInsts *rec;    Instrument *ip;    /*     * Search through all ordered soundfonts     */    int o = order;    for(rec = sfrecs; rec != NULL; rec = rec->next)    {	if(rec->fname != NULL)	{	    ip = try_load_soundfont(rec, o, bank, preset, keynote);	    if(ip != NULL)		return ip;	    if (o > 0) o++;	}    }    return NULL;}/*----------------------------------------------------------------*/#define TO_MHZ(abscents) (int32)(8176.0 * pow(2.0,(double)(abscents)/1200.0))#if 0#ifndef M_LN2#define M_LN2		0.69314718055994530942#endif /* M_LN2 */#ifndef M_LN10#define M_LN10		2.30258509299404568402#endif /* M_LN10 */#define TO_VOLUME(centibel) (uint8)(255 * (1.0 - \				(centibel) * (M_LN10 / 1200.0 / M_LN2)))#else#define TO_VOLUME(level)  (uint8)(255.0 - (level) * (255.0/1000.0))#endifstatic FLOAT_T calc_volume(LayerTable *tbl){    int v;    if(!tbl->set[SF_initAtten] || (int)tbl->val[SF_initAtten] == 0)	return (FLOAT_T)1.0;	v = (int)tbl->val[SF_initAtten];    if(v < 0) {v = 0;}    else if(v > 960) {v = 960;}	return cb_to_amp_table[v];}/* convert from 16bit value to fractional offset (15.15) */static int32 to_offset(int32 offset){	return offset << 14;}#define SF_ENVRATE_MAX (0x3FFFFFFFL)#define SF_ENVRATE_MIN (1L)/* calculate ramp rate in fractional unit; * diff = 16bit, time = msec */static int32 calc_rate(int32 diff, double msec){    double rate;    if(msec == 0) {return (int32)SF_ENVRATE_MAX + 1;}    if(diff <= 0) {diff = 1;}    diff <<= 14;    rate = ((double)diff / play_mode->rate) * control_ratio * 1000.0 / msec;    if(fast_decay) {rate *= 2;}	if(rate > SF_ENVRATE_MAX) {rate = SF_ENVRATE_MAX;}	else if(rate < SF_ENVRATE_MIN) {rate = SF_ENVRATE_MIN;}    return (int32)rate;}/* calculate ramp rate in fractional unit; * diff = 16bit, timecent */static int32 to_rate(int32 diff, int timecent){    double rate;    if(timecent == -12000)	/* instantaneous attack */	{return (int32)SF_ENVRATE_MAX + 1;}    if(diff <= 0) {diff = 1;}    diff <<= 14;    rate = (double)diff * control_ratio / play_mode->rate / pow(2.0, (double)timecent / 1200.0);

⌨️ 快捷键说明

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