📄 sndfont.c
字号:
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;}/* * convert timecents to sec */static double to_msec(int timecent){ return timecent == -12000 ? 0 : 1000.0 * pow(2.0, (double)timecent / 1200.0);}/* * Sustain level * sf: centibels * parm: 0x7f - sustain_level(dB) * 0.75 */static int32 calc_sustain(int sust_cB){ if(sust_cB <= 0) {return 65533;} else if(sust_cB >= 1000) {return 0;} else {return (1000 - sust_cB) * 65533 / 1000;}}static Instrument *load_from_file(SFInsts *rec, InstList *ip){ SampleList *sp; Instrument *inst; int i; int32 len; if(ip->pat.bank == 128) ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading SF Drumset %d %d: %s", ip->pat.preset + progbase, ip->pat.keynote, rec->inst_namebuf[ip->pr_idx]); else ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading SF Tonebank %d %d: %s", ip->pat.bank, ip->pat.preset + progbase, rec->inst_namebuf[ip->pr_idx]); inst = (Instrument *)safe_malloc(sizeof(Instrument)); inst->instname = rec->inst_namebuf[ip->pr_idx]; inst->type = INST_SF2; inst->samples = ip->samples; inst->sample = (Sample *)safe_malloc(sizeof(Sample) * ip->samples); memset(inst->sample, 0, sizeof(Sample) * ip->samples); for (i = 0, sp = ip->slist; i < ip->samples && sp; i++, sp = sp->next) { Sample *sample = inst->sample + i; int32 j;#ifndef LITTLE_ENDIAN int32 k; int16 *tmp, s;#endif ctl->cmsg(CMSG_INFO, VERB_DEBUG, "[%d] Rate=%d LV=%d HV=%d " "Low=%d Hi=%d Root=%d Pan=%d", sp->start, sp->v.sample_rate, sp->v.low_vel, sp->v.high_vel, sp->v.low_freq, sp->v.high_freq, sp->v.root_freq, sp->v.panning); memcpy(sample, &sp->v, sizeof(Sample)); sample->data = NULL; sample->data_alloced = 0; if(i > 0 && (!sample->note_to_use || (sample->modes & MODES_LOOPING))) { SampleList *sps; Sample *found, *s; found = NULL; for(j = 0, sps = ip->slist, s = inst->sample; j < i && sps; j++, sps = sps->next, s++) { if(s->data == NULL) break; if(sp->start == sps->start) { if(antialiasing_allowed) { if(sample->data_length != s->data_length || sample->sample_rate != s->sample_rate) continue; } if(s->note_to_use && !(s->modes & MODES_LOOPING)) continue; found = s; break; } } if(found) { sample->data = found->data; sample->data_alloced = 0; ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * Cached"); continue; } } sample->data = (sample_t *)safe_large_malloc(sp->len + 2 * 3); sample->data_alloced = 1; tf_seek(rec->tf, sp->start, SEEK_SET); tf_read(sample->data, sp->len, 1, rec->tf);#ifndef LITTLE_ENDIAN tmp = (int16*)sample->data; k = sp->len / 2; for (j = 0; j < k; j++) { s = LE_SHORT(*tmp); *tmp++ = s; }#endif /* set a small blank loop at the tail for avoiding abnormal loop. */ len = sp->len / 2; sample->data[len] = sample->data[len + 1] = sample->data[len + 2] = 0; if (antialiasing_allowed) antialiasing((int16 *)sample->data, sample->data_length >> FRACTION_BITS, sample->sample_rate, play_mode->rate); /* resample it if possible */ if (sample->note_to_use && !(sample->modes & MODES_LOOPING)) pre_resample(sample); /* do pitch detection on drums if surround chorus is used */ if (ip->pat.bank == 128 && opt_surround_chorus) { sample->chord = -1; sample->root_freq_detected = freq_fourier(sample, &(sample->chord)); sample->transpose_detected = assign_pitch_to_freq(sample->root_freq_detected) - assign_pitch_to_freq(sample->root_freq / 1024.0); }#ifdef LOOKUP_HACK squash_sample_16to8(sample);#endif } return inst;}/*---------------------------------------------------------------- * excluded samples *----------------------------------------------------------------*/int exclude_soundfont(int bank, int preset, int keynote){ SFExclude *exc; if(current_sfrec == NULL) return 1; exc = (SFExclude*)SFMalloc(current_sfrec , sizeof(SFExclude)); exc->pat.bank = bank; exc->pat.preset = preset; exc->pat.keynote = keynote; exc->next = current_sfrec->sfexclude; current_sfrec->sfexclude = exc; return 0;}/* check the instrument is specified to be excluded */static int is_excluded(SFInsts *rec, int bank, int preset, int keynote){ SFExclude *p; for (p = rec->sfexclude; p; p = p->next) { if (p->pat.bank == bank && (p->pat.preset < 0 || p->pat.preset == preset) && (p->pat.keynote < 0 || p->pat.keynote == keynote)) return 1; } return 0;}/*---------------------------------------------------------------- * ordered samples *----------------------------------------------------------------*/int order_soundfont(int bank, int preset, int keynote, int order){ SFOrder *p; if(current_sfrec == NULL) return 1; p = (SFOrder*)SFMalloc(current_sfrec, sizeof(SFOrder)); p->pat.bank = bank; p->pat.preset = preset; p->pat.keynote = keynote; p->order = order; p->next = current_sfrec->sforder; current_sfrec->sforder = p; return 0;}/* check the instrument is specified to be ordered */static int is_ordered(SFInsts *rec, int bank, int preset, int keynote){ SFOrder *p; for (p = rec->sforder; p; p = p->next) { if (p->pat.bank == bank && (p->pat.preset < 0 || p->pat.preset == preset) && (p->pat.keynote < 0 || p->pat.keynote == keynote)) return p->order; } return -1;}/*----------------------------------------------------------------*/static int load_font(SFInfo *sf, int pridx){ SFPresetHdr *preset = &sf->preset[pridx]; int rc, j, nlayers; SFGenLayer *layp, *globalp; /* if layer is empty, skip it */ if ((nlayers = preset->hdr.nlayers) <= 0 || (layp = preset->hdr.layer) == NULL) return AWE_RET_SKIP; /* check global layer */ globalp = NULL; if (is_global(layp)) { globalp = layp; layp++; nlayers--; } /* parse for each preset layer */ for (j = 0; j < nlayers; j++, layp++) { LayerTable tbl; /* set up table */ clear_table(&tbl); if (globalp) set_to_table(sf, &tbl, globalp, P_GLOBAL); set_to_table(sf, &tbl, layp, P_LAYER); /* parse the instrument */ rc = parse_layer(sf, pridx, &tbl, 0); if(rc == AWE_RET_ERR || rc == AWE_RET_NOMEM) return rc; } return AWE_RET_OK;}/*----------------------------------------------------------------*//* parse a preset layer and convert it to the patch structure */static int parse_layer(SFInfo *sf, int pridx, LayerTable *tbl, int level){ SFInstHdr *inst; int rc, i, nlayers; SFGenLayer *lay, *globalp;#if 0 SFPresetHdr *preset = &sf->preset[pridx];#endif if (level >= 2) { fprintf(stderr, "parse_layer: too deep instrument level\n"); return AWE_RET_ERR; } /* instrument must be defined */ if (!tbl->set[SF_instrument]) return AWE_RET_SKIP; inst = &sf->inst[tbl->val[SF_instrument]]; /* Here, TiMidity makes the reference of the data. The real data * is loaded after. So, duplicated data is allowed */#if 0 /* if non-standard drumset includes standard drum instruments, skip it to avoid duplicate the data */ if (def_drum_inst >= 0 && preset->bank == 128 && preset->preset != 0 && tbl->val[SF_instrument] == def_drum_inst) return AWE_RET_SKIP;#endif /* if layer is empty, skip it */ if ((nlayers = inst->hdr.nlayers) <= 0 || (lay = inst->hdr.layer) == NULL) return AWE_RET_SKIP; /* check global layer */ globalp = NULL; if (is_global(lay)) { globalp = lay; lay++; nlayers--; } /* parse for each layer */ for (i = 0; i < nlayers; i++, lay++) { LayerTable ctbl; clear_table(&ctbl); if (globalp) set_to_table(sf, &ctbl, globalp, P_GLOBAL); set_to_table(sf, &ctbl, lay, P_LAYER); if (!ctbl.set[SF_sampleId]) { /* recursive loading */ merge_table(sf, &ctbl, tbl); if (! sanity_range(&ctbl)) continue; rc = parse_layer(sf, pridx, &ctbl, level+1); if (rc != AWE_RET_OK && rc != AWE_RET_SKIP) return rc; } else { init_and_merge_table(sf, &ctbl, tbl); if (! sanity_range(&ctbl)) continue; /* load the info data */ if ((rc = make_patch(sf, pridx, &ctbl)) == AWE_RET_ERR) return rc; } } return AWE_RET_OK;}static int is_global(SFGenLayer *layer){ int i; for (i = 0; i < layer->nlists; i++) { if (layer->list[i].oper == SF_instrument || layer->list[i].oper == SF_sampleId) return 0; } return 1;}/*---------------------------------------------------------------- * layer table handlers *----------------------------------------------------------------*//* initialize layer table */static void clear_table(LayerTable *tbl){ memset(tbl->val, 0, sizeof(tbl->val)); memset(tbl->set, 0, sizeof(tbl->set));}/* set items in a layer to the table */static void set_to_table(SFInfo *sf, LayerTable *tbl, SFGenLayer *lay, int level){ int i; for (i = 0; i < lay->nlists; i++) { SFGenRec *gen = &lay->list[i]; /* copy the value regardless of its copy policy */ tbl->val[gen->oper] = gen->amount; tbl->set[gen->oper] = level; }}/* add an item to the table */static void add_item_to_table(LayerTable *tbl, int oper, int amount, int level){ LayerItem *item = &layer_items[oper]; int o_lo, o_hi, lo, hi; switch (item->copy) { case L_INHRT: tbl->val[oper] += amount; break; case L_OVWRT: tbl->val[oper] = amount; break; case L_PRSET: case L_INSTR: /* do not overwrite */ if (!tbl->set[oper]) tbl->val[oper] = amount; break; case L_RANGE: if (!tbl->set[oper]) { tbl->val[oper] = amount; } else { o_lo = LOWNUM(tbl->val[oper]); o_hi = HIGHNUM(tbl->val[oper]); lo = LOWNUM(amount); hi = HIGHNUM(amount); if (lo < o_lo) lo = o_lo; if (hi > o_hi) hi = o_hi; tbl->val[oper] = RANGE(lo, hi); } break; }}/* merge two tables */static void merge_table(SFInfo *sf, LayerTable *dst, LayerTable *src){ int i; for (i = 0; i < SF_EOF; i++) { if (src->set[i]) { if (sf->version == 1) { if (!dst->set[i] || i == SF_keyRange || i == SF_velRange) /* just copy it */ dst->val[i] = src->val[i]; } else add_item_to_table(dst, i, src->val[i], P_GLOBAL); dst->set[i] = P_GLOBAL; } }}/* merge and set default values */static void init_and_merge_table(SFInfo *sf, LayerTable *dst, LayerTable *src){ int i; /* default value is not zero */ if (sf->version == 1) { layer_items[SF_sustainEnv1].defv = 1000; layer_items[SF_sustainEnv2].defv = 1000; layer_items[SF_freqLfo1].defv = -725; layer_items[SF_freqLfo2].defv = -15600; } else { layer_items[SF_sustainEnv1].defv = 0; layer_items[SF_sustainEnv2].defv = 0; layer_items[SF_freqLfo1].defv = 0; layer_items[SF_freqLfo2].defv = 0; } /* set default */ for (i = 0; i < SF_EOF; i++) { if (!dst->set[i]) dst->val[i] = layer_items[i].defv; } merge_table(sf, dst, src); /* convert from SBK to SF2 */ if (sf->version == 1) { for (i = 0; i < SF_EOF; i++) { if (dst->set[i]) dst->val[i] = sbk_to_sf2(i, dst->val[i]); } }}/*---------------------------------------------------------------- * check key and velocity range *----------------------------------------------------------------*/static int sanity_range(LayerTable *tbl){ int lo, hi; lo = LOWNUM(tbl->val[SF_keyRange]); hi = HIGHNUM(tbl->val[SF_keyRange]); if (lo < 0 || lo > 127 || hi < 0 || hi > 127 || hi < lo) return 0; lo = LOWNUM(tbl->val[SF_velRange]); hi = HIGHNUM(tbl->val[SF_velRange]); if (lo < 0 || lo > 127 || hi < 0 || hi > 127 || hi < lo) return 0; return 1;}/*---------------------------------------------------------------- * create patch record from the stored data table *----------------------------------------------------------------*/#ifdef CFG_FOR_SFint opt_reverb_control; /* to avoid warning. */static int cfg_for_sf_scan(char *name, int x_bank, int x_preset, int x_keynote_from, int x_keynote_to, int romflag);#endifstatic int make_patch(SFInfo *sf, int pridx, LayerTable *tbl){ int bank, preset, keynote; int keynote_from, keynote_to, done; int addr, order; InstList *ip; SFSampleInfo *sample; SampleList *sp; sample = &sf->sample[tbl->val[SF_sampleId]];#ifdef CFG_FOR_SF cfg_for_sf_scan(sample->name,sf->preset[pridx].bank,sf->preset[pridx].preset,LOWNUM(tbl->val[SF_keyRange]), HIGHNUM(tbl->val[SF_keyRange]),sample->sampletype & SF_SAMPLETYPE_ROM);#endif if(sample->sampletype & SF_SAMPLETYPE_ROM) /* is ROM sample? */ { ctl->cmsg(CMSG_INFO, VERB_DEBUG, "preset %d is ROM sample: 0x%x", pridx, sample->sampletype); return AWE_RET_SKIP; } bank = sf->preset[pridx].bank; preset = sf->preset[pridx].preset; if(bank == 128){ keynote_from = LOWNUM(tbl->val[SF_keyRange]); keynote_to = HIGHNUM(tbl->val[SF_keyRange]); } else keynote_from = keynote_to = -1; done = 0; for(keynote=keynote_from;keynote<=keynote_to;keynote++){ ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY, "SF make inst pridx=%d bank=%d preset=%d keynote=%d", pridx, bank, preset, keynote); if(is_excluded(current_sfrec, bank, preset, keynote)) { ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY, " * Excluded"); continue; } else done++; order = is_ordered(current_sfrec, bank, preset, keynote); if(order < 0) order = current_sfrec->def_order; addr = INSTHASH(bank, preset, keynote); for(ip = current_sfrec->instlist[addr]; ip; ip = ip->next) { if(ip->pat.bank == bank && ip->pat.preset == preset &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -