📄 instrum.c
字号:
/* TiMidity++ -- MIDI to WAVE converter and player Copyright (C) 1999-2004 Masanao Izumo <iz@onicos.co.jp> Copyright (C) 1995 Tuukka Toivonen <tt@cgs.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA instrum.c Code to load and unload GUS-compatible instrument patches.*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#include <stdlib.h>#include <math.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include "timidity.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "readmidi.h"#include "output.h"#include "controls.h"#include "resample.h"#include "tables.h"#include "filter.h"#include "quantity.h"#include "freq.h"#define INSTRUMENT_HASH_SIZE 128struct InstrumentCache{ char *name; int panning, amp, note_to_use, strip_loop, strip_envelope, strip_tail; Instrument *ip; struct InstrumentCache *next;};static struct InstrumentCache *instrument_cache[INSTRUMENT_HASH_SIZE];/* Some functions get aggravated if not even the standard banks are available. */static ToneBank standard_tonebank, standard_drumset;ToneBank *tonebank[128 + MAP_BANK_COUNT] = {&standard_tonebank}, *drumset[128 + MAP_BANK_COUNT] = {&standard_drumset};/* bank mapping (mapped bank) */struct bank_map_elem { int16 used, mapid; int bankno;};static struct bank_map_elem map_bank[MAP_BANK_COUNT], map_drumset[MAP_BANK_COUNT];static int map_bank_counter;/* This is a special instrument, used for all melodic programs */Instrument *default_instrument=0;SpecialPatch *special_patch[NSPECIAL_PATCH];int progbase = 0;struct inst_map_elem{ int set, elem, mapped;};static struct inst_map_elem *inst_map_table[NUM_INST_MAP][128];/* This is only used for tracks that don't specify a program */int default_program[MAX_CHANNELS];char *default_instrument_name = NULL;int antialiasing_allowed=0;#ifdef FAST_DECAYint fast_decay=1;#elseint fast_decay=0;#endif/*Pseudo Reverb*/int32 modify_release;/** below three functinos are imported from sndfont.c **//* convert from 8bit value to fractional offset (15.15) */static int32 to_offset(int offset){ return (int32)offset << (7+15);}/* calculate ramp rate in fractional unit; * diff = 8bit, time = msec */static int32 calc_rate(int diff, double msec){ double rate; if(msec < 6) msec = 6; if(diff == 0) diff = 255; diff <<= (7+15); rate = ((double)diff / play_mode->rate) * control_ratio * 1000.0 / msec; if(fast_decay) rate *= 2; return (int32)rate;}/*End of Pseudo Reverb*/void free_instrument(Instrument *ip){ Sample *sp; int i; if (!ip) return; for (i=0; i<ip->samples; i++) { sp=&(ip->sample[i]); if(sp->data_alloced) free(sp->data); } free(ip->sample); free(ip);}void clear_magic_instruments(void){ int i, j; for(j = 0; j < 128 + map_bank_counter; j++) { if(tonebank[j]) { ToneBank *bank = tonebank[j]; for(i = 0; i < 128; i++) if(IS_MAGIC_INSTRUMENT(bank->tone[i].instrument)) bank->tone[i].instrument = NULL; } if(drumset[j]) { ToneBank *bank = drumset[j]; for(i = 0; i < 128; i++) if(IS_MAGIC_INSTRUMENT(bank->tone[i].instrument)) bank->tone[i].instrument = NULL; } }}#define GUS_ENVRATE_MAX (int32)(0x3FFFFFFF >> 9)static 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. */ r = r * 44100 / play_mode->rate * control_ratio * (1 << fast_decay); if(r > GUS_ENVRATE_MAX) {r = GUS_ENVRATE_MAX;} return (r << 9);}static 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);}static int32 convert_tremolo_sweep(uint8 sweep){ if (!sweep) return 0; return ((control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) / (play_mode->rate * sweep);}static int32 convert_vibrato_sweep(uint8 sweep, int32 vib_control_ratio){ if (!sweep) return 0; return (int32)(TIM_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); */}static int32 convert_tremolo_rate(uint8 rate){ return ((SINE_CYCLE_LENGTH * control_ratio * rate) << RATE_SHIFT) / (TREMOLO_RATE_TUNING * play_mode->rate);}static 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; int32 i; sp+=ls; le-=ls; le/=2; for(i = 0; i < le; i++) { s=*sp; *sp++=*ep; *ep--=s; }}static int name_hash(char *name){ unsigned int addr = 0; while(*name) addr += *name++; return addr % INSTRUMENT_HASH_SIZE;}static Instrument *search_instrument_cache(char *name, int panning, int amp, int note_to_use, int strip_loop, int strip_envelope, int strip_tail){ struct InstrumentCache *p; for(p = instrument_cache[name_hash(name)]; p != NULL; p = p->next) { if(strcmp(p->name, name) != 0) return NULL; if(p->panning == panning && p->amp == amp && p->note_to_use == note_to_use && p->strip_loop == strip_loop && p->strip_envelope == strip_envelope && p->strip_tail == strip_tail) return p->ip; } return NULL;}static void store_instrument_cache(Instrument *ip, char *name, int panning, int amp, int note_to_use, int strip_loop, int strip_envelope, int strip_tail){ struct InstrumentCache *p; int addr; addr = name_hash(name); p = (struct InstrumentCache *)safe_malloc(sizeof(struct InstrumentCache)); p->next = instrument_cache[addr]; instrument_cache[addr] = p; p->name = name; p->panning = panning; p->amp = amp; p->note_to_use = note_to_use; p->strip_loop = strip_loop; p->strip_envelope = strip_envelope; p->strip_tail = strip_tail; p->ip = ip;}static int32 adjust_tune_freq(int32 val, float tune){ if (! tune) return val; return val / pow(2.0, tune / 12.0);}static int16 adjust_scale_tune(int16 val){ return 1024 * (double) val / 100 + 0.5;}static int16 adjust_fc(int16 val){ if (val < 0 || val > play_mode->rate / 2) { return 0; } else { return val; }}static int16 adjust_reso(int16 val){ if (val < 0 || val > 960) { return 0; } else { return val; }}static int32 to_rate(int rate){ return (rate) ? (int32) (0x200 * pow(2.0, rate / 17.0) * 44100 / play_mode->rate * control_ratio) << fast_decay : 0;}#if 0static int32 to_control(int control){ return (int32) (0x2000 / pow(2.0, control / 31.0));}#endifstatic void apply_bank_parameter(Instrument *ip, ToneBankElement *tone){ int i, j; Sample *sp; if (tone->tunenum) for (i = 0; i < ip->samples; i++) { sp = &ip->sample[i]; if (tone->tunenum == 1) { sp->low_freq = adjust_tune_freq(sp->low_freq, tone->tune[0]); sp->high_freq = adjust_tune_freq(sp->high_freq, tone->tune[0]); sp->root_freq = adjust_tune_freq(sp->root_freq, tone->tune[0]); } else if (i < tone->tunenum) { sp->low_freq = adjust_tune_freq(sp->low_freq, tone->tune[i]); sp->high_freq = adjust_tune_freq(sp->high_freq, tone->tune[i]); sp->root_freq = adjust_tune_freq(sp->root_freq, tone->tune[i]); } } if (tone->envratenum) for (i = 0; i < ip->samples; i++) { sp = &ip->sample[i]; if (tone->envratenum == 1) { for (j = 0; j < 6; j++) if (tone->envrate[0][j] >= 0) sp->envelope_rate[j] = to_rate(tone->envrate[0][j]); } else if (i < tone->envratenum) { for (j = 0; j < 6; j++) if (tone->envrate[i][j] >= 0) sp->envelope_rate[j] = to_rate(tone->envrate[i][j]); } } if (tone->envofsnum) for (i = 0; i < ip->samples; i++) { sp = &ip->sample[i]; if (tone->envofsnum == 1) { for (j = 0; j < 6; j++) if (tone->envofs[0][j] >= 0) sp->envelope_offset[j] = to_offset(tone->envofs[0][j]); } else if (i < tone->envofsnum) { for (j = 0; j < 6; j++) if (tone->envofs[i][j] >= 0) sp->envelope_offset[j] = to_offset(tone->envofs[i][j]); } } if (tone->tremnum) for (i = 0; i < ip->samples; i++) { sp = &ip->sample[i]; if (tone->tremnum == 1) { if (IS_QUANTITY_DEFINED(tone->trem[0][0])) sp->tremolo_sweep_increment = quantity_to_int(&tone->trem[0][0], 0); if (IS_QUANTITY_DEFINED(tone->trem[0][1])) sp->tremolo_phase_increment = quantity_to_int(&tone->trem[0][1], 0); if (IS_QUANTITY_DEFINED(tone->trem[0][2])) sp->tremolo_depth = quantity_to_int(&tone->trem[0][2], 0) << 1; } else if (i < tone->tremnum) { if (IS_QUANTITY_DEFINED(tone->trem[i][0])) sp->tremolo_sweep_increment = quantity_to_int(&tone->trem[i][0], 0); if (IS_QUANTITY_DEFINED(tone->trem[i][1])) sp->tremolo_phase_increment = quantity_to_int(&tone->trem[i][1], 0); if (IS_QUANTITY_DEFINED(tone->trem[i][2])) sp->tremolo_depth = quantity_to_int(&tone->trem[i][2], 0) << 1; } } if (tone->vibnum) for (i = 0; i < ip->samples; i++) { sp = &ip->sample[i]; if (tone->vibnum == 1) { if (IS_QUANTITY_DEFINED(tone->vib[0][1])) sp->vibrato_control_ratio = quantity_to_int(&tone->vib[0][1], 0); if (IS_QUANTITY_DEFINED(tone->vib[0][0])) sp->vibrato_sweep_increment = quantity_to_int(&tone->vib[0][0], sp->vibrato_control_ratio); if (IS_QUANTITY_DEFINED(tone->vib[0][2])) sp->vibrato_depth = quantity_to_int(&tone->vib[0][2], 0); } else if (i < tone->vibnum) { if (IS_QUANTITY_DEFINED(tone->vib[i][1])) sp->vibrato_control_ratio = quantity_to_int(&tone->vib[i][1], 0); if (IS_QUANTITY_DEFINED(tone->vib[i][0])) sp->vibrato_sweep_increment = quantity_to_int(&tone->vib[i][0], sp->vibrato_control_ratio); if (IS_QUANTITY_DEFINED(tone->vib[i][2])) sp->vibrato_depth = quantity_to_int(&tone->vib[i][2], 0); } } if (tone->sclnotenum) for (i = 0; i < ip->samples; i++) { sp = &ip->sample[i]; if (tone->sclnotenum == 1) sp->scale_freq = tone->sclnote[0]; else if (i < tone->sclnotenum) sp->scale_freq = tone->sclnote[i]; } if (tone->scltunenum) for (i = 0; i < ip->samples; i++) { sp = &ip->sample[i]; if (tone->scltunenum == 1) sp->scale_factor = adjust_scale_tune(tone->scltune[0]); else if (i < tone->scltunenum)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -