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, §ion);
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