1 //=============================================================================
2 //  MuseScore
3 //  Linux Music Score Editor
4 //  $Id:$
5 //
6 //  Copyright (C) 2010 Werner Schweer and others
7 //
8 //  This program is free software; you can redistribute it and/or modify
9 //  it under the terms of the GNU General Public License version 2.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 //=============================================================================
20 
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 #include <vorbis/vorbisenc.h>
27 #include <vorbis/codec.h>
28 #include <vorbis/vorbisfile.h>
29 
30 #include "sfont.h"
31 #include "time.h"
32 
33 #ifndef SFTOOLS_NOXML
34 #include "xml.h"
35 #include <sndfile.h>
36 #endif
37 
38 #include <QtCore/QFile>
39 
40 using namespace SfTools;
41 
42 // #define DEBUG
43 
44 #define BE_SHORT(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
45 #ifdef __i486__
46 #define BE_LONG(x) \
47      ({ int __value; \
48         asm ("bswap %1; movl %1,%0" : "=g" (__value) : "r" (x)); \
49        __value; })
50 #else
51 #define BE_LONG(x) ((((x)&0xFF)<<24) | \
52               (((x)&0xFF00)<<8) | \
53               (((x)&0xFF0000)>>8) | \
54               (((x)>>24)&0xFF))
55 #endif
56 
57 #define FOURCC(a, b, c, d) a << 24 | b << 16 | c << 8 | d
58 
59 #define BLOCK_SIZE 1024
60 
61 static const bool writeCompressed = true;
62 
63 //---------------------------------------------------------
64 //   Sample
65 //---------------------------------------------------------
66 
Sample()67 Sample::Sample()
68       {
69       name = nullptr;
70       start = 0;
71       end = 0;
72       loopstart = 0;
73       loopend = 0;
74       samplerate = 0;
75       origpitch = 0;
76       pitchadj = 0;
77       sampleLink = 0;
78       sampletype = 0;
79       }
80 
~Sample()81 Sample::~Sample()
82       {
83       free(name);
84       }
85 
86 //---------------------------------------------------------
87 //   Instrument
88 //---------------------------------------------------------
89 
Instrument()90 Instrument::Instrument()
91       {
92       name = nullptr;
93       }
94 
~Instrument()95 Instrument::~Instrument()
96       {
97       free(name);
98       }
99 
100 //---------------------------------------------------------
101 //   SoundFont
102 //---------------------------------------------------------
103 
SoundFont(const QString & s)104 SoundFont::SoundFont(const QString& s)
105       {
106       path      = s;
107       engine    = nullptr;
108       name      = nullptr;
109       date      = nullptr;
110       comment   = nullptr;
111       tools     = nullptr;
112       creator   = nullptr;
113       product   = nullptr;
114       copyright = nullptr;
115       irom      = nullptr;
116       version.major = 0;
117       version.minor = 0;
118       iver.major = 0;
119       iver.minor = 0;
120       _smallSf   = false;
121       }
122 
~SoundFont()123 SoundFont::~SoundFont()
124       {
125       free(engine);
126       free(name);
127       free(date);
128       free(comment);
129       free(tools);
130       free(creator);
131       free(product);
132       free(copyright);
133       free(irom);
134       }
135 
136 //---------------------------------------------------------
137 //   read
138 //---------------------------------------------------------
139 
read()140 bool SoundFont::read()
141       {
142       file = new QFile(path);
143       if (!file->open(QIODevice::ReadOnly)) {
144             fprintf(stderr, "cannot open <%s>\n", qPrintable(path));
145             delete file;
146             return false;
147             }
148       try {
149             int len = readFourcc("RIFF");
150             readSignature("sfbk");
151             len -= 4;
152             while (len) {
153                   int len2 = readFourcc("LIST");
154                   len -= (len2 + 8);
155                   char fourcc[5];
156                   fourcc[0] = 0;
157                   readSignature(fourcc);
158                   fourcc[4] = 0;
159                   len2 -= 4;
160                   while (len2) {
161                         fourcc[0] = 0;
162                         int len3 = readFourcc(fourcc);
163                         fourcc[4] = 0;
164                         len2 -= (len3 + 8);
165                         readSection(fourcc, len3);
166                         }
167                   }
168             }
169       catch (QString s) {
170             printf("read sf file failed: %s\n", qPrintable(s));
171             delete file;
172             return false;
173             }
174       delete file;
175       return true;
176       }
177 
178 //---------------------------------------------------------
179 //   skip
180 //---------------------------------------------------------
181 
skip(int n)182 void SoundFont::skip(int n)
183       {
184       qint64 pos = file->pos();
185       if (!file->seek(pos + n))
186             throw(QString("unexpected end of file\n"));
187       }
188 
189 //---------------------------------------------------------
190 //   readFourcc
191 //---------------------------------------------------------
192 
readFourcc(char * signature)193 int SoundFont::readFourcc(char* signature)
194       {
195       readSignature(signature);
196       return readDword();
197       }
198 
readFourcc(const char * signature)199 int SoundFont::readFourcc(const char* signature)
200       {
201       readSignature(signature);
202       return readDword();
203       }
204 
205 //---------------------------------------------------------
206 //   readSignature
207 //---------------------------------------------------------
208 
readSignature(const char * signature)209 void SoundFont::readSignature(const char* signature)
210       {
211       char fourcc[4];
212       readSignature(fourcc);
213       if (memcmp(fourcc, signature, 4) != 0)
214             throw(QString("fourcc <%1> expected").arg(signature));
215       }
216 
readSignature(char * signature)217 void SoundFont::readSignature(char* signature)
218       {
219       if (file->read(signature, 4) != 4)
220             throw(QString("unexpected end of file\n"));
221       }
222 
223 //---------------------------------------------------------
224 //   readDword
225 //---------------------------------------------------------
226 
readDword()227 unsigned SoundFont::readDword()
228       {
229       unsigned format;
230       if (file->read((char*)&format, 4) != 4)
231             throw(QString("unexpected end of file\n"));
232       if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
233             return BE_LONG(format);
234       else
235         return format;
236       }
237 
238 //---------------------------------------------------------
239 //   writeDword
240 //---------------------------------------------------------
241 
writeDword(int val)242 void SoundFont::writeDword(int val)
243       {
244       if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
245             val = BE_LONG(val);
246       write((char*)&val, 4);
247       }
248 
249 //---------------------------------------------------------
250 //   writeWord
251 //---------------------------------------------------------
252 
writeWord(unsigned short int val)253 void SoundFont::writeWord(unsigned short int val)
254       {
255       if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
256             val = BE_SHORT(val);
257       write((char*)&val, 2);
258       }
259 
260 //---------------------------------------------------------
261 //   writeByte
262 //---------------------------------------------------------
263 
writeByte(unsigned char val)264 void SoundFont::writeByte(unsigned char val)
265       {
266       write((char*)&val, 1);
267       }
268 
269 //---------------------------------------------------------
270 //   writeChar
271 //---------------------------------------------------------
272 
writeChar(char val)273 void SoundFont::writeChar(char val)
274       {
275       write((char*)&val, 1);
276       }
277 
278 //---------------------------------------------------------
279 //   writeShort
280 //---------------------------------------------------------
281 
writeShort(short val)282 void SoundFont::writeShort(short val)
283       {
284       if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
285             val = BE_SHORT(val);
286       write((char*)&val, 2);
287       }
288 
289 //---------------------------------------------------------
290 //   readWord
291 //---------------------------------------------------------
292 
readWord()293 int SoundFont::readWord()
294       {
295       unsigned short format;
296       if (file->read((char*)&format, 2) != 2)
297             throw(QString("unexpected end of file\n"));
298       if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
299             return BE_SHORT(format);
300       else
301         return format;
302       }
303 
304 //---------------------------------------------------------
305 //   readShort
306 //---------------------------------------------------------
307 
readShort()308 int SoundFont::readShort()
309       {
310       short format;
311       if (file->read((char*)&format, 2) != 2)
312             throw(QString("unexpected end of file\n"));
313       if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
314             return BE_SHORT(format);
315       else
316         return format;
317       }
318 
319 //---------------------------------------------------------
320 //   readByte
321 //---------------------------------------------------------
322 
readByte()323 int SoundFont::readByte()
324       {
325       uchar val;
326       if (file->read((char*)&val, 1) != 1)
327             throw(QString("unexpected end of file\n"));
328       return val;
329       }
330 
331 //---------------------------------------------------------
332 //   readChar
333 //---------------------------------------------------------
334 
readChar()335 int SoundFont::readChar()
336       {
337       char val;
338       if (file->read(&val, 1) != 1)
339             throw(QString("unexpected end of file\n"));
340       return val;
341       }
342 
343 //---------------------------------------------------------
344 //   readVersion
345 //---------------------------------------------------------
346 
readVersion(sfVersionTag * v)347 void SoundFont::readVersion(sfVersionTag * v)
348       {
349       unsigned char data[4];
350       if (file->read((char*)data, 4) != 4)
351             throw(QString("unexpected end of file\n"));
352       v->major = data[0] + (data[1] << 8);
353       v->minor = data[2] + (data[3] << 8);
354       }
355 
356 //---------------------------------------------------------
357 //   readString
358 //---------------------------------------------------------
359 
readString(int n)360 char* SoundFont::readString(int n)
361       {
362       char data[2500];
363       if (file->read((char*)data, n) != n)
364             throw(QString("unexpected end of file\n"));
365       if (data[n-1] != 0)
366             data[n] = 0;
367       return strdup(data);
368       }
369 
370 //---------------------------------------------------------
371 //   readSection
372 //---------------------------------------------------------
373 
readSection(const char * fourcc,int len)374 void SoundFont::readSection(const char* fourcc, int len)
375       {
376       printf("readSection <%s> len %d\n", fourcc, len);
377 
378       switch(FOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3])) {
379             case FOURCC('i', 'f', 'i', 'l'):    // version
380                   readVersion(&version);
381                   break;
382             case FOURCC('I','N','A','M'):       // sound font name
383                   name = readString(len);
384                   break;
385             case FOURCC('i','s','n','g'):       // target render engine
386                   engine = readString(len);
387                   break;
388             case FOURCC('I','P','R','D'):       // product for which the bank was intended
389                   product = readString(len);
390                   break;
391             case FOURCC('I','E','N','G'): // sound designers and engineers for the bank
392                   creator = readString(len);
393                   break;
394             case FOURCC('I','S','F','T'): // SoundFont tools used to create and alter the bank
395                   tools = readString(len);
396                   break;
397             case FOURCC('I','C','R','D'): // date of creation of the bank
398                   date = readString(len);
399                   break;
400             case FOURCC('I','C','M','T'): // comments on the bank
401                   comment = readString(len);
402                   break;
403             case FOURCC('I','C','O','P'): // copyright message
404                   copyright = readString(len);
405                   break;
406             case FOURCC('s','m','p','l'): // the digital audio samples
407                   samplePos = file->pos();
408                   sampleLen = len;
409                   skip(len);
410                   break;
411             case FOURCC('s','m','2','4'): // audio samples (24-bit part)
412                   skip(len); // Just skip it
413                   break;
414             case FOURCC('p','h','d','r'): // preset headers
415                   readPhdr(len);
416                   break;
417             case FOURCC('p','b','a','g'): // preset index list
418                   readBag(len, &pZones);
419                   break;
420             case FOURCC('p','m','o','d'): // preset modulator list
421                   readMod(len, &pZones);
422                   break;
423             case FOURCC('p','g','e','n'): // preset generator list
424                   readGen(len, &pZones);
425                   break;
426             case FOURCC('i','n','s','t'): // instrument names and indices
427                   readInst(len);
428                   break;
429             case FOURCC('i','b','a','g'): // instrument index list
430                   readBag(len, &iZones);
431                   break;
432             case FOURCC('i','m','o','d'): // instrument modulator list
433                   readMod(len, &iZones);
434                   break;
435             case FOURCC('i','g','e','n'): // instrument generator list
436                   readGen(len, &iZones);
437                   break;
438             case FOURCC('s','h','d','r'): // sample headers
439                   readShdr(len);
440                   break;
441             case FOURCC('i', 'r', 'o', 'm'):    // sample rom
442                   irom = readString(len);
443                   break;
444             case FOURCC('i', 'v', 'e', 'r'):    // sample rom version
445                   readVersion(&iver);
446                   break;
447             default:
448                   skip(len);
449                   throw(QString("unknown fourcc <%1>").arg(fourcc));
450             }
451       }
452 
453 //---------------------------------------------------------
454 //   readPhdr
455 //---------------------------------------------------------
456 
readPhdr(int len)457 void SoundFont::readPhdr(int len)
458       {
459       if (len < (38 * 2))
460             throw(QString("phdr too short"));
461       if (len % 38)
462             throw(QString("phdr not a multiple of 38"));
463       int n = len / 38;
464       if (n <= 1) {
465             printf("no presets\n");
466             skip(len);
467             return;
468             }
469       int index1 = 0, index2;
470       for (int i = 0; i < n; ++i) {
471             Preset* preset       = new Preset;
472             preset->name         = readString(20);
473             preset->preset       = readWord();
474             preset->bank         = readWord();
475             index2               = readWord();
476             preset->library      = readDword();
477             preset->genre        = readDword();
478             preset->morphology   = readDword();
479             if (index2 < index1)
480                   throw("preset header indices not monotonic");
481             if (i > 0) {
482                   int n = index2 - index1;
483                   while (n--) {
484                         Zone* z = new Zone;
485                         presets.back()->zones.append(z);
486                         pZones.append(z);
487                         }
488                   }
489             index1 = index2;
490             presets.append(preset);
491             }
492       presets.takeLast();
493       }
494 
495 //---------------------------------------------------------
496 //   readBag
497 //---------------------------------------------------------
498 
readBag(int len,QList<Zone * > * zones)499 void SoundFont::readBag(int len, QList<Zone*>* zones)
500       {
501       if (len % 4)
502             throw(QString("bag size not a multiple of 4"));
503       int gIndex2, mIndex2;
504       int gIndex1 = readWord();
505       int mIndex1 = readWord();
506       len -= 4;
507       foreach(Zone* zone, *zones) {
508             gIndex2 = readWord();
509             mIndex2 = readWord();
510             len -= 4;
511             if (len < 0)
512                   throw(QString("bag size too small"));
513             if (gIndex2 < gIndex1)
514                   throw("generator indices not monotonic");
515             if (mIndex2 < mIndex1)
516                   throw("modulator indices not monotonic");
517             int n = mIndex2 - mIndex1;
518             while (n--)
519                   zone->modulators.append(new ModulatorList);
520             n = gIndex2 - gIndex1;
521             while (n--)
522                   zone->generators.append(new GeneratorList);
523             gIndex1 = gIndex2;
524             mIndex1 = mIndex2;
525             }
526       }
527 
528 //---------------------------------------------------------
529 //   readMod
530 //---------------------------------------------------------
531 
readMod(int size,QList<Zone * > * zones)532 void SoundFont::readMod(int size, QList<Zone*>* zones)
533       {
534       foreach(Zone* zone, *zones) {
535             foreach(ModulatorList* m, zone->modulators) {
536                   size -= 10;
537                   if (size < 0)
538                         throw(QString("pmod size mismatch"));
539                   m->src           = static_cast<Modulator>(readWord());
540                   m->dst           = static_cast<Generator>(readWord());
541                   m->amount        = readShort();
542                   m->amtSrc        = static_cast<Modulator>(readWord());
543                   m->transform     = static_cast<Transform>(readWord());
544                   }
545             }
546       if (size != 10)
547             throw(QString("modulator list size mismatch"));
548       skip(10);
549       }
550 
551 //---------------------------------------------------------
552 //   readGen
553 //---------------------------------------------------------
554 
readGen(int size,QList<Zone * > * zones)555 void SoundFont::readGen(int size, QList<Zone*>* zones)
556       {
557       if (size % 4)
558             throw(QString("bad generator list size"));
559       foreach (Zone* zone, *zones) {
560             size -= (zone->generators.size() * 4);
561             if (size < 0)
562                   break;
563 
564             foreach (GeneratorList* gen, zone->generators) {
565                   gen->gen = static_cast<Generator>(readWord());
566                   if (gen->gen == Gen_KeyRange || gen->gen == Gen_VelRange) {
567                         gen->amount.lo = readByte();
568                         gen->amount.hi = readByte();
569                         }
570                   else if (gen->gen == Gen_Instrument)
571                         gen->amount.uword = readWord();
572                   else
573                         gen->amount.sword = readWord();
574                   }
575             }
576       if (size != 4)
577             throw(QString("generator list size mismatch %1 != 4").arg(size));
578       skip(size);
579       }
580 
581 //---------------------------------------------------------
582 //   readInst
583 //---------------------------------------------------------
584 
readInst(int size)585 void SoundFont::readInst(int size)
586       {
587       int n = size / 22;
588       int index1 = 0, index2;
589       for (int i = 0; i < n; ++i) {
590             Instrument* instrument = new Instrument;
591             instrument->name = readString(20);
592             index2           = readWord();
593             if (index2 < index1)
594                   throw("instrument header indices not monotonic");
595             if (i > 0) {
596                   int n = index2 - index1;
597                   while (n--) {
598                         Zone* z = new Zone;
599                         instruments.back()->zones.append(z);
600                         iZones.append(z);
601                         }
602                   }
603             index1 = index2;
604             instruments.append(instrument);
605             }
606       instruments.takeLast();
607       }
608 
609 //---------------------------------------------------------
610 //   readShdr
611 //---------------------------------------------------------
612 
readShdr(int size)613 void SoundFont::readShdr(int size)
614       {
615       int n = size / 46;
616       for (int i = 0; i < n-1; ++i) {
617             Sample* s = new Sample;
618             s->name       = readString(20);
619             s->start      = readDword();
620             s->end        = readDword();
621             s->loopstart  = readDword();
622             s->loopend    = readDword();
623             s->samplerate = readDword();
624             s->origpitch  = readByte();
625             s->pitchadj   = readChar();
626             s->sampleLink = readWord();
627             s->sampletype = readWord();
628 
629 // printf("readFontHeader %d %d   %d %d\n", s->start, s->end, s->loopstart, s->loopend);
630             samples.append(s);
631             }
632       skip(46);   // trailing record
633       }
634 
635 //---------------------------------------------------------
636 //   write
637 //---------------------------------------------------------
638 
write()639 bool SoundFont::write()
640       {
641       qint64 riffLenPos;
642       qint64 listLenPos;
643       try {
644             file->write("RIFF", 4);
645             riffLenPos = file->pos();
646             writeDword(0);
647             file->write("sfbk", 4);
648 
649             file->write("LIST", 4);
650             listLenPos = file->pos();
651             writeDword(0);
652             file->write("INFO", 4);
653 
654             writeIfil();
655             if (name)
656                   writeStringSection("INAM", name);
657             if (engine)
658                   writeStringSection("isng", engine);
659             if (product)
660                   writeStringSection("IPRD", product);
661             if (creator)
662                   writeStringSection("IENG", creator);
663             if (tools)
664                   writeStringSection("ISFT", tools);
665             if (date)
666                   writeStringSection("ICRD", date);
667             if (comment)
668                   writeStringSection("ICMT", comment);
669             if (copyright)
670                   writeStringSection("ICOP", copyright);
671             if (irom)
672                   writeStringSection("irom", irom);
673             writeIver();
674 
675             qint64 pos = file->pos();
676             file->seek(listLenPos);
677             writeDword(pos - listLenPos - 4);
678             file->seek(pos);
679 
680             file->write("LIST", 4);
681             listLenPos = file->pos();
682             writeDword(0);
683             file->write("sdta", 4);
684             writeSmpl();
685             pos = file->pos();
686             file->seek(listLenPos);
687             writeDword(pos - listLenPos - 4);
688             file->seek(pos);
689 
690             file->write("LIST", 4);
691             listLenPos = file->pos();
692             writeDword(0);
693             file->write("pdta", 4);
694 
695             writePhdr();
696             writeBag("pbag", &pZones);
697             writeMod("pmod", &pZones);
698             writeGen("pgen", &pZones);
699             writeInst();
700             writeBag("ibag", &iZones);
701             writeMod("imod", &iZones);
702             writeGen("igen", &iZones);
703             writeShdr();
704 
705             pos = file->pos();
706             file->seek(listLenPos);
707             writeDword(pos - listLenPos - 4);
708             file->seek(pos);
709 
710             qint64 endPos = file->pos();
711             file->seek(riffLenPos);
712             writeDword(endPos - riffLenPos - 4);
713             }
714       catch (QString s) {
715             printf("write sf file failed: %s\n", qPrintable(s));
716             return false;
717             }
718       return true;
719       }
720 
compress(QFile * f,double oggQuality,double oggAmp,qint64 oggSerial)721 bool SoundFont::compress(QFile* f, double oggQuality, double oggAmp, qint64 oggSerial)
722       {
723       file = f;
724       _compress = true;
725       _oggQuality = oggQuality;
726       _oggAmp = oggAmp;
727       _oggSerial = oggSerial;
728 
729       return write();
730       }
731 
uncompress(QFile * f)732 bool SoundFont::uncompress(QFile* f)
733       {
734       file = f;
735       _compress = false;
736       return write();
737       }
738 
739 //---------------------------------------------------------
740 //   write
741 //---------------------------------------------------------
742 
write(const char * p,int n)743 void SoundFont::write(const char* p, int n)
744       {
745       if (file->write(p, n) != n)
746             throw(QString("write error"));
747       }
748 
749 //---------------------------------------------------------
750 //   writeStringSection
751 //---------------------------------------------------------
752 
writeStringSection(const char * fourcc,char * s)753 void SoundFont::writeStringSection(const char* fourcc, char* s)
754       {
755       write(fourcc, 4);
756       int nn = strlen(s) + 1;
757       int n = ((nn + 1) / 2) * 2;
758       writeDword(n);
759       write(s, nn);
760       if (n - nn) {
761             char c = 0;
762             write(&c, 1);
763             }
764       }
765 
766 //---------------------------------------------------------
767 //   writeIfil
768 //---------------------------------------------------------
769 
writeIfil()770 void SoundFont::writeIfil()
771       {
772       write("ifil", 4);
773       writeDword(4);
774       unsigned char data[4];
775       if (_compress) {
776             version.major = 3;
777             version.minor = 0;
778       } else {
779             version.major = 2;
780             version.minor = 1;
781       }
782       data[0] = version.major;
783       data[1] = version.major >> 8;
784       data[2] = version.minor;
785       data[3] = version.minor >> 8;
786       write((char*)data, 4);
787       }
788 
789 //---------------------------------------------------------
790 //   writeIVer
791 //---------------------------------------------------------
792 
writeIver()793 void SoundFont::writeIver()
794       {
795       write("iver", 4);
796       writeDword(4);
797       unsigned char data[4];
798       data[0] = iver.major;
799       data[1] = iver.major >> 8;
800       data[2] = iver.minor;
801       data[3] = iver.minor >> 8;
802       write((char*)data, 4);
803       }
804 
805 //---------------------------------------------------------
806 //   writeSmpl
807 //---------------------------------------------------------
808 
writeSmpl()809 void SoundFont::writeSmpl()
810       {
811       write("smpl", 4);
812 
813       qint64 pos = file->pos();
814       writeDword(0);
815       int currentSamplePos = 0;
816       if (_compress) {
817             // Compress wave data
818             foreach(Sample* s, samples) {
819                   // Loop start and end are now based on the beginning of each sample
820                   s->loopstart -= s->start;
821                   s->loopend -= s->start;
822 
823                   // OGG flag added
824                   s->sampletype |= 0x10;
825                   int len  = writeCompressedSample(s); // In byte
826                   s->start = currentSamplePos;
827                   currentSamplePos += len;
828                   s->end = currentSamplePos;
829                   }
830             }
831       else {
832             // Uncompress from OGG data
833             foreach(Sample* s, samples) {
834                   // OGG flag is removed
835                   s->sampletype &= ~0x10;
836                   int len = writeUncompressedSample(s) / 2; // In sample data points (16 bits)
837                   s->start = currentSamplePos;
838                   currentSamplePos += len;
839                   s->end = currentSamplePos;
840 
841                   // Loop start and end are now based on the beginning of the section "smpl"
842                   s->loopstart += s->start;
843                   s->loopend   += s->start;
844                   }
845             }
846       qint64 npos = file->pos();
847       file->seek(pos);
848       writeDword(npos - pos - 4);
849       file->seek(npos);
850       }
851 
852 //---------------------------------------------------------
853 //   writePhdr
854 //---------------------------------------------------------
855 
writePhdr()856 void SoundFont::writePhdr()
857       {
858       write("phdr", 4);
859       int n = presets.size();
860       writeDword((n + 1) * 38);
861       int zoneIdx = 0;
862       foreach(const Preset* p, presets) {
863             writePreset(zoneIdx, p);
864             zoneIdx += p->zones.size();
865             }
866       Preset p;
867       writePreset(zoneIdx, &p);
868       }
869 
870 //---------------------------------------------------------
871 //   writePreset
872 //---------------------------------------------------------
873 
writePreset(int zoneIdx,const Preset * preset)874 void SoundFont::writePreset(int zoneIdx, const Preset* preset)
875       {
876       char name[20];
877       memset(name, 0, 20);
878       if (preset->name)
879             memcpy(name, preset->name, strlen(preset->name));
880       write(name, 20);
881       writeWord(preset->preset);
882       writeWord(preset->bank);
883       writeWord(zoneIdx);
884       writeDword(preset->library);
885       writeDword(preset->genre);
886       writeDword(preset->morphology);
887       }
888 
889 //---------------------------------------------------------
890 //   writeBag
891 //---------------------------------------------------------
892 
writeBag(const char * fourcc,QList<Zone * > * zones)893 void SoundFont::writeBag(const char* fourcc, QList<Zone*>* zones)
894       {
895       write(fourcc, 4);
896       int n = zones->size();
897       writeDword((n + 1) * 4);
898       int gIndex = 0;
899       int pIndex = 0;
900       foreach(const Zone* z, *zones) {
901             writeWord(gIndex);
902             writeWord(pIndex);
903             gIndex += z->generators.size();
904             pIndex += z->modulators.size();
905             }
906       writeWord(gIndex);
907       writeWord(pIndex);
908       }
909 
910 //---------------------------------------------------------
911 //   writeMod
912 //---------------------------------------------------------
913 
writeMod(const char * fourcc,const QList<Zone * > * zones)914 void SoundFont::writeMod(const char* fourcc, const QList<Zone*>* zones)
915       {
916       write(fourcc, 4);
917       int n = 0;
918       foreach(const Zone* z, *zones)
919             n += z->modulators.size();
920       writeDword((n + 1) * 10);
921 
922       foreach(const Zone* zone, *zones) {
923             foreach(const ModulatorList* m, zone->modulators)
924                   writeModulator(m);
925             }
926       ModulatorList mod;
927       memset(&mod, 0, sizeof(mod));
928       writeModulator(&mod);
929       }
930 
931 //---------------------------------------------------------
932 //   writeModulator
933 //---------------------------------------------------------
934 
writeModulator(const ModulatorList * m)935 void SoundFont::writeModulator(const ModulatorList* m)
936       {
937       writeWord(m->src);
938       writeWord(m->dst);
939       writeShort(m->amount);
940       writeWord(m->amtSrc);
941       writeWord(m->transform);
942       }
943 
944 //---------------------------------------------------------
945 //   writeGen
946 //---------------------------------------------------------
947 
writeGen(const char * fourcc,QList<Zone * > * zones)948 void SoundFont::writeGen(const char* fourcc, QList<Zone*>* zones)
949       {
950       write(fourcc, 4);
951       int n = 0;
952       foreach(const Zone* z, *zones)
953             n += z->generators.size();
954       writeDword((n + 1) * 4);
955 
956       foreach(const Zone* zone, *zones) {
957             foreach(const GeneratorList* g, zone->generators)
958                   writeGenerator(g);
959             }
960       GeneratorList gen;
961       memset(&gen, 0, sizeof(gen));
962       writeGenerator(&gen);
963       }
964 
965 //---------------------------------------------------------
966 //   writeGenerator
967 //---------------------------------------------------------
968 
writeGenerator(const GeneratorList * g)969 void SoundFont::writeGenerator(const GeneratorList* g)
970       {
971       writeWord(g->gen);
972       if (g->gen == Gen_KeyRange || g->gen == Gen_VelRange) {
973             writeByte(g->amount.lo);
974             writeByte(g->amount.hi);
975             }
976       else if (g->gen == Gen_Instrument)
977             writeWord(g->amount.uword);
978       else
979             writeWord(g->amount.sword);
980       }
981 
982 //---------------------------------------------------------
983 //   writeInst
984 //---------------------------------------------------------
985 
writeInst()986 void SoundFont::writeInst()
987       {
988       write("inst", 4);
989       int n = instruments.size();
990       writeDword((n + 1) * 22);
991       int zoneIdx = 0;
992       foreach(const Instrument* p, instruments) {
993             writeInstrument(zoneIdx, p);
994             zoneIdx += p->zones.size();
995             }
996       Instrument p;
997       writeInstrument(zoneIdx, &p);
998       }
999 
1000 //---------------------------------------------------------
1001 //   writeInstrument
1002 //---------------------------------------------------------
1003 
writeInstrument(int zoneIdx,const Instrument * instrument)1004 void SoundFont::writeInstrument(int zoneIdx, const Instrument* instrument)
1005       {
1006       char name[20];
1007       memset(name, 0, 20);
1008       if (instrument->name)
1009             memcpy(name, instrument->name, strlen(instrument->name));
1010       write(name, 20);
1011       writeWord(zoneIdx);
1012       }
1013 
1014 //---------------------------------------------------------
1015 //   writeShdr
1016 //---------------------------------------------------------
1017 
writeShdr()1018 void SoundFont::writeShdr()
1019       {
1020       write("shdr", 4);
1021       writeDword(46 * (samples.size() + 1));
1022       foreach(const Sample* s, samples)
1023             writeSample(s);
1024       Sample s;
1025       writeSample(&s);
1026       }
1027 
1028 //---------------------------------------------------------
1029 //   writeSample
1030 //---------------------------------------------------------
1031 
writeSample(const Sample * s)1032 void SoundFont::writeSample(const Sample* s)
1033       {
1034       char name[20];
1035       memset(name, 0, 20);
1036       if (s->name)
1037             memcpy(name, s->name, strlen(s->name));
1038       write(name, 20);
1039       writeDword(s->start);
1040       writeDword(s->end);
1041       writeDword(s->loopstart);
1042       writeDword(s->loopend);
1043       writeDword(s->samplerate);
1044       writeByte(s->origpitch);
1045       writeChar(s->pitchadj);
1046       writeWord(s->sampleLink);
1047       writeWord(s->sampletype);
1048       }
1049 
1050 //---------------------------------------------------------
1051 //   writeCompressedSample
1052 //---------------------------------------------------------
1053 
writeCompressedSample(Sample * s)1054 int SoundFont::writeCompressedSample(Sample* s)
1055       {
1056       QFile f(path);
1057       if (!f.open(QIODevice::ReadOnly)) {
1058             fprintf(stderr, "cannot open <%s>\n", qPrintable(f.fileName()));
1059             return 0;
1060             }
1061       f.seek(samplePos + s->start * sizeof(short));
1062       int samples = s->end - s->start;
1063       short * ibuffer = new short[samples];
1064       f.read((char*)ibuffer, samples * sizeof(short));
1065       f.close();
1066 
1067       ogg_stream_state os;
1068       ogg_page         og;
1069       ogg_packet       op;
1070       vorbis_info      vi;
1071       vorbis_dsp_state vd;
1072       vorbis_block     vb;
1073       vorbis_comment   vc;
1074 
1075       vorbis_info_init(&vi);
1076       int ret = vorbis_encode_init_vbr(&vi, 1, s->samplerate, _oggQuality);
1077       if (ret) {
1078             printf("vorbis init failed\n");
1079             delete [] ibuffer;
1080             return false;
1081             }
1082       vorbis_comment_init(&vc);
1083       vorbis_analysis_init(&vd, &vi);
1084       vorbis_block_init(&vd, &vb);
1085       srand(time(nullptr));
1086       ogg_stream_init(&os, _oggSerial == std::numeric_limits<qint64>::max() ? rand() : (int)_oggSerial);
1087 
1088       ogg_packet header;
1089       ogg_packet header_comm;
1090       ogg_packet header_code;
1091 
1092       // Keep a track of the attenuation used before the compression
1093       vorbis_comment_add(&vc, QString("AMP=%1\0").arg(_oggAmp).toStdString().c_str());
1094 
1095       vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code);
1096       ogg_stream_packetin(&os, &header);
1097       ogg_stream_packetin(&os, &header_comm);
1098       ogg_stream_packetin(&os, &header_code);
1099 
1100       char* obuf = new char[1048576]; // 1024 * 1024
1101       char* p = obuf;
1102 
1103       for (;;) {
1104             int result = ogg_stream_flush(&os, &og);
1105             if (result == 0)
1106                   break;
1107             memcpy(p, og.header, og.header_len);
1108             p += og.header_len;
1109             memcpy(p, og.body, og.body_len);
1110             p += og.body_len;
1111             }
1112 
1113       long i;
1114       int page = 0;
1115       double linearAmp = pow(10.0, _oggAmp / 20.0);
1116       for(;;) {
1117             int bufflength = qMin(BLOCK_SIZE, samples-page*BLOCK_SIZE);
1118             float **buffer = vorbis_analysis_buffer(&vd, bufflength);
1119             int j = 0;
1120             int max = qMin((page+1)*BLOCK_SIZE, samples);
1121             for (i = page * BLOCK_SIZE; i < max ; i++) {
1122                   buffer[0][j] = (ibuffer[i] / 32768.f) * linearAmp;
1123                   j++;
1124                   }
1125 
1126             vorbis_analysis_wrote(&vd, bufflength);
1127 
1128             while (vorbis_analysis_blockout(&vd, &vb) == 1) {
1129                   vorbis_analysis(&vb, 0);
1130                   vorbis_bitrate_addblock(&vb);
1131 
1132                   while (vorbis_bitrate_flushpacket(&vd, &op)) {
1133                         ogg_stream_packetin(&os, &op);
1134 
1135                         for(;;) {
1136                               int result = ogg_stream_pageout(&os, &og);
1137                               if (result == 0)
1138                                     break;
1139                               memcpy(p, og.header, og.header_len);
1140                               p += og.header_len;
1141                               memcpy(p, og.body, og.body_len);
1142                               p += og.body_len;
1143                               }
1144                         }
1145                   }
1146                   page++;
1147                   if ((max == samples) || !((samples-page*BLOCK_SIZE)>0))
1148                         break;
1149             }
1150 
1151       vorbis_analysis_wrote(&vd, 0);
1152 
1153       while (vorbis_analysis_blockout(&vd, &vb) == 1) {
1154             vorbis_analysis(&vb, 0);
1155             vorbis_bitrate_addblock(&vb);
1156 
1157             while (vorbis_bitrate_flushpacket(&vd, &op)) {
1158                   ogg_stream_packetin(&os, &op);
1159 
1160                   for(;;) {
1161                         int result = ogg_stream_pageout(&os, &og);
1162                         if (result == 0)
1163                               break;
1164                         memcpy(p, og.header, og.header_len);
1165                         p += og.header_len;
1166                         memcpy(p, og.body, og.body_len);
1167                         p += og.body_len;
1168                         }
1169                   }
1170             }
1171 
1172       ogg_stream_clear(&os);
1173       vorbis_block_clear(&vb);
1174       vorbis_dsp_clear(&vd);
1175       vorbis_comment_clear(&vc);
1176       vorbis_info_clear(&vi);
1177 
1178       int n = p - obuf;
1179       write(obuf, n);
1180 
1181       delete [] obuf;
1182       delete [] ibuffer;
1183       return n;
1184       }
1185 
1186 //---------------------------------------------------------
1187 //   writeCSample
1188 //---------------------------------------------------------
1189 
writeCSample(Sample * s,int idx)1190 bool SoundFont::writeCSample(Sample* s, int idx)
1191       {
1192       QFile fi(path);
1193       if (!fi.open(QIODevice::ReadOnly)) {
1194             fprintf(stderr, "cannot open <%s>\n", qPrintable(fi.fileName()));
1195             return false;
1196             }
1197       fi.seek(samplePos + s->start * sizeof(short));
1198       int samples = s->end - s->start;
1199       short * ibuffer = new short[samples];
1200       fi.read((char*)ibuffer, samples * sizeof(short));
1201       fi.close();
1202 
1203       fprintf(f, "static const short wave%d[] = {\n      ", idx);
1204       int n = 0;
1205       for (int row = 0;; ++row) {
1206             for (int col = 0; col < 16; ++col) {
1207                   if (n >= samples)
1208                         break;
1209                   if (col != 0)
1210                         fprintf(f, ", ");
1211                   fprintf(f, "%d", ibuffer[n]);
1212                   ++n;
1213                   }
1214             if (n >= samples)
1215                   break;
1216             fprintf(f, ",\n      ");
1217             }
1218       fprintf(f, "\n      };\n");
1219       delete [] ibuffer;
1220       return true;
1221       }
1222 
1223 //---------------------------------------------------------
1224 //   checkInstrument
1225 //---------------------------------------------------------
1226 
checkInstrument(QList<int> pnums,QList<Preset * > presets,int instrIdx)1227 static bool checkInstrument(QList<int> pnums, QList<Preset*> presets, int instrIdx)
1228       {
1229       foreach(int idx, pnums) {
1230             Preset* p = presets[idx];
1231             foreach(Zone* z, p->zones) {
1232                   foreach(GeneratorList* g, z->generators) {
1233                         if (g->gen == Gen_Instrument) {
1234                               if (instrIdx == g->amount.uword)
1235                                     return true;
1236                               }
1237                         }
1238                   }
1239             }
1240       return false;
1241       }
1242 
checkInstrument(QList<Preset * > presets,int instrIdx)1243 static bool checkInstrument(QList<Preset*> presets, int instrIdx) {
1244       for(int i = 0; i < presets.size(); i++) {
1245             Preset* p = presets[i];
1246             Zone* z = p->zones[0];
1247             foreach(GeneratorList* g, z->generators) {
1248                         if (g->gen == Gen_Instrument) {
1249                               if (instrIdx == g->amount.uword)
1250                                     return true;
1251                               }
1252                         }
1253             }
1254       return false;
1255       }
1256 
1257 //---------------------------------------------------------
1258 //   checkSample
1259 //---------------------------------------------------------
1260 
checkSample(QList<int> pnums,QList<Preset * > presets,QList<Instrument * > instruments,int sampleIdx)1261 static bool checkSample(QList<int> pnums, QList<Preset*> presets, QList<Instrument*> instruments,
1262    int sampleIdx)
1263       {
1264       int idx = 0;
1265       foreach(Instrument* instrument, instruments) {
1266             if (!checkInstrument(pnums, presets, idx)) {
1267                   ++idx;
1268                   continue;
1269                   }
1270             foreach(Zone* z, instrument->zones) {
1271                   QList<GeneratorList*> gl;
1272                   foreach(GeneratorList* g, z->generators) {
1273                         if (g->gen == Gen_SampleId) {
1274                               if (sampleIdx == g->amount.uword)
1275                                     return true;
1276                               }
1277                         }
1278                   }
1279             ++idx;
1280             }
1281       return false;
1282       }
1283 
1284 //---------------------------------------------------------
1285 //   checkSample
1286 //---------------------------------------------------------
1287 
checkSample(QList<Preset * > presets,QList<Instrument * > instruments,int sampleIdx)1288 static bool checkSample(QList<Preset*> presets, QList<Instrument*> instruments,
1289    int sampleIdx)
1290       {
1291       int idx = 0;
1292       foreach(Instrument* instrument, instruments) {
1293             if (!checkInstrument(presets, idx)) {
1294                   ++idx;
1295                   continue;
1296                   }
1297             foreach(Zone* z, instrument->zones) {
1298                   QList<GeneratorList*> gl;
1299                   foreach(GeneratorList* g, z->generators) {
1300                         if (g->gen == Gen_SampleId) {
1301                               if (sampleIdx == g->amount.uword)
1302                                     return true;
1303                               }
1304                         }
1305                   }
1306             ++idx;
1307             }
1308       return false;
1309       }
1310 
1311 
1312 //---------------------------------------------------------
1313 //   writeCode
1314 //---------------------------------------------------------
1315 
writeCode()1316 bool SoundFont::writeCode()
1317       {
1318       int segments = 8;
1319       int n        = samples.size() / segments;
1320       for (int i = 0; i < segments; ++i) {
1321             char buffer[16];
1322             sprintf(buffer, "sf%d.cpp", i + 1);
1323             f = fopen(buffer, "w+");
1324             fprintf(f, "//\n//      this is generated code, do not change\n//\n");
1325             fprintf(f, "#include \"sfont.h\"\n\n");
1326             fprintf(f, "namespace FluidS {\n\n");
1327 
1328             //
1329             // dump wave samples
1330             //
1331             int end;
1332             if (i+1 == segments)
1333                   end = samples.size();
1334             else
1335                   end = (i+1) * n;
1336             QList<int> sampleIdx;
1337             for (int idx = i * n; idx < end; ++idx) {
1338                   if (_smallSf && !checkSample(presets, instruments, idx))
1339                         continue;
1340                   Sample* s = samples[idx];
1341                   writeCSample(s, idx);
1342                   sampleIdx.append(idx);
1343                   }
1344 
1345             //
1346             // dump Sample[]
1347             //
1348             foreach(int idx, sampleIdx) {
1349                   Sample* s = samples[idx];
1350                   fprintf(f, "Sample sample%d(%d, %d, %d, %d, %d, %d, %d, %d, wave%d);\n",
1351                      idx,
1352                      0,
1353                      s->end       - (s->start + 1),
1354                      s->loopstart, //  - s->start,
1355                      s->loopend,   //  - s->start,
1356                      s->samplerate, s->origpitch, s->pitchadj, s->sampletype,
1357                      idx);
1358                   }
1359             fprintf(f, "} // end namespace\n");
1360             fclose(f);
1361             }
1362 
1363       f = fopen("sf.cpp", "w+");
1364       fprintf(f, "//\n//      this is generated code, do not change\n//\n");
1365       fprintf(f, "#include \"sfont.h\"\n\n");
1366       fprintf(f, "namespace FluidS {\n\n");
1367 
1368       fprintf(f, "extern Sample ");
1369       for (int i = 0; i < samples.size(); ++i) {
1370             if (i) {
1371                   if ((i % 8) == 0)
1372                         fprintf(f, ";\nextern Sample ");
1373                   else
1374                         fprintf(f, ", ");
1375                   }
1376             fprintf(f, "sample%d", i);
1377             }
1378       fprintf(f, ";\n");
1379 
1380       //
1381       // dump Instrument[]
1382       //
1383       int idx2;
1384       int idx = 0;
1385       foreach(Instrument* instrument, instruments) {
1386             if (_smallSf && !checkInstrument(presets, idx)) {
1387                   ++idx;
1388                   continue;
1389                   }
1390             int zones = instrument->zones.size();
1391             idx2 = 0;
1392             foreach(Zone* z, instrument->zones) {
1393                   int keyLo     = 0;
1394                   int keyHi     = 127;
1395                   int veloLo    = 0;
1396                   int veloHi    = 127;
1397                   int sampleIdx = -1;
1398 
1399                   QList<GeneratorList*> gl;
1400                   foreach(GeneratorList* g, z->generators) {
1401                         if (g->gen == Gen_KeyRange) {
1402                               keyLo = g->amount.lo;
1403                               keyHi = g->amount.hi;
1404                               }
1405                         else if (g->gen == Gen_VelRange) {
1406                               veloLo = g->amount.lo;
1407                               veloHi = g->amount.hi;
1408                               }
1409                         else if (g->gen == Gen_SampleId)
1410                               sampleIdx = g->amount.uword;
1411                         else
1412                               gl.append(g);
1413                         if (_smallSf && g->gen == Gen_Pan)
1414                               g->amount.uword = 0;
1415                         }
1416                   int idx3 = 0;
1417                   foreach(GeneratorList* g, gl) {
1418                         if ((idx3 % 8) == 0) {
1419                               if (idx3)
1420                                     fprintf(f, ";\n");
1421                               fprintf(f, "static Generator ");
1422                               }
1423                         else
1424                               fprintf(f, ", ");
1425                         fprintf(f, "ge_%d_%d_%d(%d, %d)",
1426                            idx, idx2, idx3, int(g->gen), g->amount.sword);
1427                         ++idx3;
1428                         }
1429                   fprintf(f, ";\n");
1430                   int n = gl.size();
1431                   if (n) {
1432                         fprintf(f, "static Generator* geList_%d_%d[%d] = {\n      ", idx, idx2, n);
1433                         for (int i = 0; i < n; ++i) {
1434                               if (i) {
1435                                     fprintf(f, ", ");
1436                                     if ((i % 8) == 0)
1437                                           fprintf(f, "\n      ");
1438                                     }
1439                               fprintf(f, "&ge_%d_%d_%d", idx, idx2, i);
1440                               }
1441                         fprintf(f, "\n      };\n");
1442                         }
1443                   if (sampleIdx == -1)
1444                         fprintf(f, "static IZone iz%d_%d(%d, %d, %d, %d, 0, 0, 0);\n", idx, idx2, keyLo, keyHi, veloLo, veloHi);
1445                   else if (n)
1446                         fprintf(f, "static IZone iz%d_%d(%d, %d, %d, %d, &sample%d, %d, geList_%d_%d);  // %s\n",
1447                            idx, idx2, keyLo, keyHi, veloLo, veloHi, sampleIdx, n, idx, idx2,
1448                            samples[sampleIdx]->name);
1449                   else
1450                         fprintf(f, "static IZone iz%d_%d(%d, %d, %d, %d, &sample%d, %d, 0);  // %s\n",
1451                            idx, idx2, keyLo, keyHi, veloLo, veloHi, sampleIdx, n,
1452                            samples[sampleIdx]->name);
1453 
1454                   ++idx2;
1455                   }
1456 
1457             fprintf(f, "static IZone* izones%d[%d] = {\n", idx, zones);
1458             idx2 = 0;
1459             for (int i = 0; i < zones; ++i)
1460                   fprintf(f, "      &iz%d_%d,\n", idx, idx2++);
1461             fprintf(f, "      };\n");
1462             fprintf(f, "static Instrument instr%d(0, %d, izones%d);\n\n", idx, zones, idx);
1463             ++idx;
1464             }
1465       //
1466       // dump Preset[]
1467       //
1468       idx = 0;
1469       foreach(Preset* p, presets) {
1470             idx2 = 0;
1471             int zones = p->zones.size();
1472             if (_smallSf)
1473                   zones = 1;
1474 
1475             foreach(Zone* z, p->zones) {
1476                   int keyLo    = 0;
1477                   int keyHi    = 127;
1478                   int veloLo   = 0;
1479                   int veloHi   = 127;
1480                   int instrIdx = -1;
1481 
1482                   foreach(GeneratorList* g, z->generators) {
1483                         if (g->gen == Gen_KeyRange) {
1484                               keyLo = g->amount.lo;
1485                               keyHi = g->amount.hi;
1486                               }
1487                         else if (g->gen == Gen_VelRange) {
1488                               veloLo = g->amount.lo;
1489                               veloHi = g->amount.hi;
1490                               }
1491                         else if (g->gen == Gen_Instrument)
1492                               instrIdx = g->amount.uword;
1493                         }
1494                   if (keyLo == 0
1495                      && keyHi == 127
1496                      && veloLo == 0
1497                      && veloHi == 127) {
1498                         if (instrIdx == -1)
1499                               fprintf(f, "static PZone pz%d_%d(0);\n", idx, idx2);
1500                         else
1501                               fprintf(f, "static PZone pz%d_%d(&instr%d);\n", idx, idx2, instrIdx);
1502                         }
1503                   else {
1504                         //abort();
1505 
1506                         if (instrIdx == -1)
1507                               fprintf(f, "static PZone pz%d_%d(%d, %d, %d, %d, 0);\n", idx, idx2, keyLo, keyHi, veloLo, veloHi);
1508                         else
1509                               fprintf(f, "static PZone pz%d_%d(%d, %d, %d, %d, &instr%d);\n", idx, idx2, keyLo, keyHi, veloLo, veloHi, instrIdx);
1510                         }
1511                   if (_smallSf)
1512                         break;
1513                   ++idx2;
1514                   }
1515             fprintf(f, "static PZone* pzones%d[%d] = {\n", idx, zones);
1516             idx2 = 0;
1517             for (int i = 0; i < zones; ++i) {
1518                   fprintf(f, "      &pz%d_%d,\n", idx, idx2);
1519                   ++idx2;
1520                   }
1521             fprintf(f, "      };\n");
1522 
1523             fprintf(f, "static Preset preset%d(%d, %d, 0, %d, pzones%d);  // %s\n\n",
1524                idx, p->preset, p->bank, zones, idx, p->name);
1525             ++idx;
1526             }
1527 
1528 
1529       fprintf(f, "static Preset* sfPresets[%d] = {\n", presets.size());
1530       for(int idx = 0; idx < presets.size(); ++idx)
1531             fprintf(f, "      &preset%d,   // %s\n", idx, presets[idx]->name);
1532       fprintf(f, "      };\n");
1533 
1534       fprintf(f, "static SFont _buildinSf(%d, sfPresets);\n", presets.size());
1535       fprintf(f, "SFont* createSf() { return &_buildinSf; }\n");
1536       fprintf(f, "} // end namespace\n");
1537       fclose(f);
1538       return true;
1539       }
1540 
1541 
1542 
1543 //---------------------------------------------------------
1544 //   writeCode
1545 //---------------------------------------------------------
1546 
writeCode(QList<int> pnums)1547 bool SoundFont::writeCode(QList<int> pnums)
1548       {
1549       printf("write code\n");
1550 
1551       int n = samples.size();
1552       f = fopen("sf.cpp", "w+");
1553       fprintf(f, "//\n//      this is generated code, do not change\n//\n");
1554       fprintf(f, "#include \"sfont.h\"\n\n");
1555       fprintf(f, "namespace FluidS {\n\n");
1556 
1557       //
1558       // dump wave samples
1559       //
1560       QList<int> sampleIdx;
1561       for (int idx = 0; idx < n; ++idx) {
1562             if (!checkSample(pnums, presets, instruments, idx))
1563                   continue;
1564             Sample* s = samples[idx];
1565             writeCSample(s, idx);
1566             sampleIdx.append(idx);
1567             }
1568 
1569       //
1570       // dump Sample[]
1571       //
1572       foreach(int idx, sampleIdx) {
1573             Sample* s = samples[idx];
1574             fprintf(f, "Sample sample%d(%d, %d, %d, %d, %d, %d, %d, %d, wave%d);\n",
1575                idx,
1576                0,                         // sample start
1577                s->end       - s->start,   // samples
1578                s->loopstart - s->start,
1579                s->loopend   - s->start,
1580                s->samplerate,
1581                s->origpitch, s->pitchadj, s->sampletype,
1582                idx);
1583             }
1584 
1585       //
1586       // dump Instrument[]
1587       //
1588       int idx2;
1589       int idx = 0;
1590       foreach(Instrument* instrument, instruments) {
1591             if (!checkInstrument(pnums, presets, idx)) {
1592                   ++idx;
1593                   continue;
1594                   }
1595             int zones = instrument->zones.size();
1596             idx2 = 0;
1597             foreach(Zone* z, instrument->zones) {
1598                   int keyLo     = 0;
1599                   int keyHi     = 127;
1600                   int veloLo    = 0;
1601                   int veloHi    = 127;
1602                   int sampleIdx = -1;
1603 
1604                   QList<GeneratorList*> gl;
1605 
1606                   foreach(GeneratorList* g, z->generators) {
1607                         if (g->gen == Gen_KeyRange) {
1608                               keyLo = g->amount.lo;
1609                               keyHi = g->amount.hi;
1610                               }
1611                         else if (g->gen == Gen_VelRange) {
1612                               veloLo = g->amount.lo;
1613                               veloHi = g->amount.hi;
1614                               }
1615                         else if (g->gen == Gen_SampleId)
1616                               sampleIdx = g->amount.uword;
1617                         else
1618                               gl.append(g);
1619                         }
1620                   int idx3 = 0;
1621                   foreach(GeneratorList* g, gl) {
1622                         if ((idx3 % 8) == 0) {
1623                               if (idx3)
1624                                     fprintf(f, ";\n");
1625                               fprintf(f, "static Generator ");
1626                               }
1627                         else
1628                               fprintf(f, ", ");
1629                         fprintf(f, "ge_%d_%d_%d(%d, %d)",
1630                            idx, idx2, idx3, int(g->gen), g->amount.sword);
1631                         ++idx3;
1632                         }
1633                   fprintf(f, ";\n");
1634                   int n = gl.size();
1635                   if (n) {
1636                         fprintf(f, "static Generator* geList_%d_%d[%d] = {\n      ", idx, idx2, n);
1637                         for (int i = 0; i < n; ++i) {
1638                               if (i) {
1639                                     fprintf(f, ", ");
1640                                     if ((i % 8) == 0)
1641                                           fprintf(f, "\n      ");
1642                                     }
1643                               fprintf(f, "&ge_%d_%d_%d", idx, idx2, i);
1644                               }
1645                         fprintf(f, "\n      };\n");
1646                         }
1647                   if (sampleIdx == -1)
1648                         fprintf(f, "static IZone iz%d_%d(%d, %d, %d, %d, 0, 0, 0);\n", idx, idx2, keyLo, keyHi, veloLo, veloHi);
1649                   else
1650                         fprintf(f, "static IZone iz%d_%d(%d, %d, %d, %d, &sample%d, %d, geList_%d_%d);\n",
1651                            idx, idx2, keyLo, keyHi, veloLo, veloHi, sampleIdx, n, idx, idx2);
1652                   ++idx2;
1653                   }
1654 
1655             fprintf(f, "static IZone* izones%d[%d] = {\n", idx, zones);
1656             idx2 = 0;
1657             for (int i = 0; i < zones; ++i)
1658                   fprintf(f, "      &iz%d_%d,\n", idx, idx2++);
1659             fprintf(f, "      };\n");
1660             fprintf(f, "static Instrument instr%d(0, %d, izones%d);\n\n", idx, zones, idx);
1661             ++idx;
1662             }
1663       //
1664       // dump Preset[]
1665       //
1666 
1667       foreach(int idx, pnums) {
1668             Preset* p = presets[idx];
1669             idx2 = 0;
1670             int zones = p->zones.size();
1671             foreach(Zone* z, p->zones) {
1672                   int keyLo    = 0;
1673                   int keyHi    = 127;
1674                   int veloLo   = 0;
1675                   int veloHi   = 127;
1676                   int instrIdx = -1;
1677                   foreach(GeneratorList* g, z->generators) {
1678                         if (g->gen == Gen_KeyRange) {
1679                               keyLo = g->amount.lo;
1680                               keyHi = g->amount.hi;
1681                               }
1682                         else if (g->gen == Gen_VelRange) {
1683                               veloLo = g->amount.lo;
1684                               veloHi = g->amount.hi;
1685                               }
1686                         else if (g->gen == Gen_Instrument)
1687                               instrIdx = g->amount.uword;
1688                         }
1689                   if (keyLo == 0
1690                      && keyHi == 127
1691                      && veloLo == 0
1692                      && veloHi == 127) {
1693                         if (instrIdx == -1)
1694                               fprintf(f, "static PZone pz%d_%d(0);\n", idx, idx2);
1695                         else
1696                               fprintf(f, "static PZone pz%d_%d(&instr%d);\n", idx, idx2, instrIdx);
1697                         }
1698                   else {
1699                         if (instrIdx == -1)
1700                               fprintf(f, "static PZone pz%d_%d(%d, %d, %d, %d, 0);\n", idx, idx2, keyLo, keyHi, veloLo, veloHi);
1701                         else
1702                               fprintf(f, "static PZone pz%d_%d(%d, %d, %d, %d, &instr%d);\n", idx, idx2, keyLo, keyHi, veloLo, veloHi, instrIdx);
1703                         }
1704                   ++idx2;
1705                   }
1706             fprintf(f, "static PZone* pzones%d[%d] = {\n", idx, zones);
1707             idx2 = 0;
1708             for (int i = 0; i < zones; ++i) {
1709                   fprintf(f, "      &pz%d_%d,\n", idx, idx2);
1710                   ++idx2;
1711                   }
1712             fprintf(f, "      };\n");
1713 
1714             fprintf(f, "static Preset preset%d(%d, %d, 0, %d, pzones%d);    // %s\n\n",
1715                idx, p->preset, p->bank, p->zones.size(), idx, p->name);
1716             ++idx;
1717             }
1718 
1719       fprintf(f, "static Preset* sfPresets[%d] = {\n", pnums.size());
1720       foreach(int idx, pnums)
1721             fprintf(f, "      &preset%d,   // %s\n", idx, presets[idx]->name);
1722       fprintf(f, "      };\n");
1723 
1724       fprintf(f, "static SFont _buildinSf(%d, sfPresets);\n", pnums.size());
1725       fprintf(f, "SFont* createSf() { return &_buildinSf; }\n");
1726       fprintf(f, "} // end namespace\n");
1727       fclose(f);
1728       return true;
1729       }
1730 
1731 //---------------------------------------------------------
1732 //   dumpPresets
1733 //---------------------------------------------------------
1734 
dumpPresets()1735 void SoundFont::dumpPresets()
1736       {
1737       int idx = 0;
1738       foreach(const Preset* p, presets) {
1739             printf("%03d %04x-%02x %s\n", idx, p->bank, p->preset, p->name);
1740             ++idx;
1741             }
1742       }
1743 
1744 
1745 #ifndef SFTOOLS_NOXML
1746 static const char* generatorNames[] = {
1747       "StartAddrOfs", "EndAddrOfs", "StartLoopAddrOfs",
1748       "EndLoopAddrOfs", "StartAddrCoarseOfs", "ModLFO2Pitch",
1749       "VibLFO2Pitch", "ModEnv2Pitch", "FilterFc", "FilterQ",
1750       "ModLFO2FilterFc", "ModEnv2FilterFc", "EndAddrCoarseOfs",
1751       "ModLFO2Vol", "Unused1", "ChorusSend", "ReverbSend", "Pan",
1752       "Unused2", "Unused3", "Unused4",
1753       "ModLFODelay", "ModLFOFreq", "VibLFODelay", "VibLFOFreq",
1754       "ModEnvDelay", "ModEnvAttack", "ModEnvHold", "ModEnvDecay",
1755       "ModEnvSustain", "ModEnvRelease", "Key2ModEnvHold",
1756       "Key2ModEnvDecay", "VolEnvDelay", "VolEnvAttack",
1757       "VolEnvHold", "VolEnvDecay", "VolEnvSustain", "VolEnvRelease",
1758       "Key2VolEnvHold", "Key2VolEnvDecay", "Instrument",
1759       "Reserved1", "KeyRange", "VelRange",
1760       "StartLoopAddrCoarseOfs", "Keynum", "Velocity",
1761       "Attenuation", "Reserved2", "EndLoopAddrCoarseOfs",
1762       "CoarseTune", "FineTune", "SampleId", "SampleModes",
1763       "Reserved3", "ScaleTune", "ExclusiveClass", "OverrideRootKey",
1764       "Dummy"
1765       };
1766 
1767 //---------------------------------------------------------
1768 //   writeXml
1769 //---------------------------------------------------------
1770 
writeXml(QFile * f)1771 bool SoundFont::writeXml(QFile* f)
1772       {
1773       Xml xml(f);
1774 
1775       xml.header();
1776       xml.stag("Sfont");
1777       xml.tag("version", QString("%1.%2").arg(version.major).arg(version.minor));
1778       if (name)
1779             xml.tag("name",      Xml::xmlString(name));
1780       if (engine)
1781             xml.tag("engine",    Xml::xmlString(engine));
1782       if (date)
1783             xml.tag("date",      Xml::xmlString(date));
1784       if (comment)
1785             xml.tag("comment",   Xml::xmlString(comment));
1786       if (tools)
1787             xml.tag("tools",     Xml::xmlString(tools));
1788       if (creator)
1789             xml.tag("creator",   Xml::xmlString(creator));
1790       if (product)
1791             xml.tag("product",   Xml::xmlString(product));
1792       if (copyright)
1793             xml.tag("copyright", Xml::xmlString(copyright));
1794 
1795       foreach(Preset* p, presets) {
1796             xml.stag(QString("Preset name=\"%1\" preset=\"%2\" bank=\"%3\"")
1797                .arg(p->name).arg(p->preset).arg(p->bank));
1798             foreach(Zone* z, p->zones)
1799                   write(xml, z);
1800             xml.etag();
1801             }
1802       foreach(Instrument* instrument, instruments) {
1803             xml.stag(QString("Instrument name=\"%1\"").arg(instrument->name));
1804             foreach(Zone* z, instrument->zones)
1805                   write(xml, z);
1806             xml.etag();
1807             }
1808       int idx = 0;
1809       foreach(Sample* s, samples) {
1810             xml.stag(QString("Sample name=\"%1\"").arg(s->name));
1811             xml.tag("start",       s->start);
1812             xml.tag("end",         s->end);
1813             xml.tag("loopstart",   s->loopstart);
1814             xml.tag("loopend",     s->loopend);
1815             xml.tag("samplerate",  s->samplerate);
1816             xml.tag("origpitch",   s->origpitch);
1817             if (s->pitchadj)
1818                   xml.tag("pitchadj", s->pitchadj);
1819             xml.tag("sampletype",  s->sampletype);
1820             xml.etag();
1821             writeSampleFile(s, QString("%1").arg(idx));
1822             ++idx;
1823             }
1824       xml.etag();
1825       return true;
1826       }
1827 
1828 //---------------------------------------------------------
1829 //   write
1830 //---------------------------------------------------------
1831 
write(Xml & xml,Zone * z)1832 void SoundFont::write(Xml& xml, Zone* z)
1833       {
1834       xml.stag("Zone");
1835       foreach(GeneratorList* g, z->generators) {
1836             const char* name = generatorNames[g->gen];
1837             if (g->gen == Gen_KeyRange || g->gen == Gen_VelRange)
1838                   xml.tagE(QString("Generator name=\"%1\" lo=\"%2\" hi=\"%3\"")
1839                      .arg(name).arg(g->amount.lo).arg(g->amount.hi));
1840             else if (g->gen == Gen_Instrument) {
1841                   int idx = g->amount.uword;
1842                   xml.tag("Instrument", instruments[idx]->name);
1843                   }
1844             else if (g->gen == Gen_SampleId) {
1845                   int idx = g->amount.uword;
1846                   xml.tag("SampleId", samples[idx]->name);
1847                   }
1848             else
1849                   xml.tagE(QString("Generator name=\"%1\" val=\"%2\"")
1850                      .arg(name).arg(g->amount.sword));
1851             }
1852       foreach(ModulatorList* m, z->modulators) {
1853             xml.stag("Modulator");
1854             xml.tag("src", m->src);
1855             xml.tag("dst", m->dst);
1856             xml.tag("amount", m->amount);
1857             xml.tag("amtSrc", m->amtSrc);
1858             xml.tag("transform", m->transform);
1859             xml.etag();
1860             }
1861       xml.etag();
1862       }
1863 
1864 //---------------------------------------------------------
1865 //   writeSampleFile
1866 //---------------------------------------------------------
1867 
writeSampleFile(Sample * s,QString name)1868 bool SoundFont::writeSampleFile(Sample* s, QString name)
1869       {
1870       QString path = "waves/" + name + ".ogg";
1871 
1872       QFile f(path);
1873       if (!f.open(QIODevice::ReadOnly)) {
1874             fprintf(stderr, "cannot open <%s>\n", qPrintable(f.fileName()));
1875             return false;
1876             }
1877       f.seek(samplePos + s->start * sizeof(short));
1878       int len = s->end - s->start;
1879       short * buffer = new short[len];
1880       f.read((char*)buffer, len * sizeof(short));
1881       f.close();
1882 
1883       // int format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
1884       int format = SF_FORMAT_OGG | SF_FORMAT_VORBIS;
1885 
1886       SF_INFO info;
1887       memset(&info, 0, sizeof(info));
1888       info.channels   = 1;
1889       info.samplerate = s->samplerate;
1890       info.format     = format;
1891 
1892       SNDFILE* sf = sf_open(qPrintable(path), SFM_WRITE, &info);
1893       if (sf == 0) {
1894             fprintf(stderr, "open soundfile <%s> failed: %s\n",
1895                qPrintable(path), sf_strerror(sf));
1896             delete [] buffer;
1897             return false;
1898             }
1899 
1900       sf_write_short(sf, buffer, len);
1901       delete [] buffer;
1902 
1903       if (sf_close(sf)) {
1904             fprintf(stderr, "close soundfile failed\n");
1905             return false;
1906             }
1907       return true;
1908       }
1909 
1910 //---------------------------------------------------------
1911 //   readXml
1912 //---------------------------------------------------------
1913 
readXml(QFile * f)1914 bool SoundFont::readXml(QFile* f)
1915       {
1916       QDomDocument doc;
1917       int line, column;
1918       QString err;
1919       if (!doc.setContent(f, false, &err, &line, &column)) {
1920             QString s;
1921             printf("error reading file %s at line %d column %d: %s\n",
1922                qPrintable(f->fileName()), line, column, qPrintable(err));
1923             return false;
1924             }
1925       return true;
1926       }
1927 #endif
1928 
1929 
1930 struct VorbisData {
1931     int pos;
1932     QByteArray data;
1933 };
1934 
1935 static VorbisData vorbisData;
1936 static size_t ovRead(void* ptr, size_t size, size_t nmemb, void* datasource);
1937 static int ovSeek(void* datasource, ogg_int64_t offset, int whence);
1938 static long ovTell(void* datasource);
1939 static ov_callbacks ovCallbacks = { ovRead, ovSeek, nullptr, ovTell };
1940 
1941 //---------------------------------------------------------
1942 //   ovRead
1943 //---------------------------------------------------------
1944 
ovRead(void * ptr,size_t size,size_t nmemb,void * datasource)1945 static size_t ovRead(void* ptr, size_t size, size_t nmemb, void* datasource)
1946 {
1947     VorbisData* vd = (VorbisData*)datasource;
1948     size_t n = size * nmemb;
1949     if (vd->data.size() < int(vd->pos + n))
1950         n = vd->data.size() - vd->pos;
1951     if (n) {
1952         const char* src = vd->data.data() + vd->pos;
1953         memcpy(ptr, src, n);
1954         vd->pos += n;
1955     }
1956 
1957     return n;
1958 }
1959 
1960 //---------------------------------------------------------
1961 //   ovSeek
1962 //---------------------------------------------------------
1963 
ovSeek(void * datasource,ogg_int64_t offset,int whence)1964 static int ovSeek(void* datasource, ogg_int64_t offset, int whence)
1965 {
1966     VorbisData* vd = (VorbisData*)datasource;
1967     switch(whence) {
1968     case SEEK_SET:
1969         vd->pos = offset;
1970         break;
1971     case SEEK_CUR:
1972         vd->pos += offset;
1973         break;
1974     case SEEK_END:
1975         vd->pos = vd->data.size() - offset;
1976         break;
1977     }
1978     return 0;
1979 }
1980 
1981 //---------------------------------------------------------
1982 //   ovTell
1983 //---------------------------------------------------------
1984 
ovTell(void * datasource)1985 static long ovTell(void* datasource)
1986 {
1987     VorbisData* vd = (VorbisData*)datasource;
1988     return vd->pos;
1989 }
1990 
1991 //---------------------------------------------------------
1992 //   writeUncompressedSample
1993 //---------------------------------------------------------
1994 
writeUncompressedSample(Sample * s)1995 int SoundFont::writeUncompressedSample(Sample* s)
1996 {
1997     // Prepare input data
1998     QFile f(path);
1999     if (!f.open(QIODevice::ReadOnly)) {
2000         fprintf(stderr, "cannot open <%s>\n", qPrintable(f.fileName()));
2001         return 0;
2002     }
2003     f.seek(samplePos + s->start);
2004     int oggSize = s->end - s->start;
2005     short * ibuffer = new short[oggSize];
2006     f.read((char*)ibuffer, oggSize);
2007     f.close();
2008 
2009     vorbisData.pos  = 0;
2010     vorbisData.data = QByteArray((char *)ibuffer, oggSize);
2011 
2012     // Decode
2013     QByteArray decodedData;
2014     OggVorbis_File vf;
2015     vorbisData.pos  = 0;
2016     int length = 0;
2017     if (ov_open_callbacks(&vorbisData, &vf, nullptr, 0, ovCallbacks) == 0)
2018     {
2019         double attenuation = 0;
2020         for (int i = 0; i < vf.vc->comments; i++)
2021         {
2022             QString comment(vf.vc->user_comments[i]);
2023             if (comment.contains("AMP="))
2024             {
2025                 QStringList split = comment.split('=');
2026                 if (split.size() == 2)
2027                 {
2028                     bool ok = false;
2029                     attenuation = split[1].toDouble(&ok);
2030                     if (!ok)
2031                         attenuation = 0;
2032                 }
2033             }
2034         }
2035         double linearAmp = pow(10.0, attenuation / 20.0);
2036 
2037         short buffer[2048];
2038         int numberRead = 0;
2039         int section = 0;
2040         do {
2041             numberRead = ov_read(&vf, (char *)buffer, 2048 * sizeof(short), 0, 2, 1, &section);
2042             for (unsigned int i = 0; i < numberRead / sizeof(short); i++)
2043                 buffer[i] = (double)buffer[i] / linearAmp;
2044             write((char *)buffer, numberRead);
2045             length += numberRead;
2046         } while (numberRead);
2047 
2048         ov_clear(&vf);
2049     }
2050 
2051     delete[] ibuffer;
2052     return length;
2053 }
2054