~ubuntu-branches/ubuntu/karmic/muse/karmic-proposed

« back to all changes in this revision

Viewing changes to synti/iiwu/sfont.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2002-04-23 17:28:23 UTC
  • Revision ID: james.westby@ubuntu.com-20020423172823-w8yplzr81a759xa3
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//=========================================================
 
2
//  MusE
 
3
//  Linux Music Editor
 
4
//  $Id: sfont.cpp,v 1.1 2002/01/30 12:08:39 muse Exp $
 
5
//
 
6
//  This file is derived from IIWU Synth and modified
 
7
//    for MusE.
 
8
//  Parts of IIWU are derived from Smurf Sound Font Editor.
 
9
//  Parts of Smurf Sound Font Editor are derived from
 
10
//    awesfx utilities
 
11
//  Smurf:  Copyright (C) 1999-2000 Josh Green
 
12
//  IIWU:   Copyright (C) 2001 Peter Hanappe
 
13
//  MusE:   Copyright (C) 2001 Werner Schweer
 
14
//  awesfx: Copyright (C) 1996-1999 Takashi Iwai
 
15
//=========================================================
 
16
 
 
17
#include "sfont.h"
 
18
#include <stdarg.h>
 
19
#include <sys/stat.h>
 
20
#include <string.h>
 
21
#include <errno.h>
 
22
 
 
23
enum {
 
24
      UNKN_ID, RIFF_ID, LIST_ID, SFBK_ID,
 
25
      INFO_ID, SDTA_ID, PDTA_ID,        /* info/sample/preset */
 
26
 
 
27
      IFIL_ID, ISNG_ID, INAM_ID, IROM_ID, /* info ids (1st byte of info strings) */
 
28
      IVER_ID, ICRD_ID, IENG_ID, IPRD_ID,       /* more info ids */
 
29
      ICOP_ID, ICMT_ID, ISFT_ID,        /* and yet more info ids */
 
30
 
 
31
      SNAM_ID, SMPL_ID,         /* sample ids */
 
32
      PHDR_ID, PBAG_ID, PMOD_ID, PGEN_ID,       /* preset ids */
 
33
      IHDR_ID, IBAG_ID, IMOD_ID, IGEN_ID,       /* instrument ids */
 
34
      SHDR_ID                   /* sample info */
 
35
      };
 
36
 
 
37
//---------------------------------------------------------
 
38
//   gen_init_array
 
39
//    Set an array of generators to their initial value
 
40
//---------------------------------------------------------
 
41
 
 
42
void gen_init_array(Gen* gen)
 
43
      {
 
44
      int i;
 
45
      for (i = 0; i < GEN_LAST; i++) {
 
46
            gen[i].flags = GEN_UNUSED;
 
47
            gen[i].mod = 0.0;
 
48
            gen[i].val = 0.0;
 
49
            }
 
50
      gen[GEN_FILTERFC].val           = 13500;
 
51
      gen[GEN_MODLFODELAY].val        = -12000;
 
52
      gen[GEN_VIBLFODELAY].val        = -12000;
 
53
      gen[GEN_MODENVDELAY].val        = -12000;
 
54
      gen[GEN_MODENVATTACK].val       = -12000;
 
55
      gen[GEN_MODENVHOLD].val         = -12000;
 
56
      gen[GEN_MODENVDECAY].val        = -12000;
 
57
      gen[GEN_MODENVRELEASE].val      = -12000;
 
58
      gen[GEN_VOLENVDELAY].val        = -12000;
 
59
      gen[GEN_VOLENVATTACK].val       = -12000;
 
60
      gen[GEN_VOLENVHOLD].val         = -12000;
 
61
      gen[GEN_VOLENVDECAY].val        = -12000;
 
62
      gen[GEN_VOLENVRELEASE].val      = -12000;
 
63
      gen[GEN_KEYNUM].val             = -1;
 
64
      gen[GEN_VELOCITY].val           = -1;
 
65
      gen[GEN_SCALETUNE].val          = 100;
 
66
      gen[GEN_OVERRIDEROOTKEY].val    = -1;
 
67
      }
 
68
 
 
69
//---------------------------------------------------------
 
70
//   inside_range
 
71
//---------------------------------------------------------
 
72
 
 
73
int Zone::inside_range(int key, int vel)
 
74
      {
 
75
      return ((keylo <= key) && (keyhi >= key) && (vello <= vel) && (velhi >= vel));
 
76
      }
 
77
 
 
78
//---------------------------------------------------------
 
79
//   Preset
 
80
//---------------------------------------------------------
 
81
 
 
82
Preset::Preset()
 
83
      {
 
84
      next        = 0;
 
85
      name        = 0;
 
86
      hbank       = 0;
 
87
      lbank       = 0;
 
88
      prog        = 0;
 
89
      zone        = 0;
 
90
      _sfont      = 0;
 
91
      }
 
92
 
 
93
//---------------------------------------------------------
 
94
//   Preset
 
95
//---------------------------------------------------------
 
96
 
 
97
Preset::~Preset()
 
98
      {
 
99
      Zone* z = zone;
 
100
      while (z) {
 
101
            Zone* zz = z->next;
 
102
            delete z;
 
103
            z = zz;
 
104
            }
 
105
      }
 
106
 
 
107
//---------------------------------------------------------
 
108
//   Zone
 
109
//---------------------------------------------------------
 
110
 
 
111
Zone::Zone()
 
112
      {
 
113
      next       = 0;
 
114
      instsampno = 0;
 
115
      samp       = 0;
 
116
      sfgen      = 0;
 
117
      mod        = 0;
 
118
      inst       = 0;
 
119
      keylo      = 0;
 
120
      vello      = 0;
 
121
      velhi      = keyhi = 128;
 
122
      gen_init_array(gen);
 
123
      }
 
124
 
 
125
//---------------------------------------------------------
 
126
//   ~Zone
 
127
//---------------------------------------------------------
 
128
 
 
129
Zone::~Zone()
 
130
      {
 
131
      SFMod* m = mod;
 
132
      while (m) {                               // Free mod chunks for this zone
 
133
            SFMod* nm = m->next;
 
134
            delete m;
 
135
            m = nm;
 
136
            }
 
137
      }
 
138
 
 
139
//---------------------------------------------------------
 
140
//   chunkid
 
141
//---------------------------------------------------------
 
142
 
 
143
static int chunkid(unsigned id)
 
144
      {
 
145
      static char idlist[] = {
 
146
            "RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD"
 
147
            "ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdr"
 
148
            };
 
149
      unsigned* p = (unsigned *) & idlist;
 
150
 
 
151
      for (unsigned i = 0; i < sizeof (idlist) / sizeof (int); ++i, ++p)
 
152
            if (*p == id)
 
153
                  return (i + 1);
 
154
      return UNKN_ID;
 
155
      }
 
156
 
 
157
//---------------------------------------------------------
 
158
//   gen_valid
 
159
//    check validity of instrument generator
 
160
//    return true if valid
 
161
//---------------------------------------------------------
 
162
 
 
163
static bool gen_valid(unsigned gen)
 
164
      {
 
165
      static unsigned badgen[] = {
 
166
            Gen_Unused1, Gen_Unused2, Gen_Unused3, Gen_Unused4,
 
167
            Gen_Reserved1, Gen_Reserved2, Gen_Reserved3, 0
 
168
            };
 
169
 
 
170
      if (gen > Gen_MaxValid)
 
171
            return false;
 
172
      unsigned i;
 
173
      for (i = 0; i < sizeof(badgen)/sizeof(*badgen); ++i)
 
174
            if (badgen[i] == gen)
 
175
                  return false;
 
176
      return true;
 
177
      }
 
