📄 sffile.c
字号:
/*================================================================ * process sample data list *================================================================*/static int process_sdta(int size, SFInfo *sf, struct timidity_file *fd){ while (size > 0) { SFChunk chunk; /* read a sub chunk */ if(READCHUNK(&chunk, fd) <= 0) return -1; size -= 8; ctl->cmsg(CMSG_INFO, VERB_DEBUG, " %c%c%c%c:", chunk.id[0], chunk.id[1], chunk.id[2], chunk.id[3]); switch (chunkid(chunk.id)) { case SNAM_ID: /* sample name list */ load_sample_names(chunk.size, sf, fd); break; case SMPL_ID: /* sample data starts from here */ sf->samplepos = tf_tell(fd); sf->samplesize = chunk.size; FSKIP(chunk.size, fd); break; default: FSKIP(chunk.size, fd); break; } size -= chunk.size; } return 0;}/*================================================================ * process preset data list *================================================================*/static int process_pdta(int size, SFInfo *sf, struct timidity_file *fd){ while (size > 0) { SFChunk chunk; /* read a subchunk */ if(READCHUNK(&chunk, fd) <= 0) return -1; size -= 8; ctl->cmsg(CMSG_INFO, VERB_DEBUG, " %c%c%c%c:", chunk.id[0], chunk.id[1], chunk.id[2], chunk.id[3]); switch (chunkid(chunk.id)) { case PHDR_ID: load_preset_header(chunk.size, sf, fd); break; case PBAG_ID: load_bag(chunk.size, &prbags, fd); break; case PGEN_ID: load_gen(chunk.size, &prbags, fd); break; case INST_ID: load_inst_header(chunk.size, sf, fd); break; case IBAG_ID: load_bag(chunk.size, &inbags, fd); break; case IGEN_ID: load_gen(chunk.size, &inbags, fd); break; case SHDR_ID: load_sample_info(chunk.size, sf, fd); break; case PMOD_ID: /* ignored */ case IMOD_ID: /* ingored */ default: FSKIP(chunk.size, fd); break; } size -= chunk.size; } return 0;}/*---------------------------------------------------------------- * store sample name list; sf1 only *----------------------------------------------------------------*/static void load_sample_names(int size, SFInfo *sf, struct timidity_file *fd){ int i, nsamples; if (sf->version > 1) { ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "%s: *** version 2 has obsolete format??", current_filename); FSKIP(size, fd); return; } /* each sample name has a fixed lentgh (20 bytes) */ nsamples = size / 20; if (sf->sample == NULL) { sf->nsamples = nsamples; sf->sample = NEW(SFSampleInfo, sf->nsamples); } else if (sf->nsamples != nsamples) { ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "%s: *** different # of samples ?? (%d : %d)\n", current_filename, sf->nsamples, nsamples); FSKIP(size, fd); return; } /* read each name from file */ for (i = 0; i < sf->nsamples; i++) { READSTR(sf->sample[i].name, fd); }}/*---------------------------------------------------------------- * preset header list *----------------------------------------------------------------*/static void load_preset_header(int size, SFInfo *sf, struct timidity_file *fd){ int i; sf->npresets = size / 38; sf->preset = NEW(SFPresetHdr, sf->npresets); for (i = 0; i < sf->npresets; i++) { READSTR(sf->preset[i].hdr.name, fd); READW(&sf->preset[i].preset, fd); READW(&sf->preset[i].bank, fd); READW(&sf->preset[i].hdr.bagNdx, fd); SKIPDW(fd); /* lib; ignored*/ SKIPDW(fd); /* genre; ignored */ SKIPDW(fd); /* morph; ignored */ /* initialize layer table; it'll be parsed later */ sf->preset[i].hdr.nlayers = 0; sf->preset[i].hdr.layer = NULL; ctl->cmsg(CMSG_INFO, VERB_DEBUG, " Preset %d (%s) index=%d bank=%d preset=%d", i, sf->preset[i].hdr.name, sf->preset[i].hdr.bagNdx, sf->preset[i].bank, sf->preset[i].preset + progbase); }}/*---------------------------------------------------------------- * instrument header list *----------------------------------------------------------------*/static void load_inst_header(int size, SFInfo *sf, struct timidity_file *fd){ int i; sf->ninsts = size / 22; sf->inst = NEW(SFInstHdr, sf->ninsts); for (i = 0; i < sf->ninsts; i++) { READSTR(sf->inst[i].hdr.name, fd); READW(&sf->inst[i].hdr.bagNdx, fd); /* iniitialize layer table; it'll be parsed later */ sf->inst[i].hdr.nlayers = 0; sf->inst[i].hdr.layer = NULL; ctl->cmsg(CMSG_INFO, VERB_DEBUG, " InstHdr %d (%s) bagNdx=%d", i, sf->inst[i].hdr.name, sf->inst[i].hdr.bagNdx); }}/*---------------------------------------------------------------- * load preset/instrument bag list on the private table *----------------------------------------------------------------*/static void load_bag(int size, SFBags *bagp, struct timidity_file *fd){ int i; size /= 4; bagp->bag = NEW(uint16, size); for (i = 0; i < size; i++) { READW(&bagp->bag[i], fd); SKIPW(fd); /* mod; ignored */ } bagp->nbags = size;}/*---------------------------------------------------------------- * load preset/instrument generator list on the private table *----------------------------------------------------------------*/static void load_gen(int size, SFBags *bagp, struct timidity_file *fd){ int i; size /= 4; bagp->gen = NEW(SFGenRec, size); for (i = 0; i < size; i++) { READW((uint16 *)&bagp->gen[i].oper, fd); READW((uint16 *)&bagp->gen[i].amount, fd); } bagp->ngens = size;}/*---------------------------------------------------------------- * load sample info list *----------------------------------------------------------------*/static void load_sample_info(int size, SFInfo *sf, struct timidity_file *fd){ int i; int in_rom; /* the record size depends on the soundfont version */ if (sf->version > 1) { /* SF2 includes sample name and other infos */ sf->nsamples = size / 46; sf->sample = NEW(SFSampleInfo, sf->nsamples); } else { /* SBK; sample name may be read already */ int nsamples = size / 16; if (sf->sample == NULL) { sf->nsamples = nsamples; sf->sample = NEW(SFSampleInfo, sf->nsamples); } else if (sf->nsamples != nsamples) {#if 0 fprintf(stderr, "*** different # of infos ?? (%d : %d)\n", sf->nsamples, nsamples); FSKIP(size, fd); return;#endif /* overwrite it */ sf->nsamples = nsamples; } } in_rom = 1; /* data may start from ROM samples */ for (i = 0; i < sf->nsamples; i++) { if (sf->version > 1) /* SF2 only */ READSTR(sf->sample[i].name, fd); READDW((uint32 *)&sf->sample[i].startsample, fd); READDW((uint32 *)&sf->sample[i].endsample, fd); READDW((uint32 *)&sf->sample[i].startloop, fd); READDW((uint32 *)&sf->sample[i].endloop, fd); if (sf->version > 1) { /* SF2 only */ READDW((uint32 *)&sf->sample[i].samplerate, fd); READB(sf->sample[i].originalPitch, fd); READB(sf->sample[i].pitchCorrection, fd); READW(&sf->sample[i].samplelink, fd); READW(&sf->sample[i].sampletype, fd); } else { /* for SBK; set missing infos */ sf->sample[i].samplerate = 44100; sf->sample[i].originalPitch = 60; sf->sample[i].pitchCorrection = 0; sf->sample[i].samplelink = 0; /* the first RAM data starts from address 0 */ if (sf->sample[i].startsample == 0) in_rom = 0; if (in_rom) sf->sample[i].sampletype = 0x8001; else sf->sample[i].sampletype = 1; } }}/*================================================================ * convert from bags to layers *================================================================*/static void convert_layers(SFInfo *sf){ int i; if (prbags.bag == NULL || prbags.gen == NULL || inbags.bag == NULL || inbags.gen == NULL) { ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "%s: *** illegal bags / gens", current_filename); return; } for (i = 0; i < sf->npresets - 1; i++) { generate_layers(&sf->preset[i].hdr, &sf->preset[i+1].hdr, &prbags); } for (i = 0; i < sf->ninsts - 1; i++) { generate_layers(&sf->inst[i].hdr, &sf->inst[i+1].hdr, &inbags); }}/*---------------------------------------------------------------- * generate layer lists from stored bags *----------------------------------------------------------------*/static void generate_layers(SFHeader *hdr, SFHeader *next, SFBags *bags){ int i; SFGenLayer *layp; hdr->nlayers = next->bagNdx - hdr->bagNdx; if (hdr->nlayers < 0) { ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "%s: illegal layer numbers %d", current_filename, hdr->nlayers); return; } if (hdr->nlayers == 0) return; hdr->layer = (SFGenLayer*)safe_malloc(sizeof(SFGenLayer) * hdr->nlayers); layp = hdr->layer; for (layp = hdr->layer, i = hdr->bagNdx; i < next->bagNdx; layp++, i++) { int genNdx = bags->bag[i]; layp->nlists = bags->bag[i+1] - genNdx; if (layp->nlists < 0) { ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "%s: illegal list numbers %d", current_filename, layp->nlists); return; } layp->list = (SFGenRec*)safe_malloc(sizeof(SFGenRec) * layp->nlists); memcpy(layp->list, &bags->gen[genNdx], sizeof(SFGenRec) * layp->nlists); }}/*---------------------------------------------------------------- * free a layer *----------------------------------------------------------------*/static void free_layer(SFHeader *hdr){ int i; for (i = 0; i < hdr->nlayers; i++) { SFGenLayer *layp = &hdr->layer[i]; if (layp->nlists > 0) free(layp->list); } if (hdr->nlayers > 0) free(hdr->layer);}/* add blank loop for each data */int auto_add_blank = 0;void correct_samples(SFInfo *sf){ int i; SFSampleInfo *sp; int prev_end; prev_end = 0; for (sp = sf->sample, i = 0; i < sf->nsamples; i++, sp++) { /* correct sample positions for SBK file */ if (sf->version == 1) { sp->startloop++; sp->endloop += 2; } /* calculate sample data size */ if (sp->sampletype & 0x8000) sp->size = 0; else if (sp->startsample < prev_end && sp->startsample != 0) sp->size = 0; else { sp->size = -1; if (!auto_add_blank && i != sf->nsamples-1) sp->size = sp[1].startsample - sp->startsample; if (sp->size < 0) sp->size = sp->endsample - sp->startsample + 48; } prev_end = sp->endsample; /* calculate short-shot loop size */ if (auto_add_blank || i == sf->nsamples-1) sp->loopshot = 48; else { sp->loopshot = sp[1].startsample - sp->endsample; if (sp->loopshot < 0 || sp->loopshot > 48) sp->loopshot = 48; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -