~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to kmidi/readsbk.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*================================================================
 
2
 * readsbk.c:
 
3
 *      read soundfont file
 
4
 *================================================================*/
 
5
 
 
6
#include <stdio.h>
 
7
#include <string.h>
 
8
#include <stdlib.h>
 
9
#include "config.h"
 
10
#include "sbk.h"
 
11
 
 
12
/*----------------------------------------------------------------
 
13
 * function prototypes
 
14
 *----------------------------------------------------------------*/
 
15
 
 
16
#define NEW(type,nums)  (type*)malloc(sizeof(type) * (nums))
 
17
 
 
18
static int READCHUNK(tchunk *vp, FILE *fd)
 
19
{
 
20
        if (fread(vp, 8, 1, fd) != 1) return -1;
 
21
        vp->size = LE_LONG(vp->size);
 
22
        return 1;
 
23
}
 
24
 
 
25
static int READDW(uint32 *vp, FILE *fd)
 
26
{
 
27
        if (fread(vp, 4, 1, fd) != 1) return -1;
 
28
        *vp = LE_LONG(*vp);
 
29
        return 1;
 
30
}       
 
31
 
 
32
static int READW(uint16 *vp, FILE *fd)
 
33
{
 
34
        if (fread(vp, 2, 1, fd) != 1) return -1;
 
35
        *vp = LE_SHORT(*vp);
 
36
        return 1;
 
37
}
 
38
 
 
39
#define READSTR(var,fd) fread(var, 20, 1, fd)
 
40
 
 
41
#if 0
 
42
static int READSTR(char *str, FILE *fd)
 
43
{
 
44
    int n;
 
45
 
 
46
    if(fread(str, 20, 1, fd) != 1) return -1;
 
47
    str[20] = '\0';
 
48
    n = strlen(str);
 
49
    while(n > 0 && str[n - 1] == ' ')
 
50
        n--;
 
51
    str[n] = '\0';
 
52
    return n;
 
53
}
 
54
#endif
 
55
 
 
56
#define READID(var,fd)  fread(var, 1, 4, fd)
 
57
#define READB(var,fd)   fread(var, 1, 1, fd)
 
58
#define SKIPB(fd)       {uint8 dummy; fread(&dummy, 1, 1, fd);}
 
59
#define SKIPW(fd)       {uint16 dummy; fread(&dummy, 2, 1, fd);}
 
60
#define SKIPDW(fd)      {uint32 dummy; fread(&dummy, 4, 1, fd);}
 
61
 
 
62
static int getchunk(const char *id);
 
63
static void process_chunk(int id, int s, SFInfo *sf, FILE *fd);
 
64
static void load_sample_names(int size, SFInfo *sf, FILE *fd);
 
65
static void load_preset_header(int size, SFInfo *sf, FILE *fd);
 
66
static void load_inst_header(int size, SFInfo *sf, FILE *fd);
 
67
static void load_bag(int size, SFInfo *sf, FILE *fd, int *totalp, unsigned short **bufp);
 
68
static void load_gen(int size, SFInfo *sf, FILE *fd, int *totalp, tgenrec **bufp);
 
69
static void load_sample_info(int size, SFInfo *sf, FILE *fd);
 
70
 
 
71
 
 
72
 
 
73
enum {
 
74
        /* level 0 */
 
75
        UNKN_ID, RIFF_ID, LIST_ID,
 
76
        /* level 1 */
 
77
        INFO_ID, SDTA_ID, PDTA_ID,
 
78
        /* info stuff */
 
79
        IFIL_ID, ISNG_ID, IROM_ID, INAM_ID, IVER_ID, IPRD_ID, ICOP_ID,
 
80
#ifdef tplussbk
 
81
        ICRD_ID, IENG_ID, ISFT_ID, ICMT_ID,
 
82
#endif
 
83
        /* sample data stuff */
 
84
        SNAM_ID, SMPL_ID,
 
85
        /* preset stuff */
 
86
        PHDR_ID, PBAG_ID, PMOD_ID, PGEN_ID,
 
87
        /* inst stuff */
 
88
        INST_ID, IBAG_ID, IMOD_ID, IGEN_ID,
 
89
        /* sample header */
 
90
        SHDR_ID
 
91
};
 