178
 
 
179
//---------------------------------------------------------
 
180
//   gen_validp
 
181
//    check validity of preset generator
 
182
//---------------------------------------------------------
 
183
 
 
184
static bool gen_validp(unsigned int gen)
 
185
      {                         /* is preset generator valid? */
 
186
      static unsigned badpgen[] = {
 
187
            Gen_StartAddrOfs, Gen_EndAddrOfs, Gen_StartLoopAddrOfs,
 
188
            Gen_EndLoopAddrOfs, Gen_StartAddrCoarseOfs, Gen_EndAddrCoarseOfs,
 
189
            Gen_StartLoopAddrCoarseOfs, Gen_Keynum, Gen_Velocity,
 
190
            Gen_EndLoopAddrCoarseOfs, Gen_SampleModes, Gen_ExclusiveClass,
 
191
            Gen_OverrideRootKey, 0
 
192
            };
 
193
 
 
194
      if (!gen_valid (gen))
 
195
            return false;
 
196
      int i = 0;
 
197
      while (badpgen[i] && badpgen[i] != (unsigned) gen)
 
198
            i++;
 
199
      return (badpgen[i] == 0);
 
200
      }
 
201
 
 
202
//---------------------------------------------------------
 
203
//   gerr
 
204
//    Logging function
 
205
//---------------------------------------------------------
 
206
 
 
207
static void gerr(char * fmt, ...)
 
208
      {
 
209
      va_list args;
 
210
 
 
211
      va_start (args, fmt);
 
212
      vprintf(fmt, args);
 
213
      va_end (args);
 
214
 
 
215
      printf("\n");
 
216
      }
 
217
 
 
218
//---------------------------------------------------------
 
219
//   sfont_zone_delete
 
220
//    delete zone from zone list
 
221
//---------------------------------------------------------
 
222
 
 
223
static void sfont_zone_delete(Zone** zlist, Zone* zone)
 
224
      {
 
225
      if (zone == 0)
 
226
            return;
 
227
      Zone* prev = 0;
 
228
      for (Zone* tmp  = *zlist; tmp; tmp = tmp->next) {
 
229
            if (tmp == zone) {
 
230
                  if (prev)
 
231
                        prev->next = tmp->next;
 
232
                  if (*zlist == tmp)
 
233
                        *zlist = (*zlist)->next;
 
234
                  tmp->next = 0;
 
235
                  break;
 
236
                  }
 
237
            prev = tmp;
 
238
            }
 
239
      delete zone;
 
240
      }
 
241
 
 
242
static void SLADVREMZ(Zone*& list, Zone*& item)
 
243
      {
 
244
      Zone* _temp = item;
 
245
      if (item) {
 
246
            item = item->next;
 
247
            sfont_zone_delete(&list, _temp);
 
248
            }
 
249
      }
 
250
 
 
251
//---------------------------------------------------------
 
252
//   safe_fread
 
253
//---------------------------------------------------------
 
254
 
 
255
void SFont::safe_fread(void *buf, int count)
 
256
      {
 
257
      if (fread (buf, count, 1, fd) != 1) { // size_t = count, nmemb = 1
 
258
            if (feof (fd))
 
259
                  longjmp(env, 51);
 
260
            else
 
261
                  longjmp(env, 52);
 
262
            }
 
263
      }
 
264
 
 
265
//---------------------------------------------------------
 
266
//   readid
 
267
//---------------------------------------------------------
 
268
 
 
269
void SFont::readid(unsigned* var)
 
270
      {
 
271
      safe_fread(var, 4);
 
272
      }
 
273
 
 
274
//---------------------------------------------------------
 
275
//   readstr
 
276
//---------------------------------------------------------
 
277
 
 
278
void SFont::readstr(char* var)
 
279
      {
 
280
      safe_fread(var, 20);
 
281
      var[20] = '\0';
 
282
      }
 
283
 
 
284
//---------------------------------------------------------
 
285
//   read_listchunk
 
286
//---------------------------------------------------------
 
287
 
 
288
void SFont::read_listchunk(SFChunk* chunk)
 
289
      {
 
290
      safe_fread(chunk, 8);
 
291
      if (chunkid (chunk->id) != LIST_ID)       /* error if ! list chunk */
 
292
            longjmp(env, 7);
 
293
      readid(&chunk->id);       /* read id string */
 
294
      chunk->size -= 4;
 
295
      }
 
296
 
 
297
//---------------------------------------------------------
 
298
//   readw
 
299
//---------------------------------------------------------
 
300
 
 
301
int SFont::readw()
 
302
      {
 
303
      short s;
 
304
      safe_fread(&s, 2);
 
305
      return s;
 
306
      }
 
307
 
 
308
//---------------------------------------------------------
 
309
//   readWord
 
310
//---------------------------------------------------------
 
311
 
 
312
unsigned int SFont::readWord()
 
313
      {
 
314
      unsigned short s;
 
315
      safe_fread(&s, 2);
 
316
      return s;
 
317
      }
 
318
 
 
319
//---------------------------------------------------------
 
320
//   readd
 
321
//---------------------------------------------------------
 
322
 
 
323
int SFont::readd()
 
324
      {
 
325
      unsigned s;
 
326
      safe_fread(&s, 4);
 
327
      return s;
 
328
      }
 
329
 
 
330
//---------------------------------------------------------
 
331
//   readb
 
332
//---------------------------------------------------------
 
333
 
 
334
int SFont::readb()
 
335
      {
 
336
      char var;
 
337
      safe_fread(&var, 1);
 
338
      return var;
 
339
      }
 
340
 
 
341
//---------------------------------------------------------
 
342
//   readByte
 
343
//    read unsigned char
 
344
//---------------------------------------------------------
 
345
 
 
346
unsigned int SFont::readByte()
 
347
      {
 
348
      unsigned char var;
 
349
      safe_fread(&var, 1);
 
350
      return var;
 
351
      }
 
352
 
 
353
//---------------------------------------------------------
 
354
//   fskip
 
355
//---------------------------------------------------------
 
356
 
 
357
void SFont::fskip(int size)
 
358
      {
 
359
      if (fseek (fd, size, SEEK_CUR) == -1)
 
360
            longjmp(env, 53);
 
361
      }
 
362
 
 
363
//---------------------------------------------------------
 
364
//   SFont
 
365
//---------------------------------------------------------
 
366
 
 
367
SFont::SFont()
 
368
      {
 
369
      file       = 0;
 
370
      next       = 0;
 
371
      samplepos  = 0;
 
372
      samplesize = 0;
 
373
      sample     = 0;
 
374
      sampledata = 0;
 
375
      info       = 0;
 
376
      inst       = 0;
 
377
      preset     = 0;
 
378
      }
 
379
 
 
380
//---------------------------------------------------------
 
381
//   ~SFont
 
382
//---------------------------------------------------------
 
383
 
 
384
SFont::~SFont()
 
385
      {
 
386
      if (file)
 
387
            delete file;
 
388
      while (sample) {
 
389
            Sample* s = sample->next;
 
390
            delete sample;
 
391
            sample = s;
 
392
            }
 
393
      if (sampledata)
 
394
            delete sampledata;
 
395
 
 
396
      for (SFInfo* i = info; i; ) {
 
397
            SFInfo* ni = i->next;
 
398
            delete i;
 
399
            i = ni;
 
400
            }
 
401
 
 
402
      while (preset) {
 
403
            Preset* nz = preset->next;
 
404
            delete preset;
 
405
            preset = nz;
 
406
            }
 
407
 
 
408
      while (inst) {
 
409
            Inst* ni = inst->next;
 
410
            delete inst;
 
411
            inst = ni;
 
412
            }
 
413
      }
 
414
 
 
415
//---------------------------------------------------------
 
416
//   process_info
 
417
//---------------------------------------------------------
 
418
 
 
419
void SFont::process_info(int size)
 
420
      {
 
421
      SFChunk chunk;
 
422
 
 
423
      SFInfo* ni = info;
 
424
      while (size > 0) {
 
425
            safe_fread(&chunk, 8);
 
426
            size -= 8;
 
427
 
 
428
            unsigned char id = chunkid(chunk.id);
 
429
 
 
430
            if (id == IFIL_ID) {          // sound font version chunk?
 
431
                  if (chunk.size != 4)
 
432
                        longjmp(env, 1);
 
433
 
 
434
                  version.major = readw();
 
435
                  version.minor = readw();
 
436
 
 
437
                  if (version.major < 2)
 
438
                        longjmp(env, 2);
 
439
                  if (version.major > 2)
 
440
                        gerr ("Sound font version is %d.%d which is newer than"
 
441
                           " what this version of Smurf was designed for (v2.0x)");
 
442
                  }
 
443
            else if (id == IVER_ID) {     // ROM version chunk?
 
444
                  if (chunk.size != 4)
 
445
                        longjmp(env, 3);
 
446
                  romver.major = readw();
 
447
                  romver.minor = readw();
 
448
                  }
 
449
            else if (id != UNKN_ID) {
 
450
                  if ((id != ICMT_ID && chunk.size > 256) || (chunk.size > 65536)
 
451
                     || (chunk.size % 2))
 
452
                        longjmp(env, 4);
 
453
 
 
454
                  /* alloc for chunk id and da chunk */
 
455
                  SFInfo* item = new SFInfo;
 
456
 
 
457
                  item->data = new char[chunk.size+1];
 
458
 
 
459
                  /* attach to INFO list, sfont_close will cleanup if FAIL occurs */
 
460
                  item->next = 0;
 
461
                  if (ni)
 
462
                        ni->next = item;
 
463
                  else
 
464
                        info = item;
 
465
                  ni = item;
 
466
 
 
467
                  item->data[0] = id;
 
468
                  safe_fread (&item->data[1], chunk.size);
 
469
 
 
470
                  /* force terminate info item (don't forget uchar info ID) */
 
471
                  *(item->data + chunk.size) = '\0';
 
472
                  }
 
473
            else
 
474
                  longjmp(env, 5);
 
475
            size -= chunk.size;
 
476
            }
 
477
 
 
478
      if (size < 0)
 
479
            longjmp(env, 6);
 
480
      }
 
481
 
 
482
//---------------------------------------------------------
 
483
//   load_body
 
484
//---------------------------------------------------------
 
485
 
 
486
void SFont::load_body()
 
487
      {
 
488
      SFChunk chunk;
 
489
 
 
490
      safe_fread(&chunk, 8);
 
491
      if (chunkid (chunk.id) != RIFF_ID) {      /* error if not RIFF */
 
492
            longjmp(env, 8);
 
493
            }
 
494
 
 
495
      readid(&chunk.id);                    // load file ID */
 
496
      if (chunkid (chunk.id) != SFBK_ID)
 
497
            longjmp(env, 9);
 
498
      if (chunk.size != unsigned(fsize - 8))
 
499
            longjmp(env, 10);
 
500
 
 
501
      // Process INFO block
 
502
      read_listchunk(&chunk);
 
503
      if (chunkid (chunk.id) != INFO_ID)
 
504
            longjmp(env, 11);
 
505
      process_info(chunk.size);
 
506
 
 
507
      // Process sample chunk
 
508
      read_listchunk(&chunk);
 
509
      if (chunkid (chunk.id) != SDTA_ID)
 
510
            longjmp(env, 12);
 
511
      process_sdta(chunk.size);
 
512
 
 
513
      // process HYDRA chunk
 
514
      read_listchunk(&chunk);
 
515
      if (chunkid (chunk.id) != PDTA_ID)
 
516
            longjmp(env, 13);
 
517
      process_pdta(chunk.size);
 
518
 
 
519
      fixup_pgen();
 
520
      fixup_igen();
 
521
      fixup_sample();
 
522
 
 
523
      /* sort preset list by bank, preset # */
 
524
//TODO      preset = g_slist_sort(preset, (GCompareFunc) sfont_preset_compare_func);
 
525
      load_sampledata();
 
526
      }
 
527
 
 
528
//---------------------------------------------------------
 
529
//   process_sdta
 
530
//---------------------------------------------------------
 
531
 
 
532
void SFont::process_sdta(int size)
 
533
      {
 
534
      SFChunk chunk;
 
535
 
 
536
      if (size == 0)
 
537
            return;             /* no sample data? */
 
538
 
 
539
      /* read sub chunk */
 
540
      safe_fread(&chunk, 8);
 
541
      size -= 8;
 
542
 
 
543
      if (chunkid (chunk.id) != SMPL_ID)
 
544
            longjmp(env, 14);
 
545
 
 
546
      if ((size - chunk.size) != 0)
 
547
            longjmp(env, 15);
 
548
 
 
549
      /* sample data follows */
 
550
      samplepos = ftell(fd);
 
551
 
 
552
      /* used in fixup_sample() to check validity of sample headers */
 
553
      sdtachunk_size = chunk.size;
 
554
      samplesize     = chunk.size;
 
555
      fskip(chunk.size);
 
556
      }
 
557
 
 
558
//---------------------------------------------------------
 
559
//   pdtahelper
 
560
//---------------------------------------------------------
 
561
 
 
562
void SFont::pdtahelper(unsigned expid, unsigned reclen, SFChunk* chunk, int* size)
 
563
      {
 
564
      unsigned id;
 
565
 
 
566
      safe_fread(chunk, 8);
 
567
      *size -= 8;
 
568
 
 
569
      if ((id = chunkid (chunk->id)) != expid)
 
570
            longjmp(env, 16);
 
571
      if (chunk->size % reclen) /* valid chunk size? */
 
572
            longjmp(env, 17);
 
573
      if ((*size -= chunk->size) < 0)
 
574
            longjmp(env, 18);
 
575
      }
 
576
 
 
577
//---------------------------------------------------------
 
578
//   load_phdr
 
579
//    preset header loader
 
580
//---------------------------------------------------------
 
581
 
 
582
void SFont::load_phdr(int size)
 
583
      {
 
584
      int i2;
 
585
 
 
586
      if (size % SFPHDRSIZE || size == 0)
 
587
            longjmp(env, 19);
 
588
 
 
589
      int i = size / SFPHDRSIZE - 1;
 
590
      if (i == 0) {                             /* at least one preset + term record */
 
591
            gerr("File contains no presets");
 
592
            fskip(SFPHDRSIZE);
 
593
            return;
 
594
            }
 
595
 
 
596
      Preset* pr = preset;            // ptr to previous preset
 
597
      int pzndx  = 0;
 
598
 
 
599
      for (; i > 0; i--) {
 
600
            Preset* p = new Preset();
 
601
            p->setSFont(this);
 
602
            char buffer[21];
 
603
            readstr(buffer);
 
604
            p->name = strdup(buffer);
 
605
            p->prog   = readWord();
 
606
            int lbank = readWord();
 
607
            if (lbank == 128) {  // drum set
 
608
                  p->hbank = 1;
 
609
                  }
 
610
            else {
 
611
                  p->lbank = lbank;
 
612
                  }
 
613
            int zndx    = readWord();
 
614
            p->zoneIndex = zndx;
 
615
            p->libr     = readd();
 
616
            p->genre    = readd();
 
617
            p->morph    = readd();
 
618
 
 
619
            if (pr) {                   /* not first preset? */
 
620
                  pr->next = p;
 
621
                  if (zndx < pzndx)
 
622
                        longjmp(env, 20);
 
623
                  i2 = zndx - pzndx;
 
624
                  while (i2--) {
 
625
                        Zone* z = new Zone;
 
626
                        z->next   = pr->zone;
 
627
                        pr->zone  = z;
 
628
                        }
 
629
                  }
 
630
            else {
 
631
                  preset = p;
 
632
                  if (zndx > 0)     /* 1st preset, warn if ofs >0 */
 
633
                        longjmp(env, 21);
 
634
                  }
 
635
            pr    = p;                  /* update preset ptr */
 
636
            pzndx = zndx;
 
637
            }
 
638
 
 
639
      fskip(24);
 
640
      int zndx  = readWord();        /* Read terminal generator index */
 
641
      fskip(12);
 
642
 
 
643
      if (zndx < pzndx)
 
644
            longjmp(env, 22);
 
645
      i2 = zndx - pzndx;
 
646
      while (i2--) {
 
647
            Zone* z = new Zone;
 
648
            z->next   = pr->zone;
 
649
            pr->zone  = z;
 
650
            }
 
651
      }
 
652
 
 
653
//---------------------------------------------------------
 
654
//   process_pdta
 
655
//---------------------------------------------------------
 
656
 
 
657
void SFont::process_pdta(int size)
 
658
      {
 
659
      SFChunk chunk;
 
660
 
 
661
      pdtahelper(PHDR_ID, SFPHDRSIZE, &chunk, &size);
 
662
      load_phdr(chunk.size);
 
663
 
 
664
      pdtahelper(PBAG_ID, SFBAGSIZE, &chunk, &size);
 
665
      load_pbag(chunk.size);
 
666
 
 
667
      pdtahelper(PMOD_ID, SFMODSIZE, &chunk, &size);
 
668
      load_pmod(chunk.size);
 
669
 
 
670
      pdtahelper(PGEN_ID, SFGENSIZE, &chunk, &size);
 
671
      load_pgen(chunk.size);
 
672
 
 
673
      pdtahelper(IHDR_ID, SFIHDRSIZE, &chunk, &size);
 
674
      load_ihdr(chunk.size);
 
675
 
 
676
      pdtahelper(IBAG_ID, SFBAGSIZE, &chunk, &size);
 
677
      load_ibag(chunk.size);
 
678
 
 
679
      pdtahelper(IMOD_ID, SFMODSIZE, &chunk, &size);
 
680
      load_imod(chunk.size);
 
681
 
 
682
      pdtahelper(IGEN_ID, SFGENSIZE, &chunk, &size);
 
683
      load_igen(chunk.size);
 
684
 
 
685
      pdtahelper(SHDR_ID, SFSHDRSIZE, &chunk, &size);
 
686
      load_shdr(chunk.size);
 
687
      }
 
688
 
 
689
//---------------------------------------------------------
 
690
//   load_pbag
 
691
//    preset bag loader
 
692
//---------------------------------------------------------
 
693
 
 
694
void SFont::load_pbag(int size)
 
695
      {
 
696
      Zone* pz = 0;
 
697
      unsigned genndx, modndx;
 
698
      unsigned pgenndx=0, pmodndx = 0;
 
699
 
 
700
      if ((size % SFBAGSIZE) || size == 0)  // size is multiple of SFBAGSIZE?
 
701
            longjmp(env, 23);
 
702
 
 
703
      for (Preset* p = preset; p; p = p->next) {
 
704
            for (Zone* z = p->zone; z; z = z->next) {
 
705
                  size -= SFBAGSIZE;
 
706
                  if (size < 0)
 
707
                        longjmp(env, 24);
 
708
                  genndx      = readWord();
 
709
                  modndx      = readWord();
 
710
 
 
711
                  if (pz) {                     /* if not first zone */
 
712
                        if (genndx < pgenndx)
 
713
                              longjmp(env, 25);
 
714
                        if (modndx < pmodndx)
 
715
                              longjmp(env, 26);
 
716
// printf("preset <%s> Gen:%d Mod:%d\n", p->name, genndx-pgenndx, modndx-pmodndx);
 
717
                          int i = genndx - pgenndx;
 
718
                        pz->sfgen += i;
 
719
                        i = modndx - pmodndx;
 
720
                        while (i--) {
 
721
                              SFMod* m = new SFMod;
 
722
                              m->next = pz->mod;
 
723
                              pz->mod = m;
 
724
                              }
 
725
                        }
 
726
                  pz      = z;          // update previous zone ptr
 
727
                  pgenndx = genndx;     /* update previous zone gen index */
 
728
                  pmodndx = modndx;     /* update previous zone mod index */
 
729
                  }
 
730
            }
 
731
      size -= SFBAGSIZE;
 
732
      if (size != 0)
 
733
            longjmp(env, 24);
 
734
 
 
735
      genndx = readWord();
 
736
      modndx = readWord();
 
737
 
 
738
      if (!pz) {
 
739
            if (genndx > 0)
 
740
                  longjmp(env, 27);
 
741
            if (modndx > 0)
 
742
                  longjmp(env, 28);
 
743
            return;
 
744
            }
 
745
 
 
746
      if (genndx < pgenndx)
 
747
            longjmp(env, 29);
 
748
      if (modndx < pmodndx)
 
749
            longjmp(env, 30);
 
750
      int i = genndx - pgenndx;
 
751
 
 
752
      pz->sfgen += i;
 
753
      i = modndx - pmodndx;
 
754
      while (i--) {
 
755
            SFMod* m = new SFMod;
 
756
            m->next = pz->mod;
 
757
            pz->mod = m;
 
758
            }
 
759
      }
 
760
 
 
761
//---------------------------------------------------------
 
762
//   load_pmod
 
763
//    preset modulator loader
 
764
//---------------------------------------------------------
 
765
 
 
766
void SFont::load_pmod(int size)
 
767
      {
 
768
      for (Preset* p = preset; p; p = p->next) {
 
769
            for (Zone* z = p->zone; z; z = z->next) {
 
770
                  for (SFMod* m = z->mod; m; m = m->next) {
 
771
                        if ((size -= SFMODSIZE) < 0)
 
772
                              longjmp(env, 31);
 
773
                        m->src    = readWord();
 
774
                        m->dest   = readWord();
 
775
                        m->amount = readw();
 
776
                        m->amtsrc = readWord();
 
777
                        m->trans  = readWord();
 
778
                        }
 
779
                  }
 
780
            }
 
781
      /*
 
782
       * If there isn't even a terminal record
 
783
       * Hmmm, the specs say there should be one, but..
 
784
       */
 
785
      if (size == 0)
 
786
            return;
 
787
 
 
788
      size -= SFMODSIZE;
 
789
      if (size != 0)
 
790
            longjmp(env, 32);
 
791
      fskip(SFMODSIZE); /* terminal mod */
 
792
      }
 
793
 
 
794
//---------------------------------------------------------
 
795
//   load_ihdr
 
