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

📄 wavetable.c

📁 A GTK sound font editor. Sound font files are used to synthesize instruments from audio samples for
💻 C
📖 第 1 页 / 共 2 页
字号:
/*================================================================== * wavetable.c - Generic wavetable routines (independent of device) * * 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 <string.h>#include <unistd.h>#include <fcntl.h>#include <glib.h>#include "wavetable.h"#include "sample.h"#include "util.h"#include "sequencer.h"#include "smurfcfg.h"#include "i18n.h"#include "uif_sftree.h"		/* For NODE_* defines */#include "uif_piano.h"#include "drivers/wtbl_awe.h"#include "drivers/seq_oss.h"WTblDriverInfo wtbl_drivers[WTBL_COUNT] = {  { N_("NONE"), NULL, NULL, NULL, NULL, NULL, NULL },#ifdef AWE_SUPPORT  { N_("AWE32/64"),    awe_init,    seq_oss_fd_close,    awe_set_effect,    awe_open_patch,    awe_close_patch,    awe_load_sample,    awe_load_patch_info,    awe_clear_samples,    awe_clear_unlocked_samples,    awe_clear_sample_patch_id,    awe_mem_avail,    awe_samdata_mem_required  },#endif};static gint wtbl_auto_detect (void);static void wtbl_silence_temp_audible (void);static gint wtbl_GTraverseFunc_preset_dependents (gpointer key, gpointer value,						  gpointer data);static gint wtbl_GTraverseFunc_load_preset (gpointer key, gpointer value,					    gpointer data);static gint wtbl_ptr_compare_func (gconstpointer p1, gconstpointer p2);static gint wtbl_sfont_mem_required (SFData *sf);static gint wtbl_vbank_mem_required (VBnkData *vbnk);static gint wtbl_preset_mem_required (SFPreset *pset, SFData *sf,				      gboolean locked, GTree *gt);static gint wtbl_inst_mem_required (SFInst *inst, SFData *sf,				    gboolean locked, GTree *gt);static gint wtbl_update_cache_vars (void);static gint wtbl_clear_cache_if_needed (gint memreq);static gint wtbl_load_preset_real (gint bank, gint prenum, SFPreset *pset,				   SFData *sf);gint wtbl_driver = WTBL_NONE;	/* active wavetable driver */gboolean wtbl_active = FALSE;	/* state of wavetable driver */gchar *wtbl_oss_devname = NULL;	/* device file for OSS wavetable drivers *//* when samples are loaded as instruments should they be looped or not? */gboolean wtbl_loop_sam_as_inst = TRUE;gboolean wtbl_sample_cache_support = FALSE; /* if AWE driver supports caching */gboolean wtbl_cache_samples = FALSE; /* enable sample caching? */gboolean wtbl_recursive_bank_refresh = FALSE; /* upd8 loaded bank recursively *//* variables for the active temporary audible */SFItemID wtbl_temp_audible = SFITEMID_NONE; /* current temporary audible */gboolean wtbl_temp_audible_changed = FALSE; /* audible needs reload? */GList *wtbl_temp_audible_muted_zones = NULL; /* zones (SFItemIDs) to mute *//* currently loaded sound font or virtual bank */SFItemID wtbl_loaded_sfbank = SFITEMID_NONE;gboolean wtbl_loaded_sfbank_changed = FALSE; /* loaded sfont/vbank changed? */GTree *wtbl_changed_loaded_sfitems = NULL; /* changed sfitems in loaded SF */static gint wtbl_cache_mem_avail = -1; /* amount of mem available to cache *//* clear samples, first time a patch gets loaded */static gboolean wtbl_onetime_clear_samples = TRUE; /* initialize wavetable drivers and load config vars */gintwtbl_init_from_config (void){  GTokenValue *val;  gint drvr_id;  gboolean retval;  char *s;  /* get wavetable sample caching config var (1 = on, 0 = off, 2 = auto) */  wtbl_cache_samples =    (smurfcfg_get_val (SMURFCFG_WAVETBL_SAM_CACHING)->v_int == 1);  /* Same OSS device is used for all OSS based wavetable/sequencer/midi     drivers, load the config value here */  if (wtbl_oss_devname) g_free (wtbl_oss_devname);  s = smurfcfg_get_str (SMURFCFG_WAVETBL_OSSDEV);  if (!strlen (s))		/* if config has blank value, set to default */    s = "/dev/sequencer";  wtbl_oss_devname = g_strdup(s);  val = smurfcfg_get_val (SMURFCFG_WAVETBL_DRIVER);  if (strcmp (val->v_string, "AUTO") != 0    && (drvr_id = wtbl_locate_byname (val->v_string)) != -1)    {      log_message (_("Initializing wavetable driver \"%s\".."),val->v_string);      wtbl_set_driver (drvr_id); /* try specified wavetable driver */      retval = wtbl_init ();	/* initialize the driver */      if (retval)	log_message (_("Wavetable driver initialized"));      else	logit (LogFubar, _("Wavetable driver failed"));      return (retval);    }  else return (wtbl_auto_detect ()); /* auto detect wavetable driver */}/* "auto" detect wavetable routine (just tries each one until one loads) */static gintwtbl_auto_detect (void){  char *name;  gint i;  log_message (_("Looking for supported wavetable driver..."));  if (WTBL_COUNT <= 1)    {      log_message (_("No wavetable drivers were compiled into Smurf!"));      return (FAIL);		/* Only dummy driver exists */    }  for (i = 1; i < WTBL_COUNT; i++)    {      name = _(wtbl_drivers[i].name);      log_message (_("Trying driver %s..."), name);      if (wtbl_drivers[i].init)	{	  if ((*wtbl_drivers[i].init) ())	    {	      log_message (_("Initialization of %s driver successful"), name);	      wtbl_driver = i;	      wtbl_active = TRUE;	      log_message (_("Using supported driver %s"), name);	      return (OK);	    }	  else log_message (_("Driver %s failed"), name);	}    }  log_message (_("Failed to find a supported wavetable driver!"));  return (FAIL);}/* Sets active wavetable driver to one specified by its ID */voidwtbl_set_driver (guint drvr_id){  if (drvr_id >= WTBL_COUNT)    return;  wtbl_driver = drvr_id;}/* Find a driver by its name, return ID */gintwtbl_locate_byname (gchar * name){  gint i;  for (i = 0; i < WTBL_COUNT; i++)    {      if (strcmp (name, wtbl_drivers[i].name) == 0)	return (i);    }  return (-1);}/* silence audible (currently just clears variables) */static voidwtbl_silence_temp_audible (void){  wtbl_temp_audible = SFITEMID_NONE;}/* sound font element change notification (for wavetable refresh) */voidwtbl_sfitem_changed (SFItemID itemid, WTblItemChange change){  if (wtbl_temp_audible != SFITEMID_NONE) /* a temporary audible is loaded? */    {      if (itemid == wtbl_temp_audible) /* temp audible changed? */	{	  if (change == WTBL_ITEM_CHANGE)	    wtbl_temp_audible_changed = TRUE;	  else wtbl_silence_temp_audible (); /* item deleted, silence audible */	}    }  if (wtbl_loaded_sfbank != SFITEMID_NONE)	/* a sfont bank is loaded? */    {      GtkCTreeNode *node;      SFTreeRef *ref;      UISFont *loaded_uisf;      /* if loaded bank is a sound font (as apposed to a vbank) */      node = SFTREE_LOOKUP_ITEMID (wtbl_loaded_sfbank);      if (node && (ref = SFTREE_NODE_REF (node))->type == NODE_SFONT)	{	  loaded_uisf = (UISFont *)(ref->dptr);	  /* if item's sound font is the same as loaded sound font */	  node = SFTREE_LOOKUP_ITEMID (itemid);	  if (node && SFTREE_UPFIND_UISF (node) == loaded_uisf)	    {	      ref = SFTREE_NODE_REF (node);	      /* if recursive bank refresh is active or item is a preset */	      if ((wtbl_recursive_bank_refresh && wtbl_cache_samples)		  || ref->type == NODE_PRESET)		{		  wtbl_loaded_sfbank_changed = TRUE;		  if (!wtbl_changed_loaded_sfitems)		    wtbl_changed_loaded_sfitems =		      g_tree_new (wtbl_ptr_compare_func);		  /* add to tree of changed items (tree merges duplicates) */		  g_tree_insert (wtbl_changed_loaded_sfitems,				 GINT_TO_POINTER (itemid),				 GINT_TO_POINTER (TRUE));		}	    }	}    }}/* a little temporary bag for the next 2 functions */typedef struct{  GTree *presets;  SFData *sf;} TmpBagPDepends;voidwtbl_note_on_notify (void){  GtkCTreeNode *node;  SFTreeRef *ref;  UISFont *uisf;  SFSample *sam;  /* temporary audible need reloading? */  if (wtbl_temp_audible_changed && wtbl_temp_audible != SFITEMID_NONE      && (node = SFTREE_LOOKUP_ITEMID (wtbl_temp_audible)))    {      ref = SFTREE_NODE_REF (node);      uisf = SFTREE_UPFIND_UISF (node);      switch (ref->type)	{	case NODE_PRESET:	  wtbl_load_temp_preset ((SFPreset *)(((GSList *)(ref->dptr))->data),				 uisf->sf);	  break;	case NODE_INST:	  wtbl_load_temp_inst ((SFInst *)(((GSList *)(ref->dptr))->data),			       uisf->sf);	  break;	case NODE_SAMPLE:	  sam = (SFSample *)(((GSList *)(ref->dptr))->data);	  /* AWE driver doesn't support reloading of sample info,	     so force reload of sample data */	  wtbl_clear_sample_patch_id (sam, FALSE);	  wtbl_load_temp_sam_as_inst(sam, uisf->sf);	  break;	default:	  break;	}      /* hack for OSS AWE driver, blasted thing resets bank:preset to 0:0	 after some wavetable operations (not sure which) */      uipiano_refresh_bank_preset ();    }  if (wtbl_loaded_sfbank_changed && wtbl_loaded_sfbank != SFITEMID_NONE)    {				/* item in loaded sfont changed? */      TmpBagPDepends pdeps;      if (!(node = SFTREE_LOOKUP_ITEMID (wtbl_loaded_sfbank))) return;      if (SFTREE_NODE_REF (node)->type != NODE_SFONT) return;      pdeps.sf = SFTREE_SFNODE_SFONT (node);      pdeps.presets = g_tree_new (wtbl_ptr_compare_func);      g_tree_traverse (wtbl_changed_loaded_sfitems,		       wtbl_GTraverseFunc_preset_dependents, G_IN_ORDER,		       &pdeps);      /* don't need changed item tree anymore, so kill */      g_tree_destroy (wtbl_changed_loaded_sfitems);      wtbl_changed_loaded_sfitems = NULL;      /* open patch (with sample locking, no samples loaded, but we want to	 use the same set of samples) */      if (!wtbl_open_patch (TRUE))	return;      /* load each changed preset */      g_tree_traverse (pdeps.presets,		       wtbl_GTraverseFunc_load_preset, G_IN_ORDER, pdeps.sf);      wtbl_close_patch ();      wtbl_loaded_sfbank_changed = FALSE;    }}static gintwtbl_GTraverseFunc_preset_dependents (gpointer key, gpointer value,				      gpointer data){  TmpBagPDepends *pdeps = data;  GtkCTreeNode *node;  SFTreeRef *ref;  SFPreset *pset;  SFZone *zone;  GSList *p, *p2;  if (!(node = SFTREE_LOOKUP_ITEMID (GPOINTER_TO_INT (key))))    return (FALSE);  ref = SFTREE_NODE_REF (node);  switch (ref->type)    {    case NODE_PRESET:	/* item is a preset, add it to tree */      g_tree_insert (pdeps->presets, ((GSList *)(ref->dptr))->data,		     GINT_TO_POINTER (TRUE));      break;    case NODE_INST:	/* item is instrument, add preset dependents */      p = pdeps->sf->preset;      while (p)	{	  pset = (SFPreset *)(p->data);	  p2 = pset->zone;	  while (p2)	    {	      zone = (SFZone *)(p2->data);	      if (zone->instsamp == ref->dptr)		{		  g_tree_insert (pdeps->presets, pset, GINT_TO_POINTER (TRUE));		  break;		}	      p2 = g_slist_next (p2);	    }	  p = g_slist_next (p);	}      break;    case NODE_SAMPLE:	/* grrr, have to reload sample data! */      break;    default:      break;    }  return (FALSE);		/* don't stop traversal */}static gintwtbl_GTraverseFunc_load_preset (gpointer key, gpointer value,				gpointer data){  SFData *sf = data;  SFPreset *pset = key;  wtbl_load_preset_real (pset->bank, pset->prenum, pset, sf);  return (FALSE);		/* don't stop traversal */}static gintwtbl_ptr_compare_func (gconstpointer p1, gconstpointer p2){  if (p1 < p2) return (-1);  if (p1 > p2) return (1);  return (0);}/* calculate wavetable sample data allocation required for sound font */static gintwtbl_sfont_mem_required (SFData *sf){  GTree *gtree;  SFPreset *pset;  GSList *p;  gint size = 0;  gint rv;  /* binary tree to count multi-used sample data only once */  gtree = g_tree_new (wtbl_ptr_compare_func);  p = sf->preset;  while (p)			/* calc required mem for each preset */    {      pset = (SFPreset *)(p->data);      rv = wtbl_preset_mem_required (pset, sf, TRUE, gtree);      if (rv == -1) break;      size += rv;      p = g_slist_next (p);    }  g_tree_destroy (gtree);  if (p == NULL) return (size);	/* all presets processed? */  else return (-1);		/* ?: NO, error occured */}/* calculate wavetable sample data allocation required for virtual bank */static gintwtbl_vbank_mem_required (VBnkData *vbnk){  GTree *gtree;  GList *psetmaps, *p;  VBnkPresetMap *pmap;  gint size = 0;  gint rv;  /* binary tree to count duplicates only once */  gtree = g_tree_new (wtbl_ptr_compare_func);  /* get list of preset maps (VBnkPresetMap's are SFPresets with mapped     bank:preset) */  psetmaps = vbank_get_preset_maps (vbnk);  p = psetmaps;  while (p)			/* loop over preset maps */    {      pmap = (VBnkPresetMap *)(p->data);      /* calculate size of preset */      rv = wtbl_preset_mem_required (pmap->preset, pmap->sf, TRUE, gtree);      if (rv == -1) break;      size += rv;      p = g_list_next (p);    }  g_list_foreach (psetmaps, (GFunc)g_free, NULL);  g_list_free (psetmaps);  g_tree_destroy (gtree);  if (p == NULL) return (size);	/* make sure all presets processed */  else return (-1);		/* nope, error occured */}/* amount of sample memory required to load a preset */static gintwtbl_preset_mem_required (SFPreset *pset, SFData *sf, gboolean locked,			  GTree *gt){  GTree *gtree;  SFZone *z;  GSList *p;  gint size = 0;  gint rv;  /* create a binary tree if not supplied, for counting duplicates only once */  if (!gt) gtree = g_tree_new (wtbl_ptr_compare_func);  else gtree = gt;  p = pset->zone;  while (p)			/* loop over preset zones */    {      z = (SFZone *)(p->data);      if (z->instsamp)	{	  rv = wtbl_inst_mem_required ((SFInst *)(((GSList *)(z->instsamp))						  ->data), sf, locked, gtree);	  if (rv == -1) break;	/* error occured? */	  size += rv;	}      p = g_slist_next (p);    }  if (!gt) g_tree_destroy (gtree);  if (p == NULL) return (size);	/* all preset zones processed? */  else return (-1);		/* ?: NO, error occured */}/* amount of sample memory required to load an instrument */static gintwtbl_inst_mem_required (SFInst *inst, SFData *sf, gboolean locked, GTree *gt){  GTree *gtree;  SFZone *z;  SFSample *sam;  GSList *p;  gint size = 0;  gint rv;  /* create a binary tree if not supplied, for counting duplicates only once */

⌨️ 快捷键说明

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