92
 
 
93
 
 
94
/*----------------------------------------------------------------
 
95
 * debug routine
 
96
 *----------------------------------------------------------------*/
 
97
 
 
98
#if 0
 
99
static void debugid(char *tag, char *p)
 
100
{
 
101
        char buf[5]; strncpy(buf, p, 4); buf[4]=0;
 
102
        fprintf(stderr,"[%s:%s]\n", tag, buf);
 
103
}
 
104
 
 
105
static void debugname(char *tag, char *p)
 
106
{
 
107
        char buf[21]; strncpy(buf, p, 20); buf[20]=0;
 
108
        fprintf(stderr,"[%s:%s]\n", tag, buf);
 
109
}
 
110
 
 
111
static void debugval(char *tag, int v)
 
112
{
 
113
        fprintf(stderr, "[%s:%d]\n", tag, v);
 
114
}
 
115
#else
 
116
#define debugid(t,s) /**/
 
117
#define debugname(t,s) /**/
 
118
#define debugval(t,v) /**/
 
119
#endif
 
120
 
 
121
 
 
122
/*----------------------------------------------------------------
 
123
 * load sbk file
 
124
 *----------------------------------------------------------------*/
 
125
 
 
126
void load_sbk(FILE *fd, SFInfo *sf)
 
127
{
 
128
        tchunk chunk, subchunk;
 
129
 
 
130
        READID(sf->sbkh.riff, fd);
 
131
        READDW(&sf->sbkh.size, fd);
 
132
        READID(sf->sbkh.sfbk, fd);
 
133
 
 
134
        sf->in_rom = 1;
 
135
        while (! feof(fd)) {
 
136
                READID(chunk.id, fd);
 
137
                switch (getchunk(chunk.id)) {
 
138
                case LIST_ID:
 
139
                        READDW(&chunk.size, fd);
 
140
                        READID(subchunk.id, fd);
 
141
                        process_chunk(getchunk(subchunk.id), chunk.size - 4, sf, fd);
 
142
                        break;
 
143
                }
 
144
        }
 
145
}
 
146
 
 
147
 
 
148
/*----------------------------------------------------------------
 
149
 * free buffer
 
150
 *----------------------------------------------------------------*/
 
151
 
 
152
void free_sbk(SFInfo *sf)
 
153
{
 
154
        free(sf->samplenames);
 
155
        free(sf->presethdr);
 
156
        free(sf->sampleinfo);
 
157
        free(sf->insthdr);
 
158
        free(sf->presetbag);
 
159
        free(sf->instbag);
 
160
        free(sf->presetgen);
 
161
        free(sf->instgen);
 
162
        /* if (sf->sf_name) free(sf->sf_name); */
 
163
        memset(sf, 0, sizeof(*sf));
 
164
}
 
165
 
 
166
 
 
167
 
 
168
/*----------------------------------------------------------------
 
169
 * get id value
 
170
 *----------------------------------------------------------------*/
 
171
 
 
172
static int getchunk(const char *id)
 
173
{
 
174
        static struct idstring {
 
175
                const char *str;
 
176
                int id;
 
177
        } idlist[] = {
 
178
                {"LIST", LIST_ID},
 
179
#ifdef tplussbk
 
180
                {"sfbk", SFBK_ID},
 
181
#endif
 
182
                {"INFO", INFO_ID},
 
183
                {"sdta", SDTA_ID},
 
184
                {"snam", SNAM_ID},
 
185
                {"smpl", SMPL_ID},
 
186
                {"pdta", PDTA_ID},
 
187
                {"phdr", PHDR_ID},
 
188
                {"pbag", PBAG_ID},
 
189
                {"pmod", PMOD_ID},
 
190
                {"pgen", PGEN_ID},
 
191
                {"inst", INST_ID},
 
192
                {"ibag", IBAG_ID},
 
193
                {"imod", IMOD_ID},
 
194
                {"igen", IGEN_ID},
 
195
                {"shdr", SHDR_ID},
 
196
                {"ifil", IFIL_ID},
 
197
                {"isng", ISNG_ID},
 
198
                {"irom", IROM_ID},
 
199
                {"iver", IVER_ID},
 
200
                {"INAM", INAM_ID},
 
201
                {"IPRD", IPRD_ID},
 
202
                {"ICOP", ICOP_ID},
 
203
#ifdef tplussbk
 
204
                {"ICRD", ICRD_ID},
 
205
                {"IENG", IENG_ID},
 
206
                {"ISFT", ISFT_ID},
 
207
                {"ICMT", ICMT_ID},
 
208
#endif
 
209
        };
 
210
 
 
211
        unsigned int i;
 
212
 
 
213
        for (i = 0; i < sizeof(idlist)/sizeof(idlist[0]); i++) {
 
214
                if (strncmp(id, idlist[i].str, 4) == 0) {
 
215
                        debugid("ok", id);
 
216
                        return idlist[i].id;
 
217
                }
 
218
        }
 
219
 
 
220
        debugid("xx", id);
 
221
        return UNKN_ID;
 
222
}
 
223
 
 
224
 
 
225
static void load_sample_names(int size, SFInfo *sf, FILE *fd)
 
226
{
 
227
        int i;
 
228
        sf->nrsamples = size / 20;
 
229
        sf->samplenames = NEW(tsamplenames, sf->nrsamples);
 
230
        for (i = 0; i < sf->nrsamples; i++) {
 
231
                READSTR(sf->samplenames[i].name, fd);
 
232
                sf->samplenames[i].name[20] = 0;
 
233
        }
 
234
}
 
235
 
 
236
static void load_preset_header(int size, SFInfo *sf, FILE *fd)
 
237
{
 
238
        int i;
 
239
        sf->nrpresets = size / 38;
 
240
        sf->presethdr = NEW(tpresethdr, sf->nrpresets);
 
241
        for (i = 0; i < sf->nrpresets; i++) {
 
242
                READSTR(sf->presethdr[i].name, fd);
 
243
                READW(&sf->presethdr[i].preset, fd);
 
244
                sf->presethdr[i].sub_preset = sf->presethdr[i].preset;
 
245
                READW(&sf->presethdr[i].bank, fd);
 
246
                sf->presethdr[i].sub_bank = sf->presethdr[i].bank;
 
247
                READW(&sf->presethdr[i].bagNdx, fd);
 
248
                SKIPDW(fd); /* lib */
 
249
                SKIPDW(fd); /* genre */
 
250
                SKIPDW(fd); /* morph */
 
251
        }
 
252
}
 
253
 
 
254
static void load_inst_header(int size, SFInfo *sf, FILE *fd)
 
255
{
 
256
        int i;
 
257
 
 
258
        sf->nrinsts = size / 22;
 
259
        sf->insthdr = NEW(tinsthdr, sf->nrinsts);
 
260
        for (i = 0; i < sf->nrinsts; i++) {
 
261
                READSTR(sf->insthdr[i].name, fd);
 
262
                READW(&sf->insthdr[i].bagNdx, fd);
 
263
        }
 
264
                
 
265
}
 
266
 
 
267
static void load_bag(int size, SFInfo *sf, FILE *fd, int *totalp, unsigned short **bufp)
 
268
{
 
269
        unsigned short *buf;
 
270
        int i;
 
271
 
 
272
        debugval("bagsize", size);
 
273
        size /= 4;
 
274
        buf = NEW(unsigned short, size);
 
275
        for (i = 0; i < size; i++) {
 
276
                READW(&buf[i], fd);
 
277
                SKIPW(fd); /* mod */
 
278
        }
 
279
        *totalp = size;
 
280
        *bufp = buf;
 
281
}
 
282
 
 
283
static void load_gen(int size, SFInfo *sf, FILE *fd, int *totalp, tgenrec **bufp)
 
284
{
 
285
        tgenrec *buf;
 
286
        int i;
 
287
 
 
288
        debugval("gensize", size);
 
289
        size /= 4;
 
290
        buf = NEW(tgenrec, size);
 
291
        for (i = 0; i < size; i++) {
 
292
                READW(&buf[i].oper, fd);
 
293
                READW(&buf[i].amount, fd);
 
294
        }
 
295
        *totalp = size;
 
296
        *bufp = buf;
 
297
}
 
298
 
 
299
static void load_sample_info(int size, SFInfo *sf, FILE *fd)
 
300
{
 
301
        int i;
 
302
 
 
303
        debugval("infosize", size);
 
304
        if (sf->version > 1) {
 
305
                sf->nrinfos = size / 46;
 
306
                sf->nrsamples = sf->nrinfos;
 
307
                sf->sampleinfo = NEW(tsampleinfo, sf->nrinfos);
 
308
                sf->samplenames = NEW(tsamplenames, sf->nrsamples);
 
309
        }
 
310
        else  {
 
311
                sf->nrinfos = size / 16;
 
312
                sf->sampleinfo = NEW(tsampleinfo, sf->nrinfos);
 
313
        }
 
314
 
 
315
 
 
316
        for (i = 0; i < sf->nrinfos; i++) {
 
317
                if (sf->version > 1)
 
318
                        READSTR(sf->samplenames[i].name, fd);
 
319
                READDW(&sf->sampleinfo[i].startsample, fd);
 
320
                READDW(&sf->sampleinfo[i].endsample, fd);
 
321
                READDW(&sf->sampleinfo[i].startloop, fd);
 
322
                READDW(&sf->sampleinfo[i].endloop, fd);
 
323
                if (sf->version > 1) {
 
324
                        READDW(&sf->sampleinfo[i].samplerate, fd);
 
325
                        READB(&sf->sampleinfo[i].originalPitch, fd);
 
326
                        READB(&sf->sampleinfo[i].pitchCorrection, fd);
 
327
                        READW(&sf->sampleinfo[i].samplelink, fd);
 
328
                        READW(&sf->sampleinfo[i].sampletype, fd);
 
329
                } else {
 
330
                        if (sf->sampleinfo[i].startsample == 0)
 
331
                                sf->in_rom = 0;
 
332
                        sf->sampleinfo[i].startloop++;
 
333
                        sf->sampleinfo[i].endloop += 2;
 
334
                        sf->sampleinfo[i].samplerate = 44100;
 
335
                        sf->sampleinfo[i].originalPitch = 60;
 
336
                        sf->sampleinfo[i].pitchCorrection = 0;
 
337
                        sf->sampleinfo[i].samplelink = 0;
 
338
                        if (sf->in_rom)
 
339
                                sf->sampleinfo[i].sampletype = 0x8001;
 
340
                        else
 
341
                                sf->sampleinfo[i].sampletype = 1;
 
342
                }
 
343
        }
 
344
}
 
345
 
 
346
 
 
347
/*
 
348
 */
 
349
 
 
350
static void process_chunk(int id, int s, SFInfo *sf, FILE *fd)
 