796
//    instrument header loader
 
797
//---------------------------------------------------------
 
798
 
 
799
void SFont::load_ihdr(int size)
 
800
      {
 
801
      if (size % SFIHDRSIZE || size == 0)       /* chunk size is valid? */
 
802
            longjmp(env, 34);
 
803
 
 
804
      size = size / SFIHDRSIZE - 1;
 
805
      if (size == 0) {                          /* at least one preset + term record */
 
806
            gerr ("File contains no instruments");
 
807
            fskip(SFIHDRSIZE);
 
808
            return;
 
809
            }
 
810
      Inst *pr = inst;     // ptr to current & previous instrument
 
811
      int pzndx  = 0;
 
812
 
 
813
      for (int i = 0; i < size; i++) { /* load all instrument headers */
 
814
            Inst* p = new Inst;
 
815
            p->next = 0;
 
816
            p->zone  = 0;               /* For proper cleanup if fail (sfont_close) */
 
817
            readstr(p->name);   
 
818
            int zndx = readWord();
 
819
            if (pr) {                   /* not first instrument? */
 
820
                  pr->next = p;
 
821
                  if (zndx < pzndx)
 
822
                        longjmp(env, 35);
 
823
                  int i2 = zndx - pzndx;
 
824
                  while (i2--) {
 
825
                        Zone* z = new Zone;
 
826
                        z->next = pr->zone;
 
827
                        pr->zone = z;
 
828
                        }
 
829
                  }
 
830
            else {
 
831
                  inst = p;
 
832
                  if (zndx > 0)     /* 1st inst, warn if ofs >0 */
 
833
                        gerr ("%d instrument zones not referenced, discarding", zndx);
 
834
                  }
 
835
            pzndx = zndx;
 
836
            pr    = p;                  /* update instrument ptr */
 
837
            }
 
838
 
 
839
      fskip(20);
 
840
      int zndx = readWord();
 
841
 
 
842
      if (zndx < pzndx)
 
843
            longjmp(env, 35);
 
844
      int i2 = zndx - pzndx;
 
845
      while (i2--) {
 
846
            Zone* z = new Zone;
 
847
            z->next = pr->zone;
 
848
            pr->zone = z;
 
849
            }
 
850
      }
 
851
 
 
852
//---------------------------------------------------------
 
853
//   load_ibag
 
854
//    instrument bag loader
 
855
//---------------------------------------------------------
 
856
 
 
857
void SFont::load_ibag(int size)
 
858
      {
 
859
      Zone *pz = 0;
 
860
      unsigned int genndx, modndx;
 
861
      unsigned int pgenndx=0, pmodndx=0;
 
862
 
 
863
      if (size % SFBAGSIZE || size == 0)        /* size is multiple of SFBAGSIZE? */
 
864
            longjmp(env, 36);
 
865
 
 
866
      for (Inst* p = inst; p; p = p->next) {
 
867
            for (Zone* z = p->zone; z; z = z->next) {
 
868
                  if ((size -= SFBAGSIZE) < 0)
 
869
                        longjmp(env, 37);
 
870
                  genndx = readWord();
 
871
                  modndx = readWord();
 
872
 
 
873
                  if (pz) {                     /* if not first zone */
 
874
                        if (genndx < pgenndx)
 
875
                              longjmp(env, 38);
 
876
                        if (modndx < pmodndx)
 
877
                              longjmp(env, 39);
 
878
                        pz->sfgen += genndx - pgenndx;
 
879
                        for (unsigned i = pmodndx; i < modndx; ++i) {
 
880
                              SFMod* m = new SFMod;
 
881
                              m->next = pz->mod;
 
882
                              pz->mod = m;
 
883
                              }
 
884
                        }
 
885
                  pz      = z;     /* update previous zone ptr */
 
886
                  pgenndx = genndx;
 
887
                  pmodndx = modndx;
 
888
                  }
 
889
            }
 
890
 
 
891
      size -= SFBAGSIZE;
 
892
      if (size != 0)
 
893
            longjmp(env, 40);
 
894
 
 
895
      genndx = readWord();
 
896
      modndx = readWord();
 
897
 
 
898
      if (!pz) {                                /* in case that all are no zoners */
 
899
            if (genndx > 0)
 
900
                  gerr ("No instrument generators and terminal index not 0");
 
901
            if (modndx > 0)
 
902
                  gerr ("No instrument modulators and terminal index not 0");
 
903
            return;
 
904
            }
 
905
 
 
906
      if (genndx < pgenndx)
 
907
            longjmp(env, 41);
 
908
      if (modndx < pmodndx)
 
909
            longjmp(env, 42);
 
910
 
 
911
      pz->sfgen += genndx - pgenndx;
 
912
      for (unsigned i = pmodndx; i < modndx; ++i) {
 
913
            SFMod* m = new SFMod;
 
914
            m->next = pz->mod;
 
915
            pz->mod = m;
 
916
            }
 
917
      }
 
918
 
 
919
//---------------------------------------------------------
 
920
//   load_imod
 
921
//    instrument modulator loader
 
922
//---------------------------------------------------------
 
923
 
 
924
void SFont::load_imod(int size)
 
925
      {
 
926
      for (Inst* p = inst; p; p = p->next) {
 
927
            for (Zone* p2 = p->zone; p2; p2 = p2->next) {
 
928
                  for (SFMod* m = p2->mod; m; m = m->next) {
 
929
                        if ((size -= SFMODSIZE) < 0)
 
930
                              longjmp(env, 43);
 
931
                        m->src    = readWord();
 
932
                        m->dest   = readWord();
 
933
                        m->amount = readw();
 
934
                        m->amtsrc = readWord();
 
935
                        m->trans  = readWord();
 
936
                        }
 
937
                  }
 
938
            }
 
939
      /*
 
940
         If there isn't even a terminal record
 
941
         Hmmm, the specs say there should be one, but..
 
942
       */
 
943
      if (size == 0)
 
944
            return;
 
945
 
 
946
      size -= SFMODSIZE;
 
947
      if (size != 0)
 
948
            longjmp(env, 44);
 
949
      fskip(SFMODSIZE); /* terminal mod */
 
950
      }
 
951
 
 
952
//---------------------------------------------------------
 
953
//   load_pgen
 
954
//    preset generator loader
 
955
//    generator (per preset) loading rules:
 
956
//    Zones with no generators or modulators shall be annihilated
 
957
//    Global zone must be 1st zone, discard additional ones (instrumentless zones)
 
958
//
 
959
//    generator (per zone) loading rules (in order of decreasing precedence):
 
960
//    KeyRange is 1st in list (if exists), else discard
 
961
//    if a VelRange exists only
 
962
//          preceded by a KeyRange, else discard
 
963
//    if a generator follows an instrument
 
964
//          discard it
 
965
//    if a duplicate generator exists
 
966
//          replace previous one
 
967
//---------------------------------------------------------
 
968
 
 
969
void SFont::load_pgen(int size)
 
