1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20 
21 /*================================================================
22  * sffile.c
23  *	read SoundFont file (SBK/SF2) and store the layer lists
24  *
25  * Copyright (C) 1996,1997 Takashi Iwai
26  *
27  * This program is free software; you can redistribute it and/or modify
28  * it under the terms of the GNU General Public License as published by
29  * the Free Software Foundation; either version 2 of the License, or
30  * (at your option) any later version.
31  *
32  * This program is distributed in the hope that it will be useful,
33  * but WITHOUT ANY WARRANTY; without even the implied warranty of
34  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35  * GNU General Public License for more details.
36  *
37  * You should have received a copy of the GNU General Public License
38  * along with this program; if not, write to the Free Software
39  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
40  *================================================================*/
41 
42 /*
43  * Modified by Masanao Izumo <mo@goice.co.jp>
44  */
45 
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include "timidity.h"
50 #include "common.h"
51 #include "instrum.h"
52 
53 namespace TimidityPlus
54 {
55 
56 /*================================================================
57 	* preset / instrument bag record
58 	*================================================================*/
59 
60 
61 	/*----------------------------------------------------------------
62 	* function prototypes
63 	*----------------------------------------------------------------*/
64 
65 #define NEW(type,nums)	(type*)safe_malloc(sizeof(type) * (nums))
66 
READCHUNK(SFChunk * vp,timidity_file * tf)67 static int READCHUNK(SFChunk *vp, timidity_file *tf)
68 {
69 	if (tf_read(vp, 8, tf) != 8)
70 		return -1;
71 	vp->size = LE_LONG(vp->size);
72 	return 1;
73 }
74 
READDW(uint32_t * vp,timidity_file * tf)75 static int READDW(uint32_t *vp, timidity_file *tf)
76 {
77 	if (tf_read(vp, 4, tf) != 4)
78 		return -1;
79 	*vp = LE_LONG(*vp);
80 	return 1;
81 }
82 
READW(uint16_t * vp,timidity_file * tf)83 static int READW(uint16_t *vp, timidity_file *tf)
84 {
85 	if (tf_read(vp, 2, tf) != 2)
86 		return -1;
87 	*vp = LE_SHORT(*vp);
88 	return 1;
89 }
90 
READSTR(char * str,timidity_file * tf)91 static int READSTR(char *str, timidity_file *tf)
92 {
93 	int n;
94 
95 	if (tf_read(str, 20, tf) != 20)
96 		return -1;
97 	str[19] = '\0';
98 	n = (int)strlen(str);
99 	while (n > 0 && str[n - 1] == ' ')
100 		n--;
101 	str[n] = '\0';
102 	return n;
103 }
104 
105 #define READID(var,tf)	tf_read(var, 4, tf)
106 #define READB(var,tf)	tf_read(&var, 1, tf)
107 #define SKIPB(tf)	skip(tf, 1)
108 #define SKIPW(tf)	skip(tf, 2)
109 #define SKIPDW(tf)	skip(tf, 4)
110 
111 #define FSKIP(size,tf)	skip(tf, size)
112 
113 
114 /*----------------------------------------------------------------*/
115 
116 /*----------------------------------------------------------------
117 	* id numbers
118 	*----------------------------------------------------------------*/
119 
120 enum {
121 	/* level 0; chunk */
122 	UNKN_ID, RIFF_ID, LIST_ID, SFBK_ID,
123 	/* level 1; id only */
124 	INFO_ID, SDTA_ID, PDTA_ID,
125 	/* info stuff; chunk */
126 	IFIL_ID, ISNG_ID, IROM_ID, INAM_ID, IVER_ID, IPRD_ID, ICOP_ID,
127 	ICRD_ID, IENG_ID, ISFT_ID, ICMT_ID,
128 	/* sample data stuff; chunk */
129 	SNAM_ID, SMPL_ID,
130 	/* preset stuff; chunk */
131 	PHDR_ID, PBAG_ID, PMOD_ID, PGEN_ID,
132 	/* inst stuff; chunk */
133 	INST_ID, IBAG_ID, IMOD_ID, IGEN_ID,
134 	/* sample header; chunk */
135 	SHDR_ID
136 };
137 
138 
139 /*================================================================
140 	* load a soundfont file
141 	*================================================================*/
142 
load_soundfont(SFInfo * sf,timidity_file * fd)143 int Instruments::load_soundfont(SFInfo *sf, timidity_file *fd)
144 {
145 	SFChunk chunk;
146 
147 	sf->preset = NULL;
148 	sf->sample = NULL;
149 	sf->inst = NULL;
150 	sf->sf_name = NULL;
151 
152 	prbags.bag = inbags.bag = NULL;
153 	prbags.gen = inbags.gen = NULL;
154 	prbags.nbags = inbags.nbags =
155 		prbags.ngens = inbags.ngens = 0;
156 
157 	/* check RIFF file header */
158 	READCHUNK(&chunk, fd);
159 	if (chunkid(chunk.id) != RIFF_ID) {
160 		printMessage(CMSG_ERROR, VERB_NORMAL,
161 			"%s: *** not a RIFF file", fd->filename.c_str());
162 		return -1;
163 	}
164 	/* check file id */
165 	READID(chunk.id, fd);
166 	if (chunkid(chunk.id) != SFBK_ID) {
167 		printMessage(CMSG_ERROR, VERB_NORMAL,
168 			"%s: *** not a SoundFont file", fd->filename.c_str());
169 		return -1;
170 	}
171 
172 	for (;;) {
173 		if (READCHUNK(&chunk, fd) <= 0)
174 			break;
175 		else if (chunkid(chunk.id) == LIST_ID) {
176 			if (process_list(chunk.size, sf, fd))
177 				break;
178 		}
179 		else {
180 			printMessage(CMSG_WARNING, VERB_NORMAL,	"%s: *** illegal id in level 0: %4.4s %4d",	fd->filename.c_str(), chunk.id, chunk.size);
181 			FSKIP(chunk.size, fd);
182 			// Not aborting here will inevitably crash.
183 			return -1;
184 		}
185 	}
186 
187 	/* parse layer structure */
188 	convert_layers(sf);
189 
190 	/* free private tables */
191 	if (prbags.bag) free(prbags.bag);
192 	if (prbags.gen) free(prbags.gen);
193 	if (inbags.bag) free(inbags.bag);
194 	if (inbags.gen) free(inbags.gen);
195 
196 	return 0;
197 }
198 
199 
200 /*================================================================
201 	* free buffer
202 	*================================================================*/
203 
free_soundfont(SFInfo * sf)204 void Instruments::free_soundfont(SFInfo *sf)
205 {
206 	int i;
207 	if (sf->preset) {
208 		for (i = 0; i < sf->npresets; i++)
209 			free_layer(&sf->preset[i].hdr);
210 		free(sf->preset);
211 	}
212 	if (sf->inst) {
213 		for (i = 0; i < sf->ninsts; i++)
214 			free_layer(&sf->inst[i].hdr);
215 		free(sf->inst);
216 	}
217 	if (sf->sample) free(sf->sample);
218 	if (sf->sf_name) free(sf->sf_name);
219 }
220 
221 
222 /*----------------------------------------------------------------
223 	* get id value from 4bytes ID string
224 	*----------------------------------------------------------------*/
225 
chunkid(char * id)226 int Instruments::chunkid(char *id)
227 {
228 	static struct idstring {
229 		const char *str;
230 		int id;
231 	} idlist[] = {
232 		{"RIFF", RIFF_ID},
233 		{"LIST", LIST_ID},
234 		{"sfbk", SFBK_ID},
235 		{"INFO", INFO_ID},
236 		{"sdta", SDTA_ID},
237 		{"snam", SNAM_ID},
238 		{"smpl", SMPL_ID},
239 		{"pdta", PDTA_ID},
240 		{"phdr", PHDR_ID},
241 		{"pbag", PBAG_ID},
242 		{"pmod", PMOD_ID},
243 		{"pgen", PGEN_ID},
244 		{"inst", INST_ID},
245 		{"ibag", IBAG_ID},
246 		{"imod", IMOD_ID},
247 		{"igen", IGEN_ID},
248 		{"shdr", SHDR_ID},
249 		{"ifil", IFIL_ID},
250 		{"isng", ISNG_ID},
251 		{"irom", IROM_ID},
252 		{"iver", IVER_ID},
253 		{"INAM", INAM_ID},
254 		{"IPRD", IPRD_ID},
255 		{"ICOP", ICOP_ID},
256 		{"ICRD", ICRD_ID},
257 		{"IENG", IENG_ID},
258 		{"ISFT", ISFT_ID},
259 		{"ICMT", ICMT_ID},
260 	};
261 
262 	for (unsigned i = 0; i < sizeof(idlist) / sizeof(idlist[0]); i++) {
263 		if (strncmp(id, idlist[i].str, 4) == 0)
264 			return idlist[i].id;
265 	}
266 
267 	return UNKN_ID;
268 }
269 
270 
271 /*================================================================
272 	* process a list chunk
273 	*================================================================*/
274 
process_list(int size,SFInfo * sf,timidity_file * fd)275 int Instruments::process_list(int size, SFInfo *sf, timidity_file *fd)
276 {
277 	SFChunk chunk;
278 
279 	/* read the following id string */
280 	READID(chunk.id, fd); size -= 4;
281 	printMessage(CMSG_INFO, VERB_DEBUG, "%c%c%c%c:",
282 		chunk.id[0], chunk.id[1], chunk.id[2], chunk.id[3]);
283 	switch (chunkid(chunk.id)) {
284 	case INFO_ID:
285 		return process_info(size, sf, fd);
286 	case SDTA_ID:
287 		return process_sdta(size, sf, fd);
288 	case PDTA_ID:
289 		return process_pdta(size, sf, fd);
290 	default:
291 		printMessage(CMSG_WARNING, VERB_NORMAL,	"%s: *** illegal id in level 1: %4.4s",	fd->filename.c_str(), chunk.id);
292 		FSKIP(size, fd); /* skip it */
293 		return 0;
294 	}
295 }
296 
297 
298 /*================================================================
299 	* process info list
300 	*================================================================*/
301 
process_info(int size,SFInfo * sf,timidity_file * fd)302 int Instruments::process_info(int size, SFInfo *sf, timidity_file *fd)
303 {
304 	sf->infopos = tf_tell(fd);
305 	sf->infosize = size;
306 
307 	/* parse the buffer */
308 	while (size > 0) {
309 		SFChunk chunk;
310 
311 		/* read a sub chunk */
312 		if (READCHUNK(&chunk, fd) <= 0)
313 			return -1;
314 		size -= 8;
315 
316 		printMessage(CMSG_INFO, VERB_DEBUG, " %c%c%c%c:",
317 			chunk.id[0], chunk.id[1], chunk.id[2], chunk.id[3]);
318 		switch (chunkid(chunk.id)) {
319 		case IFIL_ID:
320 			/* soundfont file version */
321 			READW(&sf->version, fd);
322 			READW(&sf->minorversion, fd);
323 			printMessage(CMSG_INFO, VERB_DEBUG,
324 				"  version %d, minor %d",
325 				sf->version, sf->minorversion);
326 			break;
327 		case INAM_ID:
328 			/* name of the font */
329 			sf->sf_name = (char*)safe_malloc(chunk.size + 1);
330 			tf_read(sf->sf_name, chunk.size, fd);
331 			sf->sf_name[chunk.size] = 0;
332 			printMessage(CMSG_INFO, VERB_DEBUG,
333 				"  name %s", sf->sf_name);
334 			break;
335 
336 		default:
337 			FSKIP(chunk.size, fd);
338 			break;
339 		}
340 		size -= chunk.size;
341 	}
342 	return 0;
343 }
344 
345 
346 /*================================================================
347 	* process sample data list
348 	*================================================================*/
349 
process_sdta(int size,SFInfo * sf,timidity_file * fd)350 int Instruments::process_sdta(int size, SFInfo *sf, timidity_file *fd)
351 {
352 	while (size > 0) {
353 		SFChunk chunk;
354 
355 		/* read a sub chunk */
356 		if (READCHUNK(&chunk, fd) <= 0)
357 			return -1;
358 		size -= 8;
359 
360 		printMessage(CMSG_INFO, VERB_DEBUG, " %c%c%c%c:",
361 			chunk.id[0], chunk.id[1], chunk.id[2], chunk.id[3]);
362 		switch (chunkid(chunk.id)) {
363 		case SNAM_ID:
364 			/* sample name list */
365 			load_sample_names(chunk.size, sf, fd);
366 			break;
367 		case SMPL_ID:
368 			/* sample data starts from here */
369 			sf->samplepos = tf_tell(fd);
370 			sf->samplesize = chunk.size;
371 			FSKIP(chunk.size, fd);
372 			break;
373 		default:
374 			FSKIP(chunk.size, fd);
375 			break;
376 		}
377 		size -= chunk.size;
378 	}
379 	return 0;
380 }
381 
382 
383 /*================================================================
384 	* process preset data list
385 	*================================================================*/
386 
process_pdta(int size,SFInfo * sf,timidity_file * fd)387 int Instruments::process_pdta(int size, SFInfo *sf, timidity_file *fd)
388 {
389 	while (size > 0) {
390 		SFChunk chunk;
391 
392 		/* read a subchunk */
393 		if (READCHUNK(&chunk, fd) <= 0)
394 			return -1;
395 		size -= 8;
396 
397 		printMessage(CMSG_INFO, VERB_DEBUG, " %c%c%c%c:",
398 			chunk.id[0], chunk.id[1], chunk.id[2], chunk.id[3]);
399 		switch (chunkid(chunk.id)) {
400 		case PHDR_ID:
401 			load_preset_header(chunk.size, sf, fd);
402 			break;
403 		case PBAG_ID:
404 			load_bag(chunk.size, &prbags, fd);
405 			break;
406 		case PGEN_ID:
407 			load_gen(chunk.size, &prbags, fd);
408 			break;
409 		case INST_ID:
410 			load_inst_header(chunk.size, sf, fd);
411 			break;
412 		case IBAG_ID:
413 			load_bag(chunk.size, &inbags, fd);
414 			break;
415 		case IGEN_ID:
416 			load_gen(chunk.size, &inbags, fd);
417 			break;
418 		case SHDR_ID:
419 			load_sample_info(chunk.size, sf, fd);
420 			break;
421 		case PMOD_ID: /* ignored */
422 		case IMOD_ID: /* ingored */
423 		default:
424 			FSKIP(chunk.size, fd);
425 			break;
426 		}
427 		size -= chunk.size;
428 	}
429 	return 0;
430 }
431 
432 
433 /*----------------------------------------------------------------
434 	* store sample name list; sf1 only
435 	*----------------------------------------------------------------*/
436 
load_sample_names(int size,SFInfo * sf,timidity_file * fd)437 void Instruments::load_sample_names(int size, SFInfo *sf, timidity_file *fd)
438 {
439 	int i, nsamples;
440 	if (sf->version > 1) {
441 		printMessage(CMSG_WARNING, VERB_NORMAL,	"%s: *** version 2 has obsolete format??",fd->filename.c_str());
442 		FSKIP(size, fd);
443 		return;
444 	}
445 
446 	/* each sample name has a fixed lentgh (20 bytes) */
447 	nsamples = size / 20;
448 	if (sf->sample == NULL) {
449 		sf->nsamples = nsamples;
450 		sf->sample = NEW(SFSampleInfo, sf->nsamples);
451 	}
452 	else if (sf->nsamples != nsamples) {
453 		printMessage(CMSG_WARNING, VERB_NORMAL,	"%s: *** different # of samples ?? (%d : %d)\n",fd->filename.c_str(), sf->nsamples, nsamples);
454 		FSKIP(size, fd);
455 		return;
456 	}
457 
458 	/* read each name from file */
459 	for (i = 0; i < sf->nsamples; i++) {
460 		READSTR(sf->sample[i].name, fd);
461 	}
462 }
463 
464 
465 /*----------------------------------------------------------------
466 	* preset header list
467 	*----------------------------------------------------------------*/
468 
load_preset_header(int size,SFInfo * sf,timidity_file * fd)469 void Instruments::load_preset_header(int size, SFInfo *sf, timidity_file *fd)
470 {
471 	int i;
472 
473 	sf->npresets = size / 38;
474 	sf->preset = NEW(SFPresetHdr, sf->npresets);
475 	for (i = 0; i < sf->npresets; i++) {
476 		READSTR(sf->preset[i].hdr.name, fd);
477 		READW(&sf->preset[i].preset, fd);
478 		READW(&sf->preset[i].bank, fd);
479 		READW(&sf->preset[i].hdr.bagNdx, fd);
480 		SKIPDW(fd); /* lib; ignored*/
481 		SKIPDW(fd); /* genre; ignored */
482 		SKIPDW(fd); /* morph; ignored */
483 		/* initialize layer table; it'll be parsed later */
484 		sf->preset[i].hdr.nlayers = 0;
485 		sf->preset[i].hdr.layer = NULL;
486 	}
487 }
488 
489 
490 /*----------------------------------------------------------------
491 	* instrument header list
492 	*----------------------------------------------------------------*/
493 
load_inst_header(int size,SFInfo * sf,timidity_file * fd)494 void Instruments::load_inst_header(int size, SFInfo *sf, timidity_file *fd)
495 {
496 	int i;
497 
498 	sf->ninsts = size / 22;
499 	sf->inst = NEW(SFInstHdr, sf->ninsts);
500 	for (i = 0; i < sf->ninsts; i++) {
501 		READSTR(sf->inst[i].hdr.name, fd);
502 		READW(&sf->inst[i].hdr.bagNdx, fd);
503 		/* iniitialize layer table; it'll be parsed later */
504 		sf->inst[i].hdr.nlayers = 0;
505 		sf->inst[i].hdr.layer = NULL;
506 
507 		printMessage(CMSG_INFO, VERB_DEBUG,
508 			"  InstHdr %d (%s) bagNdx=%d",
509 			i, sf->inst[i].hdr.name, sf->inst[i].hdr.bagNdx);
510 	}
511 }
512 
513 
514 /*----------------------------------------------------------------
515 	* load preset/instrument bag list on the private table
516 	*----------------------------------------------------------------*/
517 
load_bag(int size,SFBags * bagp,timidity_file * fd)518 void Instruments::load_bag(int size, SFBags *bagp, timidity_file *fd)
519 {
520 	int i;
521 
522 	size /= 4;
523 	bagp->bag = NEW(uint16_t, size);
524 	for (i = 0; i < size; i++) {
525 		READW(&bagp->bag[i], fd);
526 		SKIPW(fd); /* mod; ignored */
527 	}
528 	bagp->nbags = size;
529 }
530 
531 
532 /*----------------------------------------------------------------
533 	* load preset/instrument generator list on the private table
534 	*----------------------------------------------------------------*/
535 
load_gen(int size,SFBags * bagp,timidity_file * fd)536 void Instruments::load_gen(int size, SFBags *bagp, timidity_file *fd)
537 {
538 	int i;
539 
540 	size /= 4;
541 	bagp->gen = NEW(SFGenRec, size);
542 	for (i = 0; i < size; i++) {
543 		READW((uint16_t *)&bagp->gen[i].oper, fd);
544 		READW((uint16_t *)&bagp->gen[i].amount, fd);
545 	}
546 	bagp->ngens = size;
547 }
548 
549 
550 /*----------------------------------------------------------------
551 	* load sample info list
552 	*----------------------------------------------------------------*/
553 
load_sample_info(int size,SFInfo * sf,timidity_file * fd)554 void Instruments::load_sample_info(int size, SFInfo *sf, timidity_file *fd)
555 {
556 	int i;
557 	int in_rom;
558 
559 	/* the record size depends on the soundfont version */
560 	if (sf->version > 1) {
561 		/* SF2 includes sample name and other infos */
562 		sf->nsamples = size / 46;
563 		sf->sample = NEW(SFSampleInfo, sf->nsamples);
564 	}
565 	else {
566 		/* SBK; sample name may be read already */
567 		int nsamples = size / 16;
568 		if (sf->sample == NULL) {
569 			sf->nsamples = nsamples;
570 			sf->sample = NEW(SFSampleInfo, sf->nsamples);
571 		}
572 		else if (sf->nsamples != nsamples) {
573 			/* overwrite it */
574 			sf->nsamples = nsamples;
575 		}
576 	}
577 
578 	in_rom = 1;  /* data may start from ROM samples */
579 	for (i = 0; i < sf->nsamples; i++) {
580 		if (sf->version > 1) /* SF2 only */
581 			READSTR(sf->sample[i].name, fd);
582 		READDW((uint32_t *)&sf->sample[i].startsample, fd);
583 		READDW((uint32_t *)&sf->sample[i].endsample, fd);
584 		READDW((uint32_t *)&sf->sample[i].startloop, fd);
585 		READDW((uint32_t *)&sf->sample[i].endloop, fd);
586 		if (sf->version > 1) { /* SF2 only */
587 			READDW((uint32_t *)&sf->sample[i].samplerate, fd);
588 			READB(sf->sample[i].originalPitch, fd);
589 			READB(sf->sample[i].pitchCorrection, fd);
590 			READW(&sf->sample[i].samplelink, fd);
591 			READW(&sf->sample[i].sampletype, fd);
592 		}
593 		else { /* for SBK; set missing infos */
594 			sf->sample[i].samplerate = 44100;
595 			sf->sample[i].originalPitch = 60;
596 			sf->sample[i].pitchCorrection = 0;
597 			sf->sample[i].samplelink = 0;
598 			/* the first RAM data starts from address 0 */
599 			if (sf->sample[i].startsample == 0)
600 				in_rom = 0;
601 			if (in_rom)
602 				sf->sample[i].sampletype = 0x8001;
603 			else
604 				sf->sample[i].sampletype = 1;
605 		}
606 	}
607 }
608 
609 
610 /*================================================================
611 	* convert from bags to layers
612 	*================================================================*/
613 
convert_layers(SFInfo * sf)614 void Instruments::convert_layers(SFInfo *sf)
615 {
616 	int i;
617 
618 	if (prbags.bag == NULL || prbags.gen == NULL ||
619 		inbags.bag == NULL || inbags.gen == NULL) {
620 		printMessage(CMSG_WARNING, VERB_NORMAL,	"%s: *** illegal bags / gens", sf->sf_name);
621 		return;
622 	}
623 
624 	for (i = 0; i < sf->npresets - 1; i++) {
625 		generate_layers(&sf->preset[i].hdr,
626 			&sf->preset[i + 1].hdr,
627 			&prbags);
628 	}
629 	for (i = 0; i < sf->ninsts - 1; i++) {
630 		generate_layers(&sf->inst[i].hdr,
631 			&sf->inst[i + 1].hdr,
632 			&inbags);
633 	}
634 }
635 
636 
637 /*----------------------------------------------------------------
638 	* generate layer lists from stored bags
639 	*----------------------------------------------------------------*/
640 
generate_layers(SFHeader * hdr,SFHeader * next,SFBags * bags)641 void Instruments::generate_layers(SFHeader *hdr, SFHeader *next, SFBags *bags)
642 {
643 	int i;
644 	SFGenLayer *layp;
645 
646 	hdr->nlayers = next->bagNdx - hdr->bagNdx;
647 	if (hdr->nlayers < 0) {
648 		printMessage(CMSG_WARNING, VERB_NORMAL,	"%s: illegal layer numbers %d",	"", hdr->nlayers);
649 		return;
650 	}
651 	if (hdr->nlayers == 0)
652 		return;
653 	hdr->layer = (SFGenLayer*)safe_malloc(sizeof(SFGenLayer) * hdr->nlayers);
654 	layp = hdr->layer;
655 	for (layp = hdr->layer, i = hdr->bagNdx; i < next->bagNdx; layp++, i++) {
656 		int genNdx = bags->bag[i];
657 		layp->nlists = bags->bag[i + 1] - genNdx;
658 		if (layp->nlists < 0) {
659 			printMessage(CMSG_WARNING, VERB_NORMAL, "%s: illegal list numbers %d", "", layp->nlists);
660 			return;
661 		}
662 		layp->list = (SFGenRec*)safe_malloc(sizeof(SFGenRec) * layp->nlists);
663 		memcpy(layp->list, &bags->gen[genNdx],
664 			sizeof(SFGenRec) * layp->nlists);
665 	}
666 }
667 
668 /*----------------------------------------------------------------
669 	* free a layer
670 	*----------------------------------------------------------------*/
671 
free_layer(SFHeader * hdr)672 void Instruments::free_layer(SFHeader *hdr)
673 {
674 	int i;
675 	for (i = 0; i < hdr->nlayers; i++) {
676 		SFGenLayer *layp = &hdr->layer[i];
677 		if (layp->nlists >= 0)
678 			free(layp->list);
679 	}
680 	if (hdr->nlayers > 0)
681 		free(hdr->layer);
682 }
683 
684 /* add blank loop for each data */
685 static const int auto_add_blank = 0;
correct_samples(SFInfo * sf)686 void Instruments::correct_samples(SFInfo *sf)
687 {
688 	int i;
689 	SFSampleInfo *sp;
690 	int prev_end;
691 
692 	prev_end = 0;
693 	for (sp = sf->sample, i = 0; i < sf->nsamples; i++, sp++) {
694 		/* correct sample positions for SBK file */
695 		if (sf->version == 1) {
696 			sp->startloop++;
697 			sp->endloop += 2;
698 		}
699 
700 		/* calculate sample data size */
701 		if (sp->sampletype & 0x8000)
702 			sp->size = 0;
703 		else if (sp->startsample < prev_end && sp->startsample != 0)
704 			sp->size = 0;
705 		else {
706 			sp->size = -1;
707 			if (!auto_add_blank && i != sf->nsamples - 1)
708 				sp->size = sp[1].startsample - sp->startsample;
709 			if (sp->size < 0)
710 				sp->size = sp->endsample - sp->startsample + 48;
711 		}
712 		prev_end = sp->endsample;
713 
714 		/* calculate short-shot loop size */
715 		if (auto_add_blank || i == sf->nsamples - 1)
716 			sp->loopshot = 48;
717 		else {
718 			sp->loopshot = sp[1].startsample - sp->endsample;
719 			if (sp->loopshot < 0 || sp->loopshot > 48)
720 				sp->loopshot = 48;
721 		}
722 	}
723 }
724 }
725