351
{
 
352
        int cid;
 
353
        tchunk subchunk;
 
354
 
 
355
        switch (id) {
 
356
        case INFO_ID:
 
357
                READCHUNK(&subchunk, fd);
 
358
                while ((cid = getchunk(subchunk.id)) != LIST_ID) {
 
359
                        switch (cid) {
 
360
                        case IFIL_ID:
 
361
                                READW(&sf->version, fd);
 
362
                                READW(&sf->minorversion, fd);
 
363
                                break;
 
364
                        /*
 
365
                        case INAM_ID:
 
366
                                sf->sf_name = (char*)malloc(subchunk.size);
 
367
                                if (sf->sf_name == NULL) {
 
368
                                        fprintf(stderr, "can't malloc\n");
 
369
                                        exit(1);
 
370
                                }
 
371
                                fread(sf->sf_name, 1, subchunk.size, fd);
 
372
                                break;
 
373
                        */
 
374
                        default:
 
375
                                fseek(fd, subchunk.size, SEEK_CUR);
 
376
                                break;
 
377
                        }
 
378
                        READCHUNK(&subchunk, fd);
 
379
                        if (feof(fd))
 
380
                                return;
 
381
                }
 
382
                fseek(fd, -8, SEEK_CUR); /* seek back */
 
383
                break;
 
384
 
 
385
        case SDTA_ID:
 
386
                READCHUNK(&subchunk, fd);
 
387
                while ((cid = getchunk(subchunk.id)) != LIST_ID) {
 
388
                        switch (cid) {
 
389
                        case SNAM_ID:
 
390
                                if (sf->version > 1) {
 
391
                                        printf("**** version 2 has obsolete format??\n");
 
392
                                        fseek(fd, subchunk.size, SEEK_CUR);
 
393
                                } else
 
394
                                        load_sample_names(subchunk.size, sf, fd);
 
395
                                break;
 
396
                        case SMPL_ID:
 
397
                                sf->samplepos = ftell(fd);
 
398
                                sf->samplesize = subchunk.size;
 
399
                                fseek(fd, subchunk.size, SEEK_CUR);
 
400
                        }
 
401
                        READCHUNK(&subchunk, fd);
 
402
                        if (feof(fd))
 
403
                                return;
 
404
                }
 
405
                fseek(fd, -8, SEEK_CUR); /* seek back */
 
406
                break;
 
407
 
 
408
        case PDTA_ID:
 
409
                READCHUNK(&subchunk, fd);
 
410
                while ((cid = getchunk(subchunk.id)) != LIST_ID) {
 
411
                        switch (cid) {
 
412
                        case PHDR_ID:
 
413
                                load_preset_header(subchunk.size, sf, fd);
 
414
                                break;
 
415
 
 
416
                        case PBAG_ID:
 
417
                                load_bag(subchunk.size, sf, fd,
 
418
                                         &sf->nrpbags, &sf->presetbag);
 
419
                                break;
 
420
 
 
421
                        case PMOD_ID: /* ignored */
 
422
                                fseek(fd, subchunk.size, SEEK_CUR);
 
423
                                break;
 
424
 
 
425
                        case PGEN_ID:
 
426
                                load_gen(subchunk.size, sf, fd,
 
427
                                         &sf->nrpgens, &sf->presetgen);
 
428
                                break;
 
429
 
 
430
                        case INST_ID:
 
431
                                load_inst_header(subchunk.size, sf, fd);
 
432
                                break;
 
433
 
 
434
                        case IBAG_ID:
 
435
                                load_bag(subchunk.size, sf, fd,
 
436
                                         &sf->nribags, &sf->instbag);
 
437
                                break;
 
438
 
 
439
                        case IMOD_ID: /* ingored */
 
440
                                fseek(fd, subchunk.size, SEEK_CUR);
 
441
                                break;
 
442
 
 
443
                        case IGEN_ID:
 
444
                                load_gen(subchunk.size, sf, fd,
 
445
                                         &sf->nrigens, &sf->instgen);
 
446
                                break;
 
447
                                
 
448
                        case SHDR_ID:
 
449
                                load_sample_info(subchunk.size, sf, fd);
 
450
                                break;
 
451
 
 
452
                        default:
 
453
                                fprintf(stderr, "unknown id\n");
 
454
                                fseek(fd, subchunk.size, SEEK_CUR);
 
455
                                break;
 
456
                        }
 
457
                        READCHUNK(&subchunk, fd);
 
458
                        if (feof(fd)) {
 
459
                                debugid("file", "EOF");
 
460
                                return;
 
461
                        }
 
462
                }
 
463
                fseek(fd, -8, SEEK_CUR); /* rewind */
 
464
                break;
 
465
        }
 
466
}
 
467