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

📄 instrum.c

📁 SDL_mixer 是一个基于 SDL 的混音器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    TiMidity -- Experimental MIDI to WAVE converter    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>    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., 675 Mass Ave, Cambridge, MA 02139, USA.   instrum.c       Code to load and unload GUS-compatible instrument patches.*/#include <stdio.h>#include <string.h>#include <stdlib.h>#include "config.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "output.h"#include "ctrlmode.h"#include "resample.h"#include "tables.h"#include "filter.h"/* Some functions get aggravated if not even the standard banks are    available. */static ToneBank standard_tonebank, standard_drumset;ToneBank   *tonebank[MAXBANK]={&standard_tonebank},  *drumset[MAXBANK]={&standard_drumset};/* This is a special instrument, used for all melodic programs */InstrumentLayer *default_instrument=0;/* This is only used for tracks that don't specify a program */int default_program=DEFAULT_PROGRAM;int antialiasing_allowed=0;#ifdef FAST_DECAYint fast_decay=1;#elseint fast_decay=0;#endifint current_tune_number = 0;int last_tune_purged = 0;int current_patch_memory = 0;int max_patch_memory = 60000000;static void purge_as_required(void);static void free_instrument(Instrument *ip){  Sample *sp;  int i;  if (!ip) return;  if (!ip->contents)  for (i=0; i<ip->samples; i++)    {      sp=&(ip->sample[i]);      if (sp->data) free(sp->data);    }  free(ip->sample);  if (!ip->contents)  for (i=0; i<ip->right_samples; i++)    {      sp=&(ip->right_sample[i]);      if (sp->data) free(sp->data);    }  if (ip->right_sample)    free(ip->right_sample);  free(ip);}static void free_layer(InstrumentLayer *lp){  InstrumentLayer *next;  current_patch_memory -= lp->size;  for (; lp; lp = next)   {     next = lp->next;     free_instrument(lp->instrument);     free(lp);   }}static void free_bank(int dr, int b){  int i;  ToneBank *bank=((dr) ? drumset[b] : tonebank[b]);  for (i=0; i<MAXPROG; i++)  {    if (bank->tone[i].layer)    {	  /* Not that this could ever happen, of course */	  if (bank->tone[i].layer != MAGIC_LOAD_INSTRUMENT)	  {	    free_layer(bank->tone[i].layer);	    bank->tone[i].layer=NULL;	    bank->tone[i].last_used=-1;	  }    }    if (bank->tone[i].name)    {      free(bank->tone[i].name);      bank->tone[i].name = NULL;    }  }}static void free_old_bank(int dr, int b, int how_old){  int i;  ToneBank *bank=((dr) ? drumset[b] : tonebank[b]);  for (i=0; i<MAXPROG; i++)    if (bank->tone[i].layer && bank->tone[i].last_used < how_old)      {	if (bank->tone[i].layer != MAGIC_LOAD_INSTRUMENT)	  {	    ctl->cmsg(CMSG_INFO, VERB_DEBUG,		"Unloading %s %s[%d,%d] - last used %d.",		(dr)? "drum" : "inst", bank->tone[i].name,		i, b, bank->tone[i].last_used);	    free_layer(bank->tone[i].layer);	    bank->tone[i].layer=NULL;	    bank->tone[i].last_used=-1;	  }      }}int32 convert_envelope_rate_attack(uint8 rate, uint8 fastness){  int32 r;  r=3-((rate>>6) & 0x3);  r*=3;  r = (int32)(rate & 0x3f) << r; /* 6.9 fixed point */  /* 15.15 fixed point. */  return (((r * 44100) / play_mode->rate) * control_ratio)     << 10;}int32 convert_envelope_rate(uint8 rate){  int32 r;  r=3-((rate>>6) & 0x3);  r*=3;  r = (int32)(rate & 0x3f) << r; /* 6.9 fixed point */  /* 15.15 fixed point. */  return (((r * 44100) / play_mode->rate) * control_ratio)     << ((fast_decay) ? 10 : 9);}int32 convert_envelope_offset(uint8 offset){  /* This is not too good... Can anyone tell me what these values mean?     Are they GUS-style "exponential" volumes? And what does that mean? */  /* 15.15 fixed point */  return offset << (7+15);}int32 convert_tremolo_sweep(uint8 sweep){  if (!sweep)    return 0;  return    ((control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /      (play_mode->rate * sweep);}int32 convert_vibrato_sweep(uint8 sweep, int32 vib_control_ratio){  if (!sweep)    return 0;  return    (int32) (FSCALE((double) (vib_control_ratio) * SWEEP_TUNING, SWEEP_SHIFT)	     / (double)(play_mode->rate * sweep));  /* this was overflowing with seashore.pat      ((vib_control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /      (play_mode->rate * sweep); */}int32 convert_tremolo_rate(uint8 rate){  return    ((SINE_CYCLE_LENGTH * control_ratio * rate) << RATE_SHIFT) /      (TREMOLO_RATE_TUNING * play_mode->rate);}int32 convert_vibrato_rate(uint8 rate){  /* Return a suitable vibrato_control_ratio value */  return    (VIBRATO_RATE_TUNING * play_mode->rate) /       (rate * 2 * VIBRATO_SAMPLE_INCREMENTS);}static void reverse_data(int16 *sp, int32 ls, int32 le){  int16 s, *ep=sp+le;  sp+=ls;  le-=ls;  le/=2;  while (le--)    {      s=*sp;      *sp++=*ep;      *ep--=s;    }}/*    If panning or note_to_use != -1, it will be used for all samples,   instead of the sample-specific values in the instrument file.    For note_to_use, any value <0 or >127 will be forced to 0.    For other parameters, 1 means yes, 0 means no, other values are   undefined.   TODO: do reverse loops right */static InstrumentLayer *load_instrument(char *name, int font_type, int percussion,				   int panning, int amp, int cfg_tuning, int note_to_use,				   int strip_loop, int strip_envelope,				   int strip_tail, int bank, int gm_num, int sf_ix){  InstrumentLayer *lp, *lastlp, *headlp;  Instrument *ip;  FILE *fp;  uint8 tmp[1024];  int i,j,noluck=0;#ifdef PATCH_EXT_LIST  static char *patch_ext[] = PATCH_EXT_LIST;#endif  int sf2flag = 0;  int right_samples = 0;  int stereo_channels = 1, stereo_layer;  int vlayer_list[19][4], vlayer, vlayer_count;  if (!name) return 0;    /* Open patch file */  if ((fp=open_file(name, 1, OF_NORMAL)) == NULL)    {      noluck=1;#ifdef PATCH_EXT_LIST      /* Try with various extensions */      for (i=0; patch_ext[i]; i++)	{	  if (strlen(name)+strlen(patch_ext[i])<1024)	    {              char path[1024];	      strcpy(path, name);	      strcat(path, patch_ext[i]);	      if ((fp=open_file(path, 1, OF_NORMAL)) != NULL)		{		  noluck=0;		  break;		}	    }	}#endif    }    if (noluck)    {      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 		"Instrument `%s' can't be found.", name);      return 0;    }        /*ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/    /* Read some headers and do cursory sanity checks. There are loads     of magic offsets. This could be rewritten... */  if ((239 != fread(tmp, 1, 239, fp)) ||      (memcmp(tmp, "GF1PATCH110\0ID#000002", 22) &&       memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the						      differences are */    {      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);      return 0;    }/* patch layout: * bytes:  info:		starts at offset: * 22	id (see above)		0 * 60	copyright		22 *  1	instruments		82 *  1	voices			83 *  1	channels		84 *  2	number of waveforms	85 *  2	master volume		87 *  4	datasize		89 * 36   reserved, but now:	93 * 	7 "SF2EXT\0" id			93 * 	1 right samples		       100 *     28 reserved		       101 *  2	instrument number	129 * 16	instrument name		131 *  4	instrument size		147 *  1	number of layers	151 * 40	reserved		152 *  1	layer duplicate		192 *  1	layer number		193 *  4	layer size		194 *  1	number of samples	198 * 40	reserved		199 * 				239 * THEN, for each sample, see below */  if (!memcmp(tmp + 93, "SF2EXT", 6))    {	    sf2flag = 1;	    vlayer_count = tmp[152];    }  if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 				       0 means 1 */    {      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 	   "Can't handle patches with %d instruments", tmp[82]);      return 0;    }  if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */    {      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 	   "Can't handle instruments with %d layers", tmp[151]);      return 0;    }    if (sf2flag && vlayer_count > 0) {	for (i = 0; i < 9; i++)	  for (j = 0; j < 4; j++)	    vlayer_list[i][j] = tmp[153+i*4+j];	for (i = 9; i < 19; i++)	  for (j = 0; j < 4; j++)	    vlayer_list[i][j] = tmp[199+(i-9)*4+j];  }  else {	for (i = 0; i < 19; i++)	  for (j = 0; j < 4; j++)	    vlayer_list[i][j] = 0;	vlayer_list[0][0] = 0;	vlayer_list[0][1] = 127;	vlayer_list[0][2] = tmp[198];	vlayer_list[0][3] = 0;	vlayer_count = 1;  }  lastlp = 0;  for (vlayer = 0; vlayer < vlayer_count; vlayer++) {  lp=(InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer));  lp->size = sizeof(InstrumentLayer);  lp->lo = vlayer_list[vlayer][0];  lp->hi = vlayer_list[vlayer][1];  ip=(Instrument *)safe_malloc(sizeof(Instrument));  lp->size += sizeof(Instrument);  lp->instrument = ip;  lp->next = 0;  if (lastlp) lastlp->next = lp;  else headlp = lp;  lastlp = lp;  if (sf2flag) ip->type = INST_SF2;  else ip->type = INST_GUS;  ip->samples = vlayer_list[vlayer][2];  ip->sample = (Sample *)safe_malloc(sizeof(Sample) * ip->samples);  lp->size += sizeof(Sample) * ip->samples;  ip->left_samples = ip->samples;  ip->left_sample = ip->sample;  right_samples = vlayer_list[vlayer][3];  ip->right_samples = right_samples;  if (right_samples)    {      ip->right_sample = (Sample *)safe_malloc(sizeof(Sample) * right_samples);      lp->size += sizeof(Sample) * right_samples;      stereo_channels = 2;    }  else ip->right_sample = 0;  ip->contents = 0;  ctl->cmsg(CMSG_INFO, VERB_NOISY, "%s%s[%d,%d] %s(%d-%d layer %d of %d)",	(percussion)? "   ":"", name,	(percussion)? note_to_use : gm_num, bank,	(right_samples)? "(2) " : "",	lp->lo, lp->hi, vlayer+1, vlayer_count); for (stereo_layer = 0; stereo_layer < stereo_channels; stereo_layer++) {  int sample_count;  if (stereo_layer == 0) sample_count = ip->left_samples;  else if (stereo_layer == 1) sample_count = ip->right_samples;  for (i=0; i < sample_count; i++)    {      uint8 fractions;      int32 tmplong;      uint16 tmpshort;      uint16 sample_volume;      uint8 tmpchar;      Sample *sp;      uint8 sf2delay;#define READ_CHAR(thing) \      if (1 != fread(&tmpchar, 1, 1, fp)) goto fail; \      thing = tmpchar;#define READ_SHORT(thing) \      if (1 != fread(&tmpshort, 2, 1, fp)) goto fail; \      thing = LE_SHORT(tmpshort);#define READ_LONG(thing) \      if (1 != fread(&tmplong, 4, 1, fp)) goto fail; \      thing = LE_LONG(tmplong);/* *  7	sample name *  1	fractions *  4	length *  4	loop start *  4	loop end *  2	sample rate *  4	low frequency *  4	high frequency *  2	finetune *  1	panning *  6	envelope rates			| *  6	envelope offsets		|  18 bytes *  3	tremolo sweep, rate, depth	| *  3	vibrato sweep, rate, depth	| *  1	sample mode *  2	scale frequency *  2	scale factor *  2	sample volume (??) * 34	reserved * Now: 1	delay * 	33	reserved */      skip(fp, 7); /* Skip the wave name */      if (1 != fread(&fractions, 1, 1, fp))	{	fail:	  ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);	  if (stereo_layer == 1)	     {	       for (j=0; j<i; j++)	         free(ip->right_sample[j].data);	       free(ip->right_sample);	       i = ip->left_samples;	     }	  for (j=0; j<i; j++)	    free(ip->left_sample[j].data);	  free(ip->left_sample);	  free(ip);	  free(lp);	  return 0;	}      if (stereo_layer == 0) sp=&(ip->left_sample[i]);      else if (stereo_layer == 1) sp=&(ip->right_sample[i]);      READ_LONG(sp->data_length);      READ_LONG(sp->loop_start);      READ_LONG(sp->loop_end);      READ_SHORT(sp->sample_rate);      READ_LONG(sp->low_freq);      READ_LONG(sp->high_freq);      READ_LONG(sp->root_freq);      skip(fp, 2); /* Why have a "root frequency" and then "tuning"?? */            READ_CHAR(tmp[0]);      if (panning==-1)	sp->panning = (tmp[0] * 8 + 4) & 0x7f;

⌨️ 快捷键说明

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