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

📄 sfont.c

📁 A GTK sound font editor. Sound font files are used to synthesize instruments from audio samples for
💻 C
📖 第 1 页 / 共 3 页
字号:
/*================================================================== * sfont.c - Sound font routines * * Smurf Sound Font Editor * Copyright (C) 1999-2001 Josh Green * * 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 or point your web browser to http://www.gnu.org. * * To contact the author of this program: * Email: Josh Green <jgreen@users.sourceforge.net> * Smurf homepage: http://smurf.sourceforge.net *==================================================================*/#include "config.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <glib.h>#include "sfont.h"#include "sample.h"#include "util.h"#include "i18n.h"#include "uif_sftree.h"/* optimum chunk area sizes (could be more optimum) */#define PRESET_CHUNK_OPTIMUM_AREA	256#define INST_CHUNK_OPTIMUM_AREA		256#define SAMPLE_CHUNK_OPTIMUM_AREA	256#define SAMDATAINFO_CHUNK_OPTIMUM_AREA  256#define ZONE_CHUNK_OPTIMUM_AREA		256#define MOD_CHUNK_OPTIMUM_AREA		256#define GEN_CHUNK_OPTIMUM_AREA		256/* Memory chunk pointers */static GMemChunk *chunk_preset;static GMemChunk *chunk_inst;static GMemChunk *chunk_sample;static GMemChunk *chunk_samdatainfo;static GMemChunk *chunk_zone;static GMemChunk *chunk_mod;static GMemChunk *chunk_gen;static gboolean sfont_chunks_inited = FALSE; /* Have chunks been initialized? *//*    Balanced binary tree of all sound font item GtkCTreeNodes    so references can be easily managed (not pointers but unique IDs)    which means an item can be removed and references don't need    updating only the GTree does which is managed on add/remove    of items, no segfaults from old references :)*/GTree *sfont_itemids = NULL;/* sf item unique ID counter (increments) */static gint sfont_itemid_counter = 1;/* Default range value stored in 2 byte form with correct host byte order */#define DEFRANGE	GINT16_FROM_LE(0x7F00)guint16 badgen[] = { Gen_Unused1, Gen_Unused2, Gen_Unused3, Gen_Unused4,  Gen_Reserved1, Gen_Reserved2, Gen_Reserved3, 0};guint16 badpgen[] = { Gen_StartAddrOfs, Gen_EndAddrOfs, Gen_StartLoopAddrOfs,  Gen_EndLoopAddrOfs, Gen_StartAddrCoarseOfs, Gen_EndAddrCoarseOfs,  Gen_StartLoopAddrCoarseOfs, Gen_Keynum, Gen_Velocity,  Gen_EndLoopAddrCoarseOfs, Gen_SampleModes, Gen_ExclusiveClass,  Gen_OverrideRootKey, 0};/* SF -> User unit type conversion table, comments are for NLS translators */GenConv genconv[] = {  {NULL, NULL, NULL, NULL, 0, NULL, NULL},	// None/* Short abbreviation for "samples" */  {float2int, int2float, float2int, int2float, 0, N_("smpls"), N_("smpls")},	// Unit_Smpls/* Short abbreviation for 32k (i.e. 32 thousand) "samples" */  {float2int, int2float, float2int, int2float, 0, N_("32ksmpls"), N_("32ksmpls")},	// Unit_32kSmpls/* Cents (100th of a semitone) */  {float2int, int2float, float2int, int2float, 0, N_("cents"), N_("+cents")},	// Unit_Cent/* Hertz abbreviation (cycles per second) */  {hz2cents, cents2hz, sec2tcent, tcent2sec, 2, N_("Hz"), "X"},	// Unit_HzCent/* Seconds abbreviation (second, as in the measurement of time) */  {sec2tcent, tcent2sec, sec2tcent, tcent2sec, 3, N_("sec"), "X"},	// Unit_TCent/* Decibel abbreviation */  {db2cb, cb2db, db2cb, cb2db, 2, N_("dB"), N_("+dB")},	// Unit_cB  {perc2tperc, tperc2perc, perc2tperc, tperc2perc, 1, "%", "+%"},	// Unit_Percent/* semitone abbreviation (1/12th of an octave) */  {float2int, int2float, float2int, int2float, 0, N_("semi"), N_("+semi")},	// Unit_Semitone  {NULL, NULL, NULL, NULL, 0, N_("range"), N_("+range")}	// Unit_Range};#define MAXNEG -32768#define MAXPOS 32767GenParms genparms[] = {  {0, MAXPOS, 0, Unit_Smpls, NULL},	// Gen_StartAddrOfs  {MAXNEG, 0, 0, Unit_Smpls, NULL},	// Gen_EndAddrOfs  {MAXNEG, MAXPOS, 0, Unit_Smpls, NULL},	// Gen_StartLoopAddrOfs  {MAXNEG, MAXPOS, 0, Unit_Smpls, NULL},	// Gen_EndLoopAddrOfs  {0, MAXPOS, 0, Unit_32kSmpls, NULL},	// Gen_StartAddrCoarseOfs  {-12000, 12000, 0, Unit_Cent, N_("To Pitch")},	// Gen_ModLFO2Pitch  {-12000, 12000, 0, Unit_Cent, N_("To Pitch")},	// Gen_VibLFO2Pitch  {-12000, 12000, 0, Unit_Cent, N_("To Pitch")},	// Gen_ModEnv2Pitch  {1500, 13500, 13500, Unit_HzCent, N_("Filter Cutoff")},	// Gen_FilterFc  {0, 960, 0, Unit_cB, N_("Filter Q")},	// Gen_FilterQ  {-12000, 12000, 0, Unit_Cent, N_("To Filter Cutoff")}, // Gen_ModLFO2FilterFc  {-12000, 12000, 0, Unit_Cent, N_("To Filter Cutoff")}, // Gen_ModEnv2FilterFc  {MAXNEG, 0, 0, Unit_32kSmpls, NULL},	// Gen_EndAddrCoarseOfs  {-960, 960, 0, Unit_cB, N_("To Volume")},	// Gen_ModLFO2Vol  {0, 0, 0, None, NULL},	// Gen_Unused1  {0, 1000, 0, Unit_Percent, N_("Chorus")},	// Gen_ChorusSend  {0, 1000, 0, Unit_Percent, N_("Reverb")},	// Gen_ReverbSend  {-500, 500, 0, Unit_Percent, N_("Pan")},	// Gen_Pan  {0, 0, 0, None, NULL},	// Gen_Unused2  {0, 0, 0, None, NULL},	// Gen_Unused3  {0, 0, 0, None, NULL},	// Gen_Unused4  {-12000, 5000, -12000, Unit_TCent, N_("Delay")},	// Gen_ModLFODelay  {-16000, 4500, 0, Unit_HzCent, N_("Frequency")},	// Gen_ModLFOFreq  {-12000, 5000, -12000, Unit_TCent, N_("Delay")},	// Gen_VibLFODelay  {-16000, 4500, 0, Unit_HzCent, N_("Frequency")},	// Gen_VibLFOFreq  {-12000, 5000, -12000, Unit_TCent, N_("Delay")},	// Gen_ModEnvDelay  {-12000, 8000, -12000, Unit_TCent, N_("Attack")},	// Gen_ModEnvAttack  {-12000, 5000, -12000, Unit_TCent, N_("Hold")},	// Gen_ModEnvHold  {-12000, 8000, -12000, Unit_TCent, N_("Decay")},	// Gen_ModEnvDecay  {0, 1000, 0, Unit_Percent, N_("Sustain")},	// Gen_ModEnvSustain  {-12000, 8000, -12000, Unit_TCent, N_("Release")},	// Gen_ModEnvRelease  {-1200, 1200, 0, Unit_Cent, N_("Key to Hold")},	// Gen_Key2ModEnvHold  {-1200, 1200, 0, Unit_Cent, N_("Key to Decay")},	// Gen_Key2ModEnvDecay  {-12000, 5000, -12000, Unit_TCent, N_("Delay")},	// Gen_VolEnvDelay  {-12000, 8000, -12000, Unit_TCent, N_("Attack")},	// Gen_VolEnvAttack  {-12000, 5000, -12000, Unit_TCent, N_("Hold")},	// Gen_VolEnvHold  {-12000, 8000, -12000, Unit_TCent, N_("Decay")},	// Gen_VolEnvDecay  {0, 1440, 0, Unit_cB, N_("Sustain")},	// Gen_VolEnvSustain  {-12000, 8000, -12000, Unit_TCent, N_("Release")},	// Gen_VolEnvRelease  {-1200, 1200, 0, Unit_Cent, N_("Key to Hold")},	// Gen_Key2VolEnvHold  {-1200, 1200, 0, Unit_Cent, N_("Key to Decay")},	// Gen_Key2VolEnvDecay  {0, MAXPOS, 0, None, NULL},	// Gen_Instrument  {0, 0, 0, None, NULL},	// Gen_Reserved1  {0, 127, DEFRANGE, Unit_Range, NULL},	// Gen_KeyRange  {0, 127, DEFRANGE, Unit_Range, NULL},	// Gen_VelRange  {MAXNEG, MAXPOS, 0, Unit_32kSmpls, NULL},	// Gen_StartLoopAddrCoarseOfs  {-1, 127, -1, None, NULL},	// Gen_Keynum  {-1, 127, -1, None, NULL},	// Gen_Velocity  {0, 1440, 0, Unit_cB, N_("Attenuation")},	// Gen_InitAttenuation  {0, 0, 0, None, NULL},	// Gen_Reserved2  {MAXNEG, MAXPOS, 0, Unit_32kSmpls, NULL},	// Gen_EndLoopAddrCoarseOfs  {-120, 120, 0, Unit_Semitone, N_("Coarse Tune")},	// Gen_CourseTune  {-99, 99, 0, Unit_Cent, N_("Fine Tune")},	// Gen_FineTune  {0, MAXPOS, 0, None, NULL},	// Gen_sampleId  {MAXNEG, MAXPOS, 0, None, NULL},	// Gen_SampleModes  {0, 0, 0, None, NULL},	// Gen_Reserved3  {0, 1200, 100, Unit_Cent, N_("Scale Tune")},	// Gen_ScaleTuning  {0, 127, 0, None, NULL},	// Gen_ExclusiveClass  {-1, 127, -1, None, NULL}	// Gen_OverrideRootKey};static gint sfont_itemid_compare_func (gconstpointer a, gconstpointer b);/*----- General sfont routines -----*//* initialize sound font mem chunks */voidsfont_init_chunks (void){  if (sfont_chunks_inited) return;  chunk_preset =    g_mem_chunk_create (SFPreset, PRESET_CHUNK_OPTIMUM_AREA,    G_ALLOC_AND_FREE);  chunk_inst =    g_mem_chunk_create (SFInst, INST_CHUNK_OPTIMUM_AREA, G_ALLOC_AND_FREE);  chunk_sample =    g_mem_chunk_create (SFSample, SAMPLE_CHUNK_OPTIMUM_AREA,    G_ALLOC_AND_FREE);  chunk_samdatainfo =    g_mem_chunk_create (SFSamDataInfo, SAMPLE_CHUNK_OPTIMUM_AREA,    G_ALLOC_AND_FREE);  chunk_zone =    g_mem_chunk_create (SFZone, ZONE_CHUNK_OPTIMUM_AREA, G_ALLOC_AND_FREE);  chunk_mod =    g_mem_chunk_create (SFMod, MOD_CHUNK_OPTIMUM_AREA, G_ALLOC_AND_FREE);  chunk_gen =    g_mem_chunk_create (SFGen, GEN_CHUNK_OPTIMUM_AREA, G_ALLOC_AND_FREE);  /* initialize sfont_itemids balanced binary tree */  sfont_itemids = g_tree_new (sfont_itemid_compare_func);  sfont_chunks_inited = TRUE;}/* generates the next available item ID */SFItemIDsfont_next_itemid (void){  return (sfont_itemid_counter++);}/* adds an item ID as a key to val */voidsfont_register_itemid (SFItemID itemid, gpointer val){  g_tree_insert (sfont_itemids, GINT_TO_POINTER (itemid), val);}/* looks up an item ID and returns the associated pointer value */gpointersfont_lookup_itemid (SFItemID itemid){  return (g_tree_lookup (sfont_itemids, GINT_TO_POINTER (itemid)));}/* removes a sound font item ID */voidsfont_remove_itemid (SFItemID itemid){  g_tree_remove (sfont_itemids, GINT_TO_POINTER (itemid));}static gintsfont_itemid_compare_func (gconstpointer a, gconstpointer b){  return (GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b));}/* ------------------------------------- *//* ---- SFData Sound Font functions ---- *//* ------------------------------------- *//* create a new sound font */SFData *sfont_new (gint titlenum){  SFData *sf;  gchar *s;  sf = sfont_sfdata_alloc ();  sf->version.major = 2;  sf->version.minor = 0;  /* file name to give new "untitled" sound fonts */  sf->fname = g_strdup_printf (_("untitled%d.sf2"), titlenum);  sfont_set_info (sf, ISNG_ID, "EMU8000");  /* name to give to new "untitled" sound fonts */  s = g_strdup_printf (_("Untitled %d"), titlenum);  sfont_set_info (sf, INAM_ID, s);  g_free (s);  s = g_strconcat (SFONT_ISFT_NAME VERSION, ":", NULL);  sfont_set_info (sf, ISFT_ID, s);  g_free (s);  sf->up2date = TRUE;	/* do this last, SF functions set it to FALSE */  sf->beensaved = FALSE;	/* has not been saved yet */  return (sf);}/* close a sound font and destroy all its data */voidsfont_close (SFData * sf){  sfont_destroy (sf);  if (sf->sffd)    fclose (sf->sffd);}/* recursively delete a sound font (all presets, samples, instruments etc) */voidsfont_destroy (SFData * sf){  GSList *p, *p2;  if (sf->fname)    g_free (sf->fname);  p = sf->info;  while (p)    {      g_free (p->data);      p = g_slist_next (p);    }  g_slist_free (sf->info);  sf->info = NULL;  p = sf->preset;  while (p)    {				/* loop over presets */      p2 = ((SFPreset *) (p->data))->zone;      while (p2)	{			/* loop over preset's zones */	  sfont_zone_destroy (p2->data);	  p2 = g_slist_next (p2);	}			/* free preset's zone list */      g_slist_free (((SFPreset *) (p->data))->zone);      g_mem_chunk_free (chunk_preset, p->data);	/* free preset chunk */      p = g_slist_next (p);    }  g_slist_free (sf->preset);  sf->preset = NULL;  p = sf->inst;  while (p)    {				/* loop over instruments */      p2 = ((SFInst *) (p->data))->zone;      while (p2)	{			/* loop over inst's zones */	  sfont_zone_destroy (p2->data);	  p2 = g_slist_next (p2);	}			/* free inst's zone list */      g_slist_free (((SFInst *) (p->data))->zone);      g_mem_chunk_free (chunk_inst, p->data);	/* free inst chunk */      p = g_slist_next (p);    }  g_slist_free (sf->inst);  sf->inst = NULL;  p = sf->sample;  while (p)    {      p2 = p;      p = g_slist_next (p);      /* better use the routine since it moves sample data if needed */      sfont_remove_sample (sf, (SFSample *) (p2->data));    }  sf->sample = NULL;}/* allocate and initialize an SFData structure to dead state */SFData *sfont_sfdata_alloc (void){  SFData *sf;  sf = g_new0 (SFData, 1);  return (sf);}/* free a sound font data structure */voidsfont_sfdata_free (SFData *sf){  g_free (sf);}/* create a new preset in a sound font */SFPreset *sfont_new_preset (SFData * sf, gchar * name, guint16 bank, guint16 prenum){  SFPreset *pset;  pset = sfont_preset_alloc ();  strcpy (pset->name, name);  pset->prenum = prenum;  pset->bank = bank;  sf->preset = g_slist_insert_sorted (sf->preset, pset,    (GCompareFunc) sfont_preset_compare_func);  sf->up2date = FALSE;  return (pset);}/* add an existing preset into a sound font (sorted) */voidsfont_add_preset (SFData * sf, SFPreset * pset){  sf->preset = g_slist_insert_sorted (sf->preset, pset,    (GCompareFunc) sfont_preset_compare_func);  sf->up2date = FALSE;}/* destroy and remove a preset from a sound font */voidsfont_remove_preset (SFData * sf, SFPreset * pset){  sfont_preset_destroy (pset);  sf->preset = g_slist_remove (sf->preset, pset);  sf->up2date = FALSE;}/* preset sort function, first by bank, then by preset # */gintsfont_preset_compare_func (gconstpointer a, gconstpointer b){  gint32 aval, bval;  aval = (gint32) (((SFPreset *) a)->bank) << 16 | ((SFPreset *) a)->prenum;  bval = (gint32) (((SFPreset *) b)->bank) << 16 | ((SFPreset *) b)->prenum;  return (aval - bval);}/* create a new instrument in a sound font */SFInst *sfont_new_inst (SFData * sf, gchar * name){  SFInst *inst;  inst = sfont_inst_alloc ();  sfont_add_inst (sf, inst);  strcpy (inst->name, name);  sf->up2date = FALSE;  return (inst);}/* add (append) an instrument to a sound font */voidsfont_add_inst (SFData * sf, SFInst * inst){  sf->inst = g_slist_append (sf->inst, inst);  sf->up2date = FALSE;}/* insert an instrument into a sound font */voidsfont_insert_inst (SFData * sf, SFInst * inst, gint pos){  sf->inst = g_slist_insert (sf->inst, inst, pos);  sf->up2date = FALSE;}/* destroy an instrument and remove it from a sound font */voidsfont_remove_inst (SFData * sf, SFInst * inst){  sfont_inst_destroy (inst);  sf->inst = g_slist_remove (sf->inst, inst);  sf->up2date = FALSE;}/* add a sample record to a sfdata structure */voidsfont_add_sample (SFData * sf, SFSample * sam){  sf->sample = g_slist_append (sf->sample, sam);  sf->up2date = FALSE;}/* insert a sample into a sound font */voidsfont_insert_sample (SFData * sf, SFSample * sam, gint pos){  sf->sample = g_slist_insert (sf->sample, sam, pos);  sf->up2date = FALSE;}/* delete a sample from a sound font */voidsfont_remove_sample (SFData * sf, SFSample * sam){  if (SAM_DATAINFO_REFCOUNT (sam->datainfo) <= 1)    sam_datainfo_destroy (sam->datainfo);  else if (sam->datainfo->sf == sf) /* -if data resides in sf and other refs */    sam_datainfo_move2sambuf (sam, sf);	/* -move data to sambuf */  sfont_sample_destroy (sam, TRUE);  sf->sample = g_slist_remove (sf->sample, sam);  sf->up2date = FALSE;}/* create a new zone for a preset */SFZone *sfont_new_preset_zone (SFData * sf, SFPreset * pset, GSList * inst){  SFZone *zone;  /* request to create global zone? Does one already exist? */  if (!inst && pset->zone && !((SFZone *) (pset->zone->data))->instsamp)    return (NULL);  zone = sfont_zone_alloc ();  zone->instsamp = inst;  if (inst)    pset->zone = g_slist_append (pset->zone, zone);  else  /* global zone should be first zone */    pset->zone = g_slist_prepend (pset->zone, zone);

⌨️ 快捷键说明

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