970
      {
 
971
      for (Preset* p = preset; p; p = p->next) {
 
972
            Zone** hz = 0;
 
973
            if (p->zone)
 
974
                  hz = &p->zone;
 
975
 
 
976
            bool gzone = false;
 
977
            for (Zone* zone = p->zone; zone; zone = zone->next) {
 
978
                  int level  = 0;
 
979
                  for (int gen = 0; gen < zone->sfgen; ++gen) {
 
980
                        if ((size -= SFGENSIZE) < 0)
 
981
                              longjmp(env, 32);
 
982
 
 
983
                        if (level == 3) {
 
984
                              fskip(SFGENSIZE);
 
985
                              continue;
 
986
                              }
 
987
 
 
988
                        unsigned genid = readw();
 
989
 
 
990
                        if (genid == Gen_KeyRange) {
 
991
                              unsigned char a = readByte();
 
992
                              unsigned char b = readByte();
 
993
                              if (level == 0) {
 
994
                                    level = 1;
 
995
                                    zone->keylo = a;
 
996
                                    zone->keyhi = b;
 
997
                                    }
 
998
                              }
 
999
                        else if (genid == Gen_VelRange) {
 
1000
                              unsigned char a = readByte();
 
1001
                              unsigned char b = readByte();
 
1002
                              if (level <= 1) {
 
1003
                                    level = 2;
 
1004
                                    zone->vello = a;
 
1005
                                    zone->velhi = b;
 
1006
                                    }
 
1007
                              }
 
1008
                        else if (genid == Gen_Instrument) {     // inst is last gen
 
1009
                              level = 3;
 
1010
                              zone->instsampno = readWord() + 1;
 
1011
                              }
 
1012
                        else {
 
1013
                              level = 2;
 
1014
                              int data = readw();
 
1015
                              if (gen_validp(genid)) {
 
1016
                                    zone->gen[genid].val   = double(data);
 
1017
                                    zone->gen[genid].flags = GEN_SET;
 
1018
                                    }
 
1019
                              }
 
1020
                        }
 
1021
 
 
1022
                  if (level != 3) {
 
1023
                        if (!gzone) {   // Prior global zones?
 
1024
                              gzone = true;
 
1025
 
 
1026
                              // if global zone is not 1st zone, relocate
 
1027
                              if (*hz != zone) {
 
1028
                                    Zone* save = zone;
 
1029
                                    Zone* pp = zone;
 
1030
                                    zone = zone->next;
 
1031
                                    sfont_zone_delete(hz, pp);
 
1032
                                    save->next = *hz;
 
1033
                                    *hz = save;
 
1034
                                    continue;
 
1035
                                    }
 
1036
                              }
 
1037
                        else {    // previous global zone exists, discard
 
1038
                              sfont_zone_delete(hz, zone);
 
1039
                              }
 
1040
                        }
 
1041
                  }
 
1042
            }
 
1043
      // in case there isn't a terminal record
 
1044
      if (size == 0)
 
1045
            return;
 
1046
 
 
1047
      size -= SFGENSIZE;
 
1048
      if (size != 0)
 
1049
            longjmp(env, 33);
 
1050
      fskip(SFGENSIZE);
 
1051
      }
 
1052
 
 
1053
//---------------------------------------------------------
 
1054
//   load_igen
 
1055
//    load instrument generators
 
1056
//    (see load_pgen for loading rules)
 
1057
//---------------------------------------------------------
 
1058
 
 
1059
void SFont::load_igen(int size)
 
1060
      {
 
1061
      for (Inst* ip = inst; ip; ip = ip->next) {
 
1062
            Zone** hz = 0;
 
1063
            if (ip->zone)
 
1064
                  hz = &ip->zone;
 
1065
 
 
1066
            bool gzone = false;
 
1067
            for (Zone* zone = ip->zone; zone; zone = zone->next) {
 
1068
                  int level = 0;
 
1069
                  for (int gen = 0; gen < zone->sfgen; ++gen) {
 
1070
                        if ((size -= SFGENSIZE) < 0)
 
1071
                              longjmp(env, 45);
 
1072
 
 
1073
                        if (level == 3) {
 
1074
                              fskip(SFGENSIZE);
 
1075
                              continue;
 
1076
                              }
 
1077
 
 
1078
                        unsigned genid = readWord();
 
1079
 
 
1080
                        if (genid == Gen_KeyRange) {
 
1081
                              unsigned char a = readByte();
 
1082
                              unsigned char b = readByte();
 
1083
                              if (level == 0) {
 
1084
                                    level = 1;
 
1085
                                    zone->keylo = a;
 
1086
                                    zone->keyhi = b;
 
1087
                                    }
 
1088
                              }
 
1089
                        else if (genid == Gen_VelRange) {
 
1090
                              unsigned char a = readByte();
 
1091
                              unsigned char b = readByte();
 
1092
                              if (level <= 1) {
 
1093
                                    level = 2;
 
1094
                                    zone->vello = a;
 
1095
                                    zone->velhi = b;
 
1096
                                    }
 
1097
                              }
 
1098
                        else if (genid == Gen_SampleId) {
 
1099
                              level = 3;
 
1100
                              zone->instsampno = readWord() + 1;
 
1101
                              }
 
1102
                        else {
 
1103
                              level = 2;
 
1104
                              int data = readw();
 
1105
                              if (gen_valid(genid)) {           /* gen valid? */
 
1106
                                    zone->gen[genid].val   = double(data);
 
1107
                                    zone->gen[genid].flags = GEN_SET;
 
1108
                                    }
 
1109
                              }
 
1110
                        }
 
1111
 
 
1112
                  if (level != 3) {
 
1113
                        if (!gzone) {
 
1114
                              gzone = true;
 
1115
 
 
1116
                              /* if global zone is not 1st zone, relocate */
 
1117
                              if (*hz != zone) {
 
1118
                                    Zone* save = zone;
 
1119
                                    SLADVREMZ (*hz, zone);
 
1120
                                    save->next = *hz;
 
1121
                                    *hz = save;
 
1122
                                    continue;
 
1123
                                    }
 
1124
                              }
 
1125
                        else {
 
1126
                              sfont_zone_delete (hz, zone);
 
1127
                              }
 
1128
                        }
 
1129
                  }
 
1130
            }
 
1131
 
 
1132
      /* for those non-terminal record cases, grr! */
 
1133
      if (size == 0)
 
1134
            return;
 
1135
 
 
1136
      size -= SFGENSIZE;
 
1137
      if (size != 0)
 
1138
            longjmp(env, 47);
 
1139
      fskip(SFGENSIZE); /* terminal gen */
 
1140
      }
 
1141
 
 
1142
//---------------------------------------------------------
 
1143
//   load_shdr
 
1144
//    sample header loader
 
1145
//---------------------------------------------------------
 
1146
 
 
1147
void SFont::load_shdr(int size)
 
1148
      {
 
1149
      if (size % SFSHDRSIZE || size == 0)       /* size is multiple of SHDR size? */
 
1150
            longjmp(env, 48);
 
1151
 
 
1152
      size = size / SFSHDRSIZE - 1;
 
1153
      if (size == 0) {                          /* at least one sample + term record? */
 
1154
            gerr ("File contains no samples");
 
1155
            fskip(SFSHDRSIZE);
 
1156
            return;
 
1157
            }
 
1158
      /* load all sample headers */
 
1159
      Sample* ps = sample;
 
1160
      while (ps && ps->next)
 
1161
            ps = ps->next;
 
1162
 
 
1163
      for (int i = 0; i < size; i++) {
 
1164
            Sample* p = new Sample;
 
1165
            p->next = 0;
 
1166
            if (ps)
 
1167
                  ps->next = p;
 
1168
            else
 
1169
                  sample = p;
 
1170
            ps = p;
 
1171
 
 
1172
            readstr(p->name());
 
1173
            p->start      = readd();
 
1174
            p->end        = readd();      // end, loopstart and loopend
 
1175
            p->loopstart  = readd();      // will be checked and turned into
 
1176
            p->loopend    = readd();      // offsets in fixup_sample()
 
1177
            p->samplerate = readd();
 
1178
 
 
1179
            p->origpitch  = readByte();
 
1180
            p->pitchadj   = readb();
 
1181
            fskip(2);                       // skip sample link
 
1182
            p->sampletype = readWord();
 
1183
            }
 
1184
      fskip(SFSHDRSIZE);        /* skip terminal shdr */
 
1185
      }
 
1186
 
 
1187
//---------------------------------------------------------
 
1188
//   fixup_pgen
 
1189
//    "fixup" (inst # -> inst ptr) instrument
 
1190
//    references in preset list
 
1191
//---------------------------------------------------------
 
1192
 
 
1193
void SFont::fixup_pgen()
 
1194
      {
 
1195
      for (Preset* p = preset; p; p = p->next) {
 
1196
            for (Zone* z = p->zone; z; z = z->next) {
 
1197
                  int i = z->instsampno;
 
1198
                  if (i) {                      /* load instrument # */
 
1199
                        Inst* ii = inst;
 
1200
                        --i;
 
1201
                        while (i && ii) {
 
1202
                              ii = ii->next;
 
1203
                              --i;
 
1204
                              }
 
1205
                        if (!ii)
 
1206
                              longjmp(env, 49);
 
1207
                          z->inst = ii;
 
1208
                        }
 
1209
                  }
 
1210
            }
 
1211
      }
 
1212
 
 
1213
//---------------------------------------------------------
 
1214
//   fixup_igen
 
1215
//    "fixup" (sample # -> sample ptr) sample references
 
1216
//    in instrument list
 
1217
//---------------------------------------------------------
 
1218
 
 
1219
void SFont::fixup_igen()
 
1220
      {
 
1221
      for (Inst* p = inst; p; p = p->next) {
 
1222
            for (Zone* z = p->zone; z; z = z->next) {
 
1223
                  int i = z->instsampno;
 
1224
                  if (i) {                      /* load sample # */
 
1225
                        Sample* ii = sample;
 
1226
                        --i;
 
1227
                        while (i && ii) {
 
1228
                              ii = ii->next;
 
1229
                              --i;
 
1230
                              }
 
1231
                        if (!ii) {
 
1232
//                              printf("invalid sample %d\n", z->instsampno);
 
1233
                              longjmp(env, 50);
 
1234
                              }
 
1235
                          z->samp = ii;
 
1236
                        }
 
1237
                  }
 
1238
            }
 
1239
      }
 
1240
 
 
1241
//---------------------------------------------------------
 
1242
//   fixup_sample
 
1243
//    convert sample end, loopstart and loopend to offsets
 
1244
//    and check if valid
 
1245
//---------------------------------------------------------
 
1246
 
 
1247
void SFont::fixup_sample()
 
1248
      {
 
1249
      for (Sample* sam = sample; sam; sam = sam->next) {
 
1250
            /* if sample is not a ROM sample and end is over the sample data chunk
 
1251
               or sam start is greater than 4 less than the end (at least 4 samples) */
 
1252
            if ((!(sam->sampletype & SF_SAMPLETYPE_ROM) && sam->end
 
1253
               > unsigned(sdtachunk_size)) || sam->start > (sam->end - 4)) {
 
1254
                  gerr ("Sample '%s' start/end file positions are invalid,"
 
1255
              " disabling and will not be saved", sam->name());
 
1256
 
 
1257
                  /* disable sample by setting all sample markers to 0 */
 
1258
                  sam->start = sam->end = sam->loopstart = sam->loopend = 0;
 
1259
                  return;
 
1260
                  }
 
1261
            else if (sam->loopend > sam->end || sam->loopstart >= sam->loopend
 
1262
               || sam->loopstart <= sam->start) { /* loop is fowled?? (cluck cluck :) */
 
1263
                  /* can pad loop by 8 samples and ensure at least 4 for loop (2*8+4) */
 
1264
                  if ((sam->end - sam->start) >= 20) {
 
1265
                        sam->loopstart = sam->start + 8;
 
1266
                        sam->loopend = sam->end - 8;
 
1267
                        }
 
1268
                  else { /* loop is fowled, sample is tiny (can't pad 8 samples) */
 
1269
                        sam->loopstart = sam->start + 1;
 
1270
                        sam->loopend = sam->end - 1;
 
1271
                        }
 
1272
                  }
 
1273
            sam->end -= 1;      /* marks last sample, contrary to SF spec. */
 
1274
            }
 
1275
      }
 
1276
 
 
1277
//---------------------------------------------------------
 
1278
//   load_sampledata
 
1279
//---------------------------------------------------------
 
1280
 
 
1281
void SFont::load_sampledata()
 
1282
      {
 
1283
      if (fseek(fd, samplepos, SEEK_SET) == -1)
 
1284
            longjmp(env, 53);
 
1285
      sampledata = new short[samplesize];
 
1286
      safe_fread(sampledata, samplesize);
 
1287
      for (Sample* s = sample; s; s = s->next)
 
1288
            s->setData(sampledata);
 
1289
      }
 
1290
 
 
1291
//---------------------------------------------------------
 
1292
//   get_sample
 
1293
//---------------------------------------------------------
 
1294
 
 
1295
Sample* SFont::get_sample(const char *s) const
 
1296
      {
 
1297
      for (Sample* sp = sample; sp; sp = sp->next) {
 
1298
            if (strcmp(sp->name(), s) == 0)
 
1299
                  return sp;
 
1300
            }
 
1301
      return 0;
 
1302
      }
 
1303
 
 
1304
//---------------------------------------------------------
 
1305
//   load
 
1306
//---------------------------------------------------------
 
1307
 
 
1308
int SFont::load(const char* fn)
 
1309
      {
 
1310
      static char* errMsg = "iiwu: load soundfont: %s failed: %s\n";
 
1311
 
 
1312
      file = strdup(fn);
 
1313
 
 
1314
      if (!(fd = fopen (file, "rb"))) {
 
1315
            fprintf(stderr, errMsg, "open", strerror(errno));
 
1316
            return 1;
 
1317
            }
 
1318
      struct stat buf;
 
1319
      if (fstat(fileno(fd), &buf) == -1) {
 
1320
            fprintf(stderr, errMsg, "stat", strerror(errno));
 
1321
            return 1;
 
1322
            }
 
1323
      fsize = buf.st_size;
 
1324
 
 
1325
 
 
1326
      int error = setjmp(env);
 
1327
      if (error == 0) {
 
1328
            load_body();
 
1329
            }
 
1330
      else {
 
1331
            const char* s = "??";
 
1332
            switch (error) {
 
1333
                  case 0:  break;
 
1334
                  case 1:  s = "Sound font version info chunk has invalid size"; break;
 
1335
                  case 2:  s = "Sound font version unsupported, convert to version 2.0x"; break;
 
1336
                  case 3:  s = "ROM version info chunk has invalid size"; break;
 
1337
                  case 4:  s = "INFO sub chunk has invalid chunk size"; break;
 
1338
                  case 5:  s = "Invalid chunk id in INFO chunk"; break;
 
1339
                  case 6:  s = "INFO chunk size mismatch"; break;
 
1340
                  case 7:  s = "Invalid chunk id in level 0 parse"; break;
 
1341
                  case 8:  s = "Not a RIFF file"; break;
 
1342
                  case 9:  s = "Not a sound font file"; break;
 
1343
                  case 10: s = "Sound font file size mismatch"; break;
 
1344
                  case 11: s = "Invalid ID found when expecting INFO chunk"; break;
 
1345
                  case 12: s = "Invalid ID found when expecting SAMPLE chunk"; break;
 
1346
                  case 13: s = "Invalid ID found when expecting HYDRA chunk"; break;
 
1347
                  case 14: s = "Expected SMPL chunk found invalid id instead"; break;
 
1348
                  case 15: s = "SDTA chunk size mismatch"; break;
 
1349
                  case 16: s = "Unexpected PDTA sub-chunk"; break;
 
1350
                  case 17: s = "chunk size is not a multiple of xxx bytes"; break;
 
1351
                  case 18: s = "chunk size exceeds remaining PDTA chunk size"; break;
 
1352
                  case 19: s = "Preset header chunk size is invalid"; break;
 
1353
                  case 20: s = "Preset header indices not monotonic"; break;
 
1354
                  case 21: s = "xx preset zones not referenced, discarding"; break;
 
1355
                  case 22: s = "Preset header indices not monotonic"; break;
 
1356
                  case 23: s = "Preset bag chunk size is invalid"; break;
 
1357
                  case 24: s = "Preset bag chunk size mismatch"; break;
 
1358
                  case 25: s = "Preset bag generator indices not monotonic"; break;
 
1359
                  case 26: s = "Preset bag modulator indices not monotonic"; break;
 
1360
                  case 27: s = "No preset generators and terminal index not 0"; break;
 
1361
                  case 28: s = "No preset modulators and terminal index not 0"; break;
 
1362
                  case 29: s = "Preset bag generator indices not monotonic"; break;
 
1363
                  case 30: s = "Preset bag modulator indices not monotonic"; break;
 
1364
                  case 31: s = "Preset modulator chunk size mismatch"; break;
 
1365
                  case 32: s = "Preset modulator chunk size mismatch"; break;
 
1366
                  case 33: s = "Preset generator chunk size mismatch"; break;
 
1367
                  case 34: s = "Instrument header has invalid size"; break;
 
1368
                  case 35: s = "Instrument header indices not monotonic"; break;
 
1369
                  case 36: s = "Instrument bag chunk size is invalid"; break;
 
1370
                  case 37: s = "Instrument bag chunk size mismatch"; break;
 
1371
                  case 38: s = "Instrument generator indices not monotonic"; break;
 
1372
                  case 39: s = "Instrument modulator indices not monotonic"; break;
 
1373
                  case 40: s = "Instrument chunk size mismatch"; break;
 
1374
                  case 41: s = "Instrument generator indices not monotonic"; break;
 
1375
                  case 42: s = "Instrument modulator indices not monotonic"; break;
 
1376
                  case 43: s = "Instrument modulator chunk size mismatch"; break;
 
1377
                  case 44: s = "Instrument modulator chunk size mismatch"; break;
 
1378
                  case 45: s = "IGEN chunk size mismatch"; break;
 
1379
                  case 46: s = "Instrument generator chunk size mismatch"; break;
 
1380
                  case 47: s = "IGEN chunk size mismatch"; break;
 
1381
                  case 48: s = "Sample header has invalid size"; break;
 
1382
                  case 49: s = "Preset xx xx: Invalid instrument reference"; break;
 
1383
                  case 50: s = "Instrument xxx: Invalid sample reference"; break;
 
1384
                  case 51: s = "File read: EOF"; break;
 
1385
                  case 52: s = "File read"; break;
 
1386
                  case 53: s = "seek"; break;
 
1387
                  }
 
1388
            fprintf(stderr, errMsg, "", s);
 
1389
            fclose(fd);
 
1390
            return true;
 
1391
            }
 
1392
//      dump();
 
1393
      return 0;
 
1394
      }
 
1395
 
 
1396
//---------------------------------------------------------
 
1397
//   Inst
 
1398
//---------------------------------------------------------
 
1399
 
 
1400
Inst::Inst()
 
1401
      {
 
1402
      zone        = 0;
 
1403
      }
 
1404
 
 
1405
Inst::~Inst()
 
1406
      {
 
1407
      Zone* z = zone;
 
1408
      while (z) {
 
1409
            Zone* zz = z->next;
 
1410
            delete zz;
 
1411
            z = zz;
 
1412
            }
 
1413
      }
 
1414
 
 
1415
//---------------------------------------------------------
 
1416
//   get_preset
 
1417
//---------------------------------------------------------
 
1418
 
 
1419
Preset* SFont::get_preset(char hbank, char lbank, char prog)
 
1420
      {
 
1421
      Preset* p = preset;
 
1422
      int n = 0;
 
1423
      while (p) {
 
1424
            if (p->hbank == hbank && p->lbank == lbank && (p->prog == prog)) {
 
1425
                  return p;
 
1426
                  }
 
1427
            ++n;
 
1428
            p = p->next;
 
1429
            }
 
1430
      if (next)
 
1431
            return next->get_preset(hbank, lbank, prog);
 
1432
      return 0;
 
1433
      }
 
1434
 
 
1435
//---------------------------------------------------------
 
1436
//   append_sfont
 
1437
//---------------------------------------------------------
 
1438
 
 
1439
void SFont::append_sfont(SFont* sfont2)
 
1440
      {
 
1441
      if (sfont2 == 0)
 
1442
            return;
 
1443
      if (next)
 
1444
            next->append_sfont(sfont2);
 
1445
      else {
 
1446
            sfont2->next = 0;
 
1447
            next = sfont2;
 
1448
            }
 
1449
      }
 
1450
 
 
1451
//=========================================================
 
1452
//    DEBUG
 
1453
//=========================================================
 
1454
 
 
1455
#ifdef DEBUG
 
1456
void SFont::dump() const
 
1457
      {
 
1458
      printf("Sfont <%s> Version %d.%d, size %d\n", file,
 
1459
         version.major, version.minor, fsize);
 
1460
      for (Preset* p = preset; p; p = p->next)
 
1461
            p->dump();
 
1462
      for (Inst* i = inst; i; i = i->next)
 
1463
            i->dump();
 
1464
      }
 
1465
 
 
1466
void Preset::dump() const
 
1467
      {
 
1468
      printf("Preset <%s> idx %d sfont %p\n", name, zoneIndex, _sfont);
 
1469
      for (Zone* z = zone; z; z = z->next) {
 
1470
            z->dump();
 
1471
            }
 
1472
      }
 
1473
void Zone::dump() const
 
1474
      {
 
1475
      printf("  Zone %d-%d %d-%d\n", keylo,keyhi,vello,velhi);
 
1476
      printf("    inst %p, samp %p, sfgen %p, mod %p\n",
 
1477
         inst, samp, sfgen, mod);
 
1478
      for (SFGen* g = sfgen; g; g = g->next)
 
1479
            g->dump();
 
1480
      for (SFMod* m = mod; m; m = m->next)
 
1481
            m->dump();
 
1482
 
 
1483
      }
 
1484
 
 
1485
void Inst::dump() const
 
1486
      {
 
1487
      printf("Instrument <%s>\n", name);
 
1488
      for (Zone* z = zone; z; z = z->next)
 
1489
            z->dump();
 
1490
      }
 
1491
 
 
1492
void SFGen::dump() const
 
1493
      {
 
1494
      printf("      SFGen: id %d\n", id);
 
1495
      }
 
1496
 
 
1497
void SFMod::dump() const
 
1498
      {
 
1499
      printf("      SFMod: %d %d %d %d %d\n",
 
1500
         src, dest, amount, amtsrc, trans);
 
1501
      }
 
1502
#endif
 
1503