/[svn]/libgig/trunk/src/SF.cpp
ViewVC logotype

Contents of /libgig/trunk/src/SF.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3481 - (show annotations) (download)
Fri Feb 22 12:12:50 2019 UTC (5 years, 1 month ago) by schoenebeck
File size: 64607 byte(s)
* gig.h, gig.cpp: Added File::GetRiffFile() method.
* DLS.h, DLS.cpp: Added File::GetRiffFile() method.
* sf2.h, sf2.cpp: Added Sample::GetFile() and
  File::GetRiffFile() methods.
* RIFF.h, RIFF.cpp: Added a 2nd (overridden)
  progress_t::subdivide() method which allows a more
  fine graded control into which portions the subtasks
  are divided to.
* RIFF Fix: API doc comment for Chunk::GetFilePos() was
  completely wrong.
* Bumped version (4.1.0.svn14).

1 /***************************************************************************
2 * *
3 * libsf2 - C++ cross-platform SF2 format file access library *
4 * *
5 * Copyright (C) 2009-2010 Grigor Iliev <grigor@grigoriliev.com>, *
6 * Christian Schoenebeck and Andreas Persson *
7 * *
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include "RIFF.h"
25
26 #include "SF.h"
27
28 #include "helper.h"
29 #include <math.h>
30
31 #define _1200TH_ROOT_OF_2 1.000577789506555
32 #define _200TH_ROOT_OF_10 1.011579454259899
33
34 namespace sf2 {
35 double ToSeconds(int Timecents) {
36 if (Timecents == NONE) return NONE;
37 if (Timecents == 0) return 1.0;
38 if (Timecents == -32768) return 0.0;
39 return pow(_1200TH_ROOT_OF_2, Timecents);
40 }
41
42 double ToRatio(int Centibels) {
43 if (Centibels == NONE) return NONE;
44 if (Centibels == 0) return 1.0;
45 return pow(_200TH_ROOT_OF_10, Centibels);
46 }
47
48 double ToHz(int cents) {
49 if (cents == NONE) return NONE;
50 if (cents == 0) return 8.176;
51 return pow(_1200TH_ROOT_OF_2, cents) * 8.176;
52 }
53
54 RIFF::Chunk* GetMandatoryChunk(RIFF::List* list, uint32_t chunkId) {
55 RIFF::Chunk* ck = list->GetSubChunk(chunkId);
56 if(ck == NULL) throw Exception("Mandatory chunk in RIFF list chunk not found: " + ToString(chunkId));
57 return ck;
58 }
59
60 void LoadString(RIFF::Chunk* ck, std::string& s, int strLength) {
61 if(ck == NULL) return;
62 char* buf = new char[strLength];
63 int len = 0;
64 for(int i = 0; i < strLength; i++) {
65 buf[i] = ck->ReadInt8();
66 if(buf[i] == 0 && !len) len = i;
67 }
68 if(!len) len = strLength;
69 s.assign(buf, len);
70 delete [] buf;
71 }
72
73 /**
74 * Throws an error if the chunk is NULL or
75 * the chunk data size is less than size (in bytes).
76 */
77 void VerifySize(RIFF::Chunk* ck, int size) {
78 if (ck == NULL) throw Exception("NULL chunk");
79 if (ck->GetSize() < size) {
80 throw Exception("Invalid chunk size. Chunk ID: " + ToString(ck->GetChunkID()));
81 }
82 }
83
84 Modulator::Modulator(SFModulator mod) {
85 Type = mod >> 10; // The last 6 bits
86 Polarity = mod & (1 << 9);
87 Direction = mod & (1 << 8);
88 MidiPalete = mod & (1 << 7); // two paletes - general or MIDI
89 Index = mod & 0x7f; /* index field */;
90
91 }
92
93 ModulatorItem::ModulatorItem(ModList& mod) :
94 ModSrcOper(Modulator(mod.ModSrcOper)),
95 ModAmtSrcOper(Modulator(mod.ModAmtSrcOper))
96 {
97
98 }
99
100 Version::Version(RIFF::Chunk* ck) {
101 if(ck != NULL) VerifySize(ck, 4);
102 Major = ck ? ck->ReadUint16() : 0;
103 Minor = ck ? ck->ReadUint16() : 0;
104 }
105
106 // *************** Info ***************
107 // *
108
109 /** @brief Constructor.
110 *
111 * Initializes the info strings with values provided by an INFO list chunk.
112 *
113 * @param list - pointer to a list chunk which contains an INFO list chunk
114 */
115 Info::Info(RIFF::List* list) {
116 if (list) {
117 RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);
118 if (lstINFO) {
119 pVer = new Version(GetMandatoryChunk(lstINFO, CHUNK_ID_IFIL));
120 LoadString(CHUNK_ID_ISNG, lstINFO, SoundEngine);
121 LoadString(CHUNK_ID_INAM, lstINFO, BankName);
122 LoadString(CHUNK_ID_IROM, lstINFO, RomName);
123 pRomVer = new Version(lstINFO->GetSubChunk(CHUNK_ID_IVER));
124 LoadString(CHUNK_ID_ICRD, lstINFO, CreationDate);
125 LoadString(CHUNK_ID_IENG, lstINFO, Engineers);
126 LoadString(CHUNK_ID_IPRD, lstINFO, Product);
127 LoadString(CHUNK_ID_ICOP, lstINFO, Copyright);
128 LoadString(CHUNK_ID_ICMT, lstINFO, Comments);
129 LoadString(CHUNK_ID_ISFT, lstINFO, Software);
130
131 }
132 }
133 }
134
135 Info::~Info() {
136 delete pVer;
137 delete pRomVer;
138 }
139
140 /** @brief Load given INFO field.
141 *
142 * Load INFO field from INFO chunk with chunk ID \a ChunkID from INFO
143 * list chunk \a lstINFO and save value to \a s.
144 */
145 void Info::LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s) {
146 RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
147 ::LoadString(ck, s); // function from helper.h
148 }
149
150 Sample::Sample(File* file, RIFF::Chunk* ck, RIFF::Chunk* pCkSmpl, RIFF::Chunk* pCkSm24) {
151 this->pFile = file;
152 this->pCkSmpl = pCkSmpl;
153 this->pCkSm24 = pCkSm24;
154
155 LoadString(ck, Name, 20);
156 Start = ck->ReadInt32();
157 End = ck->ReadInt32();
158 StartLoop = ck->ReadInt32();
159 EndLoop = ck->ReadInt32();
160 SampleRate = ck->ReadInt32();
161 OriginalPitch = ck->ReadInt8();
162 PitchCorrection = ck->ReadInt8();
163 SampleLink = ck->ReadInt16();
164 SampleType = ck->ReadInt16();
165
166 if (Start > End || !pCkSmpl || pCkSmpl->GetSize() <= End) {
167 throw Exception("Broken SF2 file (invalid sample info)");
168 }
169
170 ChannelCount = 1;
171 switch(SampleType) {
172 case 0 : // terminal sample
173 case sf2::Sample::MONO_SAMPLE :
174 case sf2::Sample::ROM_MONO_SAMPLE : break;
175 case sf2::Sample::RIGHT_SAMPLE :
176 case sf2::Sample::LEFT_SAMPLE :
177 case sf2::Sample::ROM_RIGHT_SAMPLE :
178 case sf2::Sample::ROM_LEFT_SAMPLE : ChannelCount = 2; break;
179 case sf2::Sample::LINKED_SAMPLE :
180 case sf2::Sample::ROM_LINKED_SAMPLE : std::cerr << "Linked samples not implemented yet"; break;
181 default: throw Exception("Broken SF2 file (invalid sample type)");
182 }
183
184 RAMCache.Size = 0;
185 RAMCache.pStart = NULL;
186 RAMCache.NullExtensionSize = 0;
187 }
188
189 int Sample::GetChannelCount() {
190 return ChannelCount;
191 }
192
193 long Sample::GetTotalFrameCount() {
194 return (End - Start);
195 }
196
197 /**
198 * @returns The frame size in bytes
199 */
200 int Sample::GetFrameSize() {
201 return ChannelCount * ((pCkSm24 != NULL) ? 3 : 2);
202 }
203
204 bool Sample::HasLoops() {
205 return StartLoop != 0 && EndLoop != 0;
206 }
207
208 /**
209 * Reads \a SampleCount number of sample points from the position stored
210 * in \a pPlaybackState into the buffer pointed by \a pBuffer and moves
211 * the position within the sample respectively, this method honors the
212 * looping informations of the sample (if any). Use this
213 * method if you don't want to load the sample into RAM, thus for disk
214 * streaming. All this methods needs to know to proceed with streaming
215 * for the next time you call this method is stored in \a pPlaybackState.
216 * You have to allocate and initialize the playback_state_t structure by
217 * yourself before you use it to stream a sample:
218 * @code
219 * PlaybackState playbackstate;
220 * playbackstate.position = 0;
221 * playbackstate.reverse = false;
222 * playbackstate.loop_cycles_left = pSample->LoopPlayCount;
223 * @endcode
224 * You don't have to take care of things like if there is actually a loop
225 * defined or if the current read position is located within a loop area.
226 * The method already handles such cases by itself.
227 *
228 * @param pBuffer destination buffer
229 * @param FrameCount number of sample points to read
230 * @param pPlaybackState will be used to store and reload the playback
231 * state for the next ReadAndLoop() call
232 * @returns number of successfully read sample points
233 */
234 unsigned long Sample::ReadAndLoop (
235 void* pBuffer,
236 unsigned long FrameCount,
237 PlaybackState* pPlaybackState,
238 Region* pRegion
239 ) {
240 // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
241 unsigned long samplestoread = FrameCount, totalreadsamples = 0, readsamples, samplestoloopend;
242 uint8_t* pDst = (uint8_t*) pBuffer;
243 SetPos(pPlaybackState->position);
244 if (pRegion->HasLoop) {
245 do {
246 samplestoloopend = pRegion->LoopEnd - GetPos();
247 readsamples = Read(&pDst[totalreadsamples * GetFrameSize()], Min(samplestoread, samplestoloopend));
248 samplestoread -= readsamples;
249 totalreadsamples += readsamples;
250 if (readsamples == samplestoloopend) {
251 SetPos(pRegion->LoopStart);
252 }
253 } while (samplestoread && readsamples);
254 } else {
255 totalreadsamples = Read(pBuffer, FrameCount);
256 }
257
258 pPlaybackState->position = GetPos();
259
260 return totalreadsamples;
261 }
262
263 Region::Region() {
264 pSample = NULL;
265 pInstrument = NULL;
266 pParentInstrument = NULL;
267 loKey = hiKey = NONE;
268 minVel = maxVel = NONE;
269 startAddrsOffset = startAddrsCoarseOffset = endAddrsOffset = endAddrsCoarseOffset = 0;
270 startloopAddrsOffset = startloopAddrsCoarseOffset = endloopAddrsOffset = endloopAddrsCoarseOffset = 0;
271 pan = fineTune = coarseTune = 0;
272 overridingRootKey = -1; // -1 means not used
273
274 HasLoop = false;
275 LoopStart = LoopEnd = 0;
276
277 EG1PreAttackDelay = EG1Attack = EG1Hold = EG1Decay = EG1Release = -12000;
278 EG1Sustain = 0;
279 EG2PreAttackDelay = EG2Attack = EG2Hold = EG2Decay = EG2Release = -12000;
280 EG2Sustain = 0;
281
282 modEnvToPitch = modLfoToPitch = modEnvToFilterFc = modLfoToFilterFc = modLfoToVolume = 0;
283 freqModLfo = 0;
284 delayModLfo = -12000;
285 vibLfoToPitch = 0;
286 freqVibLfo = 0;
287 delayVibLfo = -12000;
288
289 exclusiveClass = 0;
290
291 initialFilterFc = 13500;
292 initialFilterQ = 0;
293 }
294
295 int Region::GetUnityNote() {
296 return overridingRootKey != -1 ? overridingRootKey : pSample->OriginalPitch;
297 }
298
299 int CheckRange(std::string genName, int min, int max, int& gen) {
300 if (gen == NONE) return gen;
301
302 if (gen < min) {
303 std::cerr << "sf2: " << genName;
304 std::cerr << " is below the minimum allowed value (min=" << min << "): " << gen << std::endl;
305 gen = min;
306 }
307 if (gen > max) {
308 std::cerr << "sf2: " << genName;
309 std::cerr << " is above the maximum allowed value (max=" << max << "): " << gen << std::endl;
310 gen = max;
311 }
312
313 return gen;
314 }
315
316 void Region::SetGenerator(sf2::File* pFile, GenList& Gen) {
317 switch(Gen.GenOper) {
318 case START_ADDRS_OFFSET:
319 startAddrsOffset = Gen.GenAmount.wAmount;
320 break;
321 case END_ADDRS_OFFSET:
322 if (Gen.GenAmount.shAmount <= 0) {
323 endAddrsOffset = Gen.GenAmount.shAmount;
324 } else {
325 std::cerr << "Ignoring invalid endAddrsOffset" << std::endl;
326 }
327 break;
328 case STARTLOOP_ADDRS_OFFSET:
329 startloopAddrsOffset = Gen.GenAmount.shAmount;
330 LoopStart += startloopAddrsOffset;
331 break;
332 case ENDLOOP_ADDRS_OFFSET:
333 endloopAddrsOffset = Gen.GenAmount.shAmount;
334 LoopEnd += endloopAddrsOffset;
335 break;
336 case START_ADDRS_COARSE_OFFSET:
337 startAddrsCoarseOffset = Gen.GenAmount.wAmount;
338 break;
339 case MOD_LFO_TO_PITCH:
340 modLfoToPitch = Gen.GenAmount.shAmount;
341 CheckRange("modLfoToPitch", -12000, 12000, modLfoToPitch);
342 break;
343 case VIB_LFO_TO_PITCH:
344 vibLfoToPitch = Gen.GenAmount.shAmount;
345 CheckRange("vibLfoToPitch", -12000, 12000, vibLfoToPitch);
346 break;
347 case MOD_ENV_TO_PITCH:
348 modEnvToPitch = Gen.GenAmount.shAmount;
349 CheckRange("modEnvToPitch", -12000, 12000, modEnvToPitch);
350 break;
351 case INITIAL_FILTER_FC:
352 initialFilterFc = Gen.GenAmount.wAmount;
353 CheckRange("initialFilterFc", 1500, 13500, initialFilterFc);
354 break;
355 case INITIAL_FILTER_Q:
356 initialFilterQ = Gen.GenAmount.wAmount;
357 CheckRange("initialFilterQ", 0, 960, initialFilterQ);
358 break;
359 case MOD_LFO_TO_FILTER_FC:
360 modLfoToFilterFc = Gen.GenAmount.shAmount;
361 CheckRange("modLfoToFilterFc", -12000, 12000, modLfoToFilterFc);
362 break;
363 case MOD_ENV_TO_FILTER_FC:
364 modEnvToFilterFc = Gen.GenAmount.shAmount;
365 CheckRange("modEnvToFilterFc", -12000, 12000, modEnvToFilterFc);
366 break;
367 case END_ADDRS_COARSE_OFFSET:
368 endAddrsCoarseOffset = Gen.GenAmount.wAmount;
369 break;
370 case MOD_LFO_TO_VOLUME:
371 modLfoToVolume = Gen.GenAmount.shAmount;
372 CheckRange("modLfoToVolume", -960, 960, modLfoToVolume);
373 break;
374 case CHORUS_EFFECTS_SEND:
375 break;
376 case REVERB_EFFECTS_SEND:
377 break;
378 case PAN:
379 pan = Gen.GenAmount.shAmount;
380 CheckRange("pan", -500, 500, pan);
381 pan = pan * 64 / 500;
382 if (pan > 63) pan = 63;
383 break;
384 case DELAY_MOD_LFO:
385 delayModLfo = Gen.GenAmount.shAmount;
386 CheckRange("delayModLfo", -12000, 5000, delayModLfo);
387 break;
388 case FREQ_MOD_LFO:
389 freqModLfo = Gen.GenAmount.shAmount;
390 CheckRange("freqModLfo", -16000, 4500, freqModLfo);
391 break;
392 case DELAY_VIB_LFO:
393 delayVibLfo = Gen.GenAmount.shAmount;
394 CheckRange("delayVibLfo", -12000, 5000, delayVibLfo);
395 break;
396 case FREQ_VIB_LFO:
397 freqVibLfo = Gen.GenAmount.shAmount;
398 CheckRange("freqModLfo", -16000, 4500, freqModLfo);
399 break;
400 case DELAY_MOD_ENV:
401 EG2PreAttackDelay = Gen.GenAmount.shAmount;
402 CheckRange("delayModEnv", -12000, 5000, EG2PreAttackDelay);
403 break;
404 case ATTACK_MOD_ENV:
405 EG2Attack = Gen.GenAmount.shAmount;
406 CheckRange("attackModEnv", -12000, 8000, EG2Attack);
407 break;
408 case HOLD_MOD_ENV:
409 EG2Hold = Gen.GenAmount.shAmount;
410 CheckRange("holdModEnv", -12000, 5000, EG2Hold);
411 break;
412 case DECAY_MOD_ENV:
413 EG2Decay = Gen.GenAmount.shAmount;
414 CheckRange("decayModEnv", -12000, 8000, EG2Decay);
415 break;
416 case SUSTAIN_MOD_ENV:
417 EG2Sustain = Gen.GenAmount.shAmount;
418 CheckRange("sustainModEnv", 0, 1000, EG2Sustain);
419 break;
420 case RELEASE_MOD_ENV:
421 EG2Release = Gen.GenAmount.shAmount;
422 CheckRange("releaseModEnv", -12000, 8000, EG2Release);
423 break;
424 case KEYNUM_TO_MOD_ENV_HOLD:
425 break;
426 case KEYNUM_TO_MOD_ENV_DECAY:
427 break;
428 case DELAY_VOL_ENV:
429 EG1PreAttackDelay = Gen.GenAmount.shAmount;
430 CheckRange("delayVolEnv", -12000, 5000, EG1PreAttackDelay);
431 break;
432 case ATTACK_VOL_ENV:
433 EG1Attack = Gen.GenAmount.shAmount;
434 CheckRange("attackVolEnv", -12000, 8000, EG1Attack);
435 break;
436 case HOLD_VOL_ENV:
437 EG1Hold = Gen.GenAmount.shAmount;
438 CheckRange("holdVolEnv", -12000, 5000, EG1Hold);
439 break;
440 case DECAY_VOL_ENV:
441 EG1Decay = Gen.GenAmount.shAmount;
442 CheckRange("decayVolEnv", -12000, 8000, EG1Decay);
443 break;
444 case SUSTAIN_VOL_ENV:
445 EG1Sustain = Gen.GenAmount.shAmount;
446 CheckRange("sustainVolEnv", 0, 1440, EG1Sustain);
447 break;
448 case RELEASE_VOL_ENV:
449 EG1Release = Gen.GenAmount.shAmount;
450 CheckRange("releaseVolEnv", -12000, 8000, EG1Release);
451 break;
452 case KEYNUM_TO_VOL_ENV_HOLD:
453 break;
454 case KEYNUM_TO_VOL_ENV_DECAY:
455 break;
456 case INSTRUMENT: {
457 uint16_t id = Gen.GenAmount.wAmount;
458 if (id >= pFile->Instruments.size()) {
459 throw Exception("Broken SF2 file (missing instruments)");
460 }
461 pInstrument = pFile->Instruments[id];
462 break;
463 }
464 case KEY_RANGE:
465 loKey = Gen.GenAmount.ranges.byLo;
466 CheckRange("loKey", 0, 127, loKey);
467 hiKey = Gen.GenAmount.ranges.byHi;
468 CheckRange("hiKey", 0, 127, hiKey);
469 break;
470 case VEL_RANGE:
471 minVel = Gen.GenAmount.ranges.byLo;
472 CheckRange("minVel", 0, 127, minVel);
473 maxVel = Gen.GenAmount.ranges.byHi;
474 CheckRange("maxVel", 0, 127, maxVel);
475 break;
476 case STARTLOOP_ADDRS_COARSE_OFFSET:
477 startloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
478 LoopStart += startloopAddrsCoarseOffset * 32768;
479 break;
480 case KEYNUM:
481 break;
482 case VELOCITY:
483 break;
484 case INITIAL_ATTENUATION:
485 break;
486 case ENDLOOP_ADDRS_COARSE_OFFSET:
487 endloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
488 LoopEnd += endloopAddrsCoarseOffset * 32768;
489 break;
490 case COARSE_TUNE:
491 coarseTune = Gen.GenAmount.shAmount;
492 CheckRange("coarseTune", -120, 120, coarseTune);
493 break;
494 case FINE_TUNE:
495 fineTune = Gen.GenAmount.shAmount;
496 CheckRange("fineTune", -99, 99, fineTune);
497 break;
498 case SAMPLE_ID: {
499 uint16_t sid = Gen.GenAmount.wAmount;
500 if (sid >= pFile->Samples.size()) {
501 throw Exception("Broken SF2 file (missing samples)");
502 }
503 pSample = pFile->Samples[sid];
504
505 if (HasLoop) {
506 LoopStart += pSample->StartLoop;
507 LoopEnd += pSample->EndLoop;
508 if ( LoopStart < pSample->Start || LoopStart > pSample->End ||
509 LoopStart > LoopEnd || LoopEnd > pSample->End ) {
510 throw Exception("Broken SF2 file (invalid loops)");
511 }
512 LoopStart -= pSample->Start; // Relative to the sample start
513 LoopEnd -= pSample->Start; // Relative to the sample start
514 }
515 break;
516 }
517 case SAMPLE_MODES:
518 HasLoop = Gen.GenAmount.wAmount & 1;
519 // TODO: 3 indicates a sound which loops for the duration of key depression
520 // then proceeds to play the remainder of the sample.
521 break;
522 case SCALE_TUNING:
523 break;
524 case EXCLUSIVE_CLASS:
525 exclusiveClass = Gen.GenAmount.wAmount;
526 break;
527 case OVERRIDING_ROOT_KEY:
528 overridingRootKey = Gen.GenAmount.shAmount;
529 CheckRange("overridingRootKey", -1, 127, overridingRootKey);
530 break;
531 }
532 }
533
534 void Region::SetModulator(sf2::File* pFile, ModList& Mod) {
535 modulators.push_back(ModulatorItem(Mod));
536 /*switch(srcType) {
537 case NO_CONTROLLER:
538 break;
539 case NOTE_ON_VELOCITY:
540 break;
541 case NOTE_ON_KEY_NUMBER:
542 break;
543 case POLY_PRESSURE:
544 break;
545 case CHANNEL_PRESSURE:
546 break;
547 case PITCH_WHEEL:
548 break;
549 case PITCH_WHEEL_SENSITIVITY:
550 break;
551 case LINK:
552 break;
553 default: std::cout << "Unknown controller source: " << srcType << std::endl;
554 }*/
555 }
556
557 int Region::GetPan(Region* pPresetRegion) {
558 if (pPresetRegion == NULL) return pan;
559 int p = pPresetRegion->pan + pan;
560 if (p < -64) p = -64;
561 if (p > 63) p = 63;
562 return p;
563 }
564
565 int Region::GetFineTune(Region* pPresetRegion) {
566 if (pPresetRegion == NULL) return fineTune;
567 int t = pPresetRegion->fineTune + fineTune;
568 if (t < -99) t = -99;
569 if (t > 99) t = 99;
570 return t;
571 }
572
573 int Region::GetCoarseTune(Region* pPresetRegion) {
574 if (pPresetRegion == NULL) return coarseTune;
575 int t = pPresetRegion->coarseTune + coarseTune;
576 if (t < -120) t = -120;
577 if (t > 120) t = 120;
578 return t;
579 }
580
581 double Region::GetEG1PreAttackDelay(Region* pPresetRegion) {
582 int val = (pPresetRegion == NULL || pPresetRegion->EG1PreAttackDelay == NONE) ?
583 EG1PreAttackDelay : pPresetRegion->EG1PreAttackDelay + EG1PreAttackDelay;
584 return ToSeconds(CheckRange("GetEG1PreAttackDelay()", -12000, 5000, val));
585 }
586
587 double Region::GetEG1Attack(Region* pPresetRegion) {
588 int val = (pPresetRegion == NULL || pPresetRegion->EG1Attack == NONE) ?
589 EG1Attack : pPresetRegion->EG1Attack + EG1Attack;
590 return ToSeconds(CheckRange("GetEG1Attack()", -12000, 8000, val));
591 }
592
593 double Region::GetEG1Hold(Region* pPresetRegion) {
594 int val = (pPresetRegion == NULL || pPresetRegion->EG1Hold == NONE) ?
595 EG1Hold : pPresetRegion->EG1Hold + EG1Hold;
596 return ToSeconds(CheckRange("GetEG1Hold()", -12000, 5000, val));
597 }
598
599 double Region::GetEG1Decay(Region* pPresetRegion) {
600 int val = (pPresetRegion == NULL || pPresetRegion->EG1Decay == NONE) ?
601 EG1Decay : pPresetRegion->EG1Decay + EG1Decay;
602 return ToSeconds(CheckRange("GetEG1Decay()", -12000, 8000, val));
603 }
604
605 int Region::GetEG1Sustain(Region* pPresetRegion) {
606 int val = (pPresetRegion == NULL || pPresetRegion->EG1Sustain == NONE) ?
607 EG1Sustain : pPresetRegion->EG1Sustain + EG1Sustain;
608 return CheckRange("GetEG1Sustain()", 0, 1440, val);
609 }
610
611 double Region::GetEG1Release(Region* pPresetRegion) {
612 int val = (pPresetRegion == NULL || pPresetRegion->EG1Release == NONE) ?
613 EG1Release : pPresetRegion->EG1Release + EG1Release;
614 return ToSeconds(CheckRange("GetEG1Release()", -12000, 8000, val));
615 }
616
617 double Region::GetEG2PreAttackDelay(Region* pPresetRegion) {
618 int val = (pPresetRegion == NULL || pPresetRegion->EG2PreAttackDelay == NONE) ?
619 EG2PreAttackDelay : pPresetRegion->EG2PreAttackDelay + EG2PreAttackDelay;
620 return ToSeconds(CheckRange("GetEG2PreAttackDelay()", -12000, 5000, val));
621 }
622
623 double Region::GetEG2Attack(Region* pPresetRegion) {
624 int val = (pPresetRegion == NULL || pPresetRegion->EG2Attack == NONE) ?
625 EG2Attack : pPresetRegion->EG2Attack + EG2Attack;
626 return ToSeconds(CheckRange("GetEG2Attack()", -12000, 8000, val));
627 }
628
629 double Region::GetEG2Hold(Region* pPresetRegion) {
630 int val = (pPresetRegion == NULL || pPresetRegion->EG2Hold == NONE) ?
631 EG2Hold : pPresetRegion->EG2Hold + EG2Hold;
632 return ToSeconds(CheckRange("GetEG2Hold()", -12000, 5000, val));
633 }
634
635 double Region::GetEG2Decay(Region* pPresetRegion) {
636 int val = (pPresetRegion == NULL || pPresetRegion->EG2Decay == NONE) ?
637 EG2Decay : pPresetRegion->EG2Decay + EG2Decay;
638 return ToSeconds(CheckRange("GetEG2Decay()", -12000, 8000, val));
639 }
640
641 int Region::GetEG2Sustain(Region* pPresetRegion) {
642 int val = (pPresetRegion == NULL || pPresetRegion->EG2Sustain == NONE) ?
643 EG2Sustain : pPresetRegion->EG2Sustain + EG2Sustain;
644 return CheckRange("GetEG2Sustain()", 0, 1000, val);
645 }
646
647 double Region::GetEG2Release(Region* pPresetRegion) {
648 int val = (pPresetRegion == NULL || pPresetRegion->EG2Release == NONE) ?
649 EG2Release : pPresetRegion->EG2Release + EG2Release;
650 return ToSeconds(CheckRange("GetEG2Release()", -12000, 8000, val));
651 }
652
653 int Region::GetModEnvToPitch(Region* pPresetRegion) {
654 int val = (pPresetRegion == NULL || pPresetRegion->modEnvToPitch == NONE) ?
655 modEnvToPitch : pPresetRegion->modEnvToPitch + modEnvToPitch;
656 return CheckRange("GetModEnvToPitch()", -12000, 12000, val);
657 }
658
659 int Region::GetModLfoToPitch(Region* pPresetRegion) {
660 int val = (pPresetRegion == NULL || pPresetRegion->modLfoToPitch == NONE) ?
661 modLfoToPitch : pPresetRegion->modLfoToPitch + modLfoToPitch;
662 return CheckRange("GetModLfoToPitch()", -12000, 12000, val);
663 }
664
665 int Region::GetModEnvToFilterFc(Region* pPresetRegion) {
666 int val = (pPresetRegion == NULL || pPresetRegion->modEnvToFilterFc == NONE) ?
667 modEnvToFilterFc : pPresetRegion->modEnvToFilterFc + modEnvToFilterFc;
668 return CheckRange("GetModEnvToFilterFc()", -12000, +12000, val);
669 }
670
671 int Region::GetModLfoToFilterFc(Region* pPresetRegion) {
672 int val = (pPresetRegion == NULL || pPresetRegion->modLfoToFilterFc == NONE) ?
673 modLfoToFilterFc : pPresetRegion->modLfoToFilterFc + modLfoToFilterFc;
674 return CheckRange("GetModLfoToFilterFc()", -12000, +12000, val);
675 }
676
677 double Region::GetModLfoToVolume(Region* pPresetRegion) {
678 int val = (pPresetRegion == NULL || pPresetRegion->modLfoToVolume == NONE) ?
679 modLfoToVolume : pPresetRegion->modLfoToVolume + modLfoToVolume;
680 return CheckRange("GetModLfoToVolume()", -960, 960, val);
681 }
682
683 double Region::GetFreqModLfo(Region* pPresetRegion) {
684 int val = (pPresetRegion == NULL || pPresetRegion->freqModLfo == NONE) ?
685 freqModLfo : pPresetRegion->freqModLfo + freqModLfo;
686 return ToHz(CheckRange("GetFreqModLfo()", -16000, 4500, val));
687 }
688
689 double Region::GetDelayModLfo(Region* pPresetRegion) {
690 int val = (pPresetRegion == NULL || pPresetRegion->delayModLfo == NONE) ?
691 delayModLfo : pPresetRegion->delayModLfo + delayModLfo;
692 return ToSeconds(CheckRange("GetDelayModLfo()", -12000, 5000, val));
693 }
694
695 int Region::GetVibLfoToPitch(Region* pPresetRegion) {
696 int val = (pPresetRegion == NULL || pPresetRegion->vibLfoToPitch == NONE) ?
697 vibLfoToPitch : pPresetRegion->vibLfoToPitch + vibLfoToPitch;
698 return CheckRange("GetVibLfoToPitch()", -12000, 12000, val);
699 }
700
701 double Region::GetFreqVibLfo(Region* pPresetRegion) {
702 int val = (pPresetRegion == NULL || pPresetRegion->freqVibLfo == NONE) ?
703 freqVibLfo : pPresetRegion->freqVibLfo + freqVibLfo;
704 return ToHz(CheckRange("GetFreqVibLfo()", -16000, 4500, val));
705 }
706
707 double Region::GetDelayVibLfo(Region* pPresetRegion) {
708 int val = (pPresetRegion == NULL || pPresetRegion->delayVibLfo == NONE) ?
709 delayVibLfo : pPresetRegion->delayVibLfo + delayVibLfo;
710 return ToSeconds(CheckRange("GetDelayVibLfo()", -12000, 5000, val));
711 }
712
713 int Region::GetInitialFilterFc(Region* pPresetRegion) {
714 if (pPresetRegion == NULL || pPresetRegion->initialFilterFc == NONE) return initialFilterFc;
715 int val = pPresetRegion->initialFilterFc + initialFilterFc;
716 return CheckRange("GetInitialFilterFc()", 1500, 13500, val);
717 }
718
719 int Region::GetInitialFilterQ(Region* pPresetRegion) {
720 int val = (pPresetRegion == NULL || pPresetRegion->initialFilterQ == NONE) ?
721 initialFilterQ : pPresetRegion->initialFilterQ + initialFilterQ;
722 return CheckRange("GetInitialFilterQ()", 0, 960, val);
723 }
724
725 InstrumentBase::InstrumentBase(sf2::File* pFile) {
726 this->pFile = pFile;
727 pGlobalRegion = NULL;
728 }
729
730 InstrumentBase::~InstrumentBase() {
731 if (pGlobalRegion) delete pGlobalRegion;
732 for (ssize_t i = regions.size() - 1; i >= 0; i--) {
733 if (regions[i]) delete (regions[i]);
734 }
735 }
736
737 int InstrumentBase::GetRegionCount() {
738 return (int) regions.size();
739 }
740
741 Region* InstrumentBase::GetRegion(int idx) {
742 if (idx < 0 || idx >= GetRegionCount()) {
743 throw Exception("Region index out of bounds");
744 }
745
746 return regions[idx];
747 }
748
749 Query::Query(InstrumentBase& instrument) : instrument(instrument) {
750 i = 0;
751 }
752
753 Region* Query::next() {
754 while (i < instrument.GetRegionCount()) {
755 Region* r = instrument.GetRegion(i++);
756 if (((r->loKey == NONE && r->hiKey == NONE) || (key >= r->loKey && key <= r->hiKey)) &&
757 ((r->minVel == NONE && r->maxVel == NONE) || (vel >= r->minVel && vel <= r->maxVel))) {
758 return r;
759 }
760 }
761 return 0;
762 }
763
764 Instrument::Instrument(sf2::File* pFile, RIFF::Chunk* ck) : InstrumentBase(pFile) {
765 this->pFile = pFile;
766 LoadString(ck, Name, 20);
767 InstBagNdx = ck->ReadInt16();
768 }
769
770 Instrument::~Instrument() {
771 }
772
773 Region* Instrument::CreateRegion() {
774 Region* r = new Region;
775 r->pParentInstrument = this;
776
777 if (pGlobalRegion != NULL) {
778 r->loKey = pGlobalRegion->loKey;
779 r->hiKey = pGlobalRegion->hiKey;
780 r->minVel = pGlobalRegion->minVel;
781 r->maxVel = pGlobalRegion->maxVel;
782 r->pan = pGlobalRegion->pan;
783 r->fineTune = pGlobalRegion->fineTune;
784 r->coarseTune = pGlobalRegion->coarseTune;
785 r->overridingRootKey = pGlobalRegion->overridingRootKey;
786 r->startAddrsOffset = pGlobalRegion->startAddrsOffset;
787 r->startAddrsCoarseOffset = pGlobalRegion->startAddrsCoarseOffset;
788 r->endAddrsOffset = pGlobalRegion->endAddrsOffset;
789 r->endAddrsCoarseOffset = pGlobalRegion->endAddrsCoarseOffset;
790 r->startloopAddrsOffset = pGlobalRegion->startloopAddrsOffset;
791 r->startloopAddrsCoarseOffset = pGlobalRegion->startloopAddrsCoarseOffset;
792 r->endloopAddrsOffset = pGlobalRegion->endloopAddrsOffset;
793 r->endloopAddrsCoarseOffset = pGlobalRegion->endloopAddrsCoarseOffset;
794
795 r->EG1PreAttackDelay = pGlobalRegion->EG1PreAttackDelay;
796 r->EG1Attack = pGlobalRegion->EG1Attack;
797 r->EG1Hold = pGlobalRegion->EG1Hold;
798 r->EG1Decay = pGlobalRegion->EG1Decay;
799 r->EG1Sustain = pGlobalRegion->EG1Sustain;
800 r->EG1Release = pGlobalRegion->EG1Release;
801
802 r->EG2PreAttackDelay = pGlobalRegion->EG2PreAttackDelay;
803 r->EG2Attack = pGlobalRegion->EG2Attack;
804 r->EG2Hold = pGlobalRegion->EG2Hold;
805 r->EG2Decay = pGlobalRegion->EG2Decay;
806 r->EG2Sustain = pGlobalRegion->EG2Sustain;
807 r->EG2Release = pGlobalRegion->EG2Release;
808
809 r->modEnvToPitch = pGlobalRegion->modEnvToPitch;
810 r->modLfoToPitch = pGlobalRegion->modLfoToPitch;
811 r->modEnvToFilterFc = pGlobalRegion->modEnvToFilterFc;
812 r->modLfoToFilterFc = pGlobalRegion->modLfoToFilterFc;
813 r->modLfoToVolume = pGlobalRegion->modLfoToVolume;
814 r->freqModLfo = pGlobalRegion->freqModLfo;
815 r->delayModLfo = pGlobalRegion->delayModLfo;
816 r->vibLfoToPitch = pGlobalRegion->vibLfoToPitch;
817 r->freqVibLfo = pGlobalRegion->freqVibLfo;
818 r->delayVibLfo = pGlobalRegion->delayVibLfo;
819 r->initialFilterFc = pGlobalRegion->initialFilterFc;
820 r->initialFilterQ = pGlobalRegion->initialFilterQ;
821
822 r->HasLoop = pGlobalRegion->HasLoop;
823 r->LoopStart = pGlobalRegion->LoopStart;
824 r->LoopEnd = pGlobalRegion->LoopEnd;
825
826 r->exclusiveClass = pGlobalRegion->exclusiveClass;
827 }
828
829 return r;
830 }
831
832 void Instrument::DeleteRegion(Region* pRegion) {
833 for (int i = 0; i < regions.size(); i++) {
834 if (regions[i] == pRegion) {
835 delete pRegion;
836 regions[i] = NULL;
837 return;
838 }
839 }
840
841 std::cerr << "Can't remove unknown Region" << std::endl;
842 }
843
844 void Instrument::LoadRegions(int idx1, int idx2) {
845 for (int i = idx1; i < idx2; i++) {
846 int gIdx1 = pFile->InstBags[i].InstGenNdx;
847 int gIdx2 = pFile->InstBags[i + 1].InstGenNdx;
848
849 if (gIdx1 < 0 || gIdx2 < 0 || gIdx1 > gIdx2 || gIdx2 >= pFile->InstGenLists.size()) {
850 throw Exception("Broken SF2 file (invalid InstGenNdx)");
851 }
852
853 int mIdx1 = pFile->InstBags[i].InstModNdx;
854 int mIdx2 = pFile->InstBags[i + 1].InstModNdx;
855
856 if (mIdx1 < 0 || mIdx2 < 0 || mIdx1 > mIdx2 || mIdx2 >= pFile->InstModLists.size()) {
857 throw Exception("Broken SF2 file (invalid InstModNdx)");
858 }
859
860 Region* reg = CreateRegion();
861
862 for (int j = gIdx1; j < gIdx2; j++) {
863 reg->SetGenerator(pFile, pFile->InstGenLists[j]);
864 // TODO: ignore generators following a sampleID generator
865 }
866
867 for (int j = mIdx1; j < mIdx2; j++) {
868 reg->SetModulator(pFile, pFile->InstModLists[j]);
869 }
870
871 if (reg->pSample == NULL) {
872 if (i == idx1 && idx2 - idx1 > 1) {
873 pGlobalRegion = reg; // global zone
874 } else {
875 std::cerr << "Ignoring instrument's region without sample" << std::endl;
876 delete reg;
877 }
878 } else {
879 regions.push_back(reg);
880 }
881 }
882 }
883
884 Preset::Preset(sf2::File* pFile, RIFF::Chunk* ck): InstrumentBase(pFile) {
885 this->pFile = pFile;
886 LoadString(ck, Name, 20);
887 PresetNum = ck->ReadInt16();
888 Bank = ck->ReadInt16();
889 PresetBagNdx = ck->ReadInt16();
890 Library = ck->ReadInt32();
891 Genre = ck->ReadInt32();
892 Morphology = ck->ReadInt32();
893 }
894
895 Preset::~Preset() {
896 }
897
898 Region* Preset::CreateRegion() {
899 Region* r = new Region;
900
901 r->EG1PreAttackDelay = r->EG1Attack = r->EG1Hold = r->EG1Decay = r->EG1Sustain = r->EG1Release = NONE;
902 r->EG2PreAttackDelay = r->EG2Attack = r->EG2Hold = r->EG2Decay = r->EG2Sustain = r->EG2Release = NONE;
903 r->freqModLfo = r->delayModLfo = r->freqVibLfo = r->delayVibLfo = NONE;
904 r->initialFilterFc = r->initialFilterQ = NONE;
905
906 if (pGlobalRegion != NULL) {
907 r->pan = pGlobalRegion->pan;
908 r->fineTune = pGlobalRegion->fineTune;
909 r->coarseTune = pGlobalRegion->coarseTune;
910
911 r->EG1PreAttackDelay = pGlobalRegion->EG1PreAttackDelay;
912 r->EG1Attack = pGlobalRegion->EG1Attack;
913 r->EG1Hold = pGlobalRegion->EG1Hold;
914 r->EG1Decay = pGlobalRegion->EG1Decay;
915 r->EG1Sustain = pGlobalRegion->EG1Sustain;
916 r->EG1Release = pGlobalRegion->EG1Release;
917
918 r->EG2PreAttackDelay = pGlobalRegion->EG2PreAttackDelay;
919 r->EG2Attack = pGlobalRegion->EG2Attack;
920 r->EG2Hold = pGlobalRegion->EG2Hold;
921 r->EG2Decay = pGlobalRegion->EG2Decay;
922 r->EG2Sustain = pGlobalRegion->EG2Sustain;
923 r->EG2Release = pGlobalRegion->EG2Release;
924
925 r->modEnvToPitch = pGlobalRegion->modEnvToPitch;
926 r->modLfoToPitch = pGlobalRegion->modLfoToPitch;
927 r->modEnvToFilterFc = pGlobalRegion->modEnvToFilterFc;
928 r->modLfoToFilterFc = pGlobalRegion->modLfoToFilterFc;
929 r->modLfoToVolume = pGlobalRegion->modLfoToVolume;
930 r->freqModLfo = pGlobalRegion->freqModLfo;
931 r->delayModLfo = pGlobalRegion->delayModLfo;
932 r->vibLfoToPitch = pGlobalRegion->vibLfoToPitch;
933 r->freqVibLfo = pGlobalRegion->freqVibLfo;
934 r->delayVibLfo = pGlobalRegion->delayVibLfo;
935 r->initialFilterFc = pGlobalRegion->initialFilterFc;
936 r->initialFilterQ = pGlobalRegion->initialFilterQ;
937 }
938
939 return r;
940 }
941
942 void Preset::LoadRegions(int idx1, int idx2) {
943 for (int i = idx1; i < idx2; i++) {
944 int gIdx1 = pFile->PresetBags[i].GenNdx;
945 int gIdx2 = pFile->PresetBags[i + 1].GenNdx;
946
947 if (gIdx1 < 0 || gIdx2 < 0 || gIdx1 > gIdx2 || gIdx2 >= pFile->PresetGenLists.size()) {
948 throw Exception("Broken SF2 file (invalid PresetGenNdx)");
949 }
950
951 Region* reg = CreateRegion();
952
953 for (int j = gIdx1; j < gIdx2; j++) {
954 reg->SetGenerator(pFile, pFile->PresetGenLists[j]);
955 }
956 if (reg->pInstrument == NULL) {
957 if (i == idx1 && idx2 - idx1 > 1) {
958 pGlobalRegion = reg; // global zone
959 } else {
960 std::cerr << "Ignoring preset's region without instrument" << std::endl;
961 delete reg;
962 }
963 } else {
964 regions.push_back(reg);
965 }
966 }
967 }
968
969 /** @brief Constructor.
970 *
971 * Load an existing SF2 file.
972 *
973 * @param pRIFF - pointer to a RIFF file which is actually the SF2 file
974 * to load
975 * @throws Exception if given file is not a SF2 file, expected chunks
976 * are missing
977 */
978 File::File(RIFF::File* pRIFF) {
979 if (!pRIFF) throw Exception("NULL pointer reference to RIFF::File object.");
980 this->pRIFF = pRIFF;
981
982 if (pRIFF->GetListType() != RIFF_TYPE_SF2) {
983 throw Exception("Not a SF2 file");
984 }
985
986 pInfo = new Info(pRIFF);
987 if (pInfo->pVer->Major != 2) {
988 throw Exception("Unsupported version: " + ToString(pInfo->pVer->Major));
989 }
990
991 RIFF::List* lstSDTA = pRIFF->GetSubList(LIST_TYPE_SDTA);
992 if (lstSDTA == NULL) {
993 throw Exception("Broken SF2 file (missing sdta)");
994 }
995
996 RIFF::Chunk* pCkSmpl = lstSDTA->GetSubChunk(CHUNK_ID_SMPL);
997 RIFF::Chunk* pCkSm24 = lstSDTA->GetSubChunk(CHUNK_ID_SM24);
998 if (pCkSmpl != NULL && pCkSm24 != NULL) {
999 long l = pCkSmpl->GetSize() / 2;
1000 if (l%2) l++;
1001 if (pCkSm24->GetSize() != l) {
1002 pCkSm24 = NULL; // ignoring sm24 due to invalid size
1003 }
1004 }
1005
1006 RIFF::List* lstPDTA = pRIFF->GetSubList(LIST_TYPE_PDTA);
1007 if (lstPDTA == NULL) {
1008 throw Exception("Broken SF2 file (missing pdta)");
1009 }
1010
1011 RIFF::Chunk* ck = lstPDTA->GetSubChunk(CHUNK_ID_PHDR);
1012 if (ck->GetSize() < 38) {
1013 throw Exception("Broken SF2 file (broken phdr)");
1014 }
1015
1016 int count = (int) ck->GetSize() / 38;
1017 for (int i = 0; i < count; i++) {
1018 Presets.push_back(new Preset(this, ck));
1019 }
1020
1021 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_PBAG);
1022 if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
1023 throw Exception("Broken SF2 file (broken pbag)");
1024 }
1025
1026 count = int(ck->GetSize() / 4);
1027 for (int i = 0; i < count; i++) {
1028 PresetBag pb;
1029 pb.GenNdx = ck->ReadInt16();
1030 pb.ModNdx = ck->ReadInt16();
1031 PresetBags.push_back(pb);
1032 }
1033 //std::cout << "Preset bags: " << PresetBags.size() << std::endl;
1034
1035 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_PMOD);
1036 if (ck->GetSize() % 10) {
1037 throw Exception("Broken SF2 file (broken pmod)");
1038 }
1039
1040 count = int(ck->GetSize() / 10);
1041 for (int i = 0; i < count; i++) {
1042 ModList ml;
1043 ml.ModSrcOper = ck->ReadInt16();
1044 ml.ModDestOper = ck->ReadInt16();
1045 ml.ModAmount = ck->ReadInt16();
1046 ml.ModAmtSrcOper = ck->ReadInt16();
1047 ml.ModTransOper = ck->ReadInt16();
1048 PresetModLists.push_back(ml);
1049 }
1050 //std::cout << "Preset mod lists: " << PresetModLists.size() << std::endl;
1051
1052 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_PGEN);
1053 if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
1054 throw Exception("Broken SF2 file (broken pgen)");
1055 }
1056
1057 count = int(ck->GetSize() / 4);
1058 for (int i = 0; i < count; i++) {
1059 GenList gl;
1060 gl.GenOper = ck->ReadInt16();
1061 gl.GenAmount.wAmount = ck->ReadInt16();
1062 PresetGenLists.push_back(gl);
1063 }
1064 //std::cout << "Preset gen lists: " << PresetGenLists.size() << std::endl;
1065
1066 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_INST);
1067 if (ck->GetSize() < (22 * 2) || (ck->GetSize() % 22)) {
1068 throw Exception("Broken SF2 file (broken inst)");
1069 }
1070 count = int(ck->GetSize() / 22);
1071 for (int i = 0; i < count; i++) {
1072 Instruments.push_back(new Instrument(this, ck));
1073 }
1074
1075 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_IBAG);
1076 if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
1077 throw Exception("Broken SF2 file (broken ibag)");
1078 }
1079
1080 count = int(ck->GetSize() / 4);
1081 for (int i = 0; i < count; i++) {
1082 InstBag ib;
1083 ib.InstGenNdx = ck->ReadInt16();
1084 ib.InstModNdx = ck->ReadInt16();
1085 InstBags.push_back(ib);
1086 }
1087 //std::cout << "Instrument bags: " << InstBags.size() << std::endl;
1088
1089 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_IMOD);
1090 if (ck->GetSize() % 10) {
1091 throw Exception("Broken SF2 file (broken imod)");
1092 }
1093
1094 count = int(ck->GetSize() / 10);
1095 for (int i = 0; i < count; i++) {
1096 ModList ml;
1097 ml.ModSrcOper = ck->ReadInt16();
1098 ml.ModDestOper = ck->ReadInt16();
1099 ml.ModAmount = ck->ReadInt16();
1100 ml.ModAmtSrcOper = ck->ReadInt16();
1101 ml.ModTransOper = ck->ReadInt16();
1102 InstModLists.push_back(ml);
1103 }
1104 //std::cout << "Instrument mod lists: " << InstModLists.size() << std::endl;
1105
1106 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_IGEN);
1107 if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
1108 throw Exception("Broken SF2 file (broken igen)");
1109 }
1110
1111 count = int(ck->GetSize() / 4);
1112 for (int i = 0; i < count; i++) {
1113 GenList gl;
1114 gl.GenOper = ck->ReadInt16();
1115 gl.GenAmount.wAmount = ck->ReadInt16();
1116 InstGenLists.push_back(gl);
1117 }
1118 //std::cout << "Instrument gen lists: " << InstGenLists.size() << std::endl;
1119
1120 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_SHDR);
1121 if ((ck->GetSize() % 46)) {
1122 throw Exception("Broken SF2 file (broken shdr)");
1123 }
1124 count = int(ck->GetSize() / 46);
1125 for (int i = 0; i < count; i++) {
1126 Samples.push_back(new Sample(this, ck, pCkSmpl, pCkSm24));
1127 }
1128
1129 // Loading instrument regions
1130 for (int i = 0; i < Instruments.size() - 1; i++) {
1131 Instrument* instr = Instruments[i];
1132 int x1 = instr->InstBagNdx;
1133 int x2 = Instruments[i + 1]->InstBagNdx;
1134 if (x1 < 0 || x2 < 0 || x1 > x2 || x2 >= InstBags.size()) {
1135 throw Exception("Broken SF2 file (invalid InstBagNdx)");
1136 }
1137
1138 instr->LoadRegions(x1, x2);
1139 }
1140
1141 // Loading preset regions
1142 for (int i = 0; i < Presets.size() - 1; i++) {
1143 Preset* preset = Presets[i];
1144 int x1 = preset->PresetBagNdx;
1145 int x2 = Presets[i + 1]->PresetBagNdx;
1146 if (x1 < 0 || x2 < 0 || x1 > x2 || x2 >= PresetBags.size()) {
1147 throw Exception("Broken SF2 file (invalid PresetBagNdx)");
1148 }
1149
1150 preset->LoadRegions(x1, x2);
1151 }
1152 }
1153
1154 File::~File() {
1155 delete pInfo;
1156 for (ssize_t i = Presets.size() - 1; i >= 0; i--) {
1157 if (Presets[i]) delete (Presets[i]);
1158 }
1159 for (ssize_t i = Instruments.size() - 1; i >= 0; i--) {
1160 if (Instruments[i]) delete (Instruments[i]);
1161 }
1162 for (ssize_t i = Samples.size() - 1; i >= 0; i--) {
1163 if (Samples[i]) delete (Samples[i]);
1164 }
1165 }
1166
1167 int File::GetPresetCount() {
1168 return (int) Presets.size() - 1; // exclude terminal preset (EOP)
1169 }
1170
1171 Preset* File::GetPreset(int idx) {
1172 if (idx < 0 || idx >= GetPresetCount()) {
1173 throw Exception("Preset index out of bounds");
1174 }
1175
1176 return Presets[idx];
1177 }
1178
1179 int File::GetInstrumentCount() {
1180 return (int) Instruments.size() - 1; // exclude terminal instrument (EOI)
1181 }
1182
1183 Instrument* File::GetInstrument(int idx) {
1184 if (idx < 0 || idx >= GetInstrumentCount()) {
1185 throw Exception("Instrument index out of bounds");
1186 }
1187
1188 return Instruments[idx];
1189 }
1190
1191 void File::DeleteInstrument(Instrument* pInstrument) {
1192 for (int i = 0; i < GetPresetCount(); i++) {
1193 Preset* p = GetPreset(i);
1194 if (p == NULL) continue;
1195 for (int j = p->GetRegionCount() - 1; j >= 0 ; j--) {
1196 if (p->GetRegion(j) && p->GetRegion(j)->pInstrument == pInstrument) {
1197 p->GetRegion(j)->pInstrument = NULL;
1198 }
1199 }
1200 }
1201
1202 for (int i = 0; i < GetInstrumentCount(); i++) {
1203 if (GetInstrument(i) == pInstrument) {
1204 Instruments[i] = NULL;
1205 delete pInstrument;
1206 }
1207 }
1208 }
1209
1210 int File::GetSampleCount() {
1211 return (int) Samples.size() - 1; // exclude terminal sample (EOS)
1212 }
1213
1214 Sample* File::GetSample(int idx) {
1215 if (idx < 0 || idx >= GetSampleCount()) {
1216 throw Exception("Sample index out of bounds");
1217 }
1218
1219 return Samples[idx];
1220 }
1221
1222 void File::DeleteSample(Sample* pSample) {
1223 // Sanity check
1224 for (int i = GetInstrumentCount() - 1; i >= 0; i--) {
1225 Instrument* pInstr = GetInstrument(i);
1226 if (pInstr == NULL) continue;
1227
1228 for (int j = pInstr->GetRegionCount() - 1; j >= 0 ; j--) {
1229 if (pInstr->GetRegion(j) && pInstr->GetRegion(j)->GetSample() == pSample) {
1230 std::cerr << "Deleting sample which is still in use" << std::endl;
1231 }
1232 }
1233 }
1234 ///////
1235
1236 for (int i = 0; i < GetSampleCount(); i++) {
1237 if (Samples[i] == pSample) {
1238 delete pSample;
1239 Samples[i] = NULL;
1240 return;
1241 }
1242 }
1243
1244 throw Exception("Unknown sample: " + pSample->Name);
1245 }
1246
1247 bool File::HasSamples() {
1248 for (int i = 0; i < GetSampleCount(); i++) {
1249 if (Samples[i] != NULL) return true;
1250 }
1251
1252 return false;
1253 }
1254
1255 RIFF::File* File::GetRiffFile() {
1256 return pRIFF;
1257 }
1258
1259 /**
1260 * Loads the whole sample wave into RAM. Use
1261 * ReleaseSampleData() to free the memory if you don't need the cached
1262 * sample data anymore.
1263 *
1264 * @returns buffer_t structure with start address and size of the buffer
1265 * in bytes
1266 * @see ReleaseSampleData(), Read(), SetPos()
1267 */
1268 Sample::buffer_t Sample::LoadSampleData() {
1269 return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), 0); // 0 amount of NullSamples
1270 }
1271
1272 /**
1273 * Reads and caches the first \a SampleCount
1274 * numbers of SamplePoints in RAM. Use ReleaseSampleData() to free the
1275 * memory space if you don't need the cached samples anymore.
1276 * Read the <i>Size</i> member of the <i>buffer_t</i> structure
1277 * that will be returned to determine the actual cached samples, but note
1278 * that the size is given in bytes! You get the number of actually cached
1279 * samples by dividing it by the frame size of the sample:
1280 * @code
1281 * buffer_t buf = pSample->LoadSampleData(acquired_samples);
1282 * long cachedsamples = buf.Size / pSample->FrameSize;
1283 * @endcode
1284 *
1285 * @param SampleCount - number of sample points to load into RAM
1286 * @returns buffer_t structure with start address and size of
1287 * the cached sample data in bytes
1288 * @see ReleaseSampleData(), Read(), SetPos()
1289 */
1290 Sample::buffer_t Sample::LoadSampleData(unsigned long SampleCount) {
1291 return LoadSampleDataWithNullSamplesExtension(SampleCount, 0); // 0 amount of NullSamples
1292 }
1293
1294 /**
1295 * Loads the whole sample wave into RAM. Use
1296 * ReleaseSampleData() to free the memory if you don't need the cached
1297 * sample data anymore.
1298 * The method will add \a NullSamplesCount silence samples past the
1299 * official buffer end (this won't affect the 'Size' member of the
1300 * buffer_t structure, that means 'Size' always reflects the size of the
1301 * actual sample data, the buffer might be bigger though). Silence
1302 * samples past the official buffer are needed for differential
1303 * algorithms that always have to take subsequent samples into account
1304 * (resampling/interpolation would be an important example) and avoids
1305 * memory access faults in such cases.
1306 *
1307 * @param NullSamplesCount - number of silence samples the buffer should
1308 * be extended past it's data end
1309 * @returns buffer_t structure with start address and
1310 * size of the buffer in bytes
1311 * @see ReleaseSampleData(), Read(), SetPos()
1312 */
1313 Sample::buffer_t Sample::LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount) {
1314 return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), NullSamplesCount);
1315 }
1316
1317 /**
1318 * Reads and caches the first \a SampleCount
1319 * numbers of SamplePoints in RAM. Use ReleaseSampleData() to free the
1320 * memory space if you don't need the cached samples anymore.
1321 * Read the <i>Size</i> member of the <i>buffer_t</i> structure
1322 * that will be returned to determine the actual cached samples, but note
1323 * that the size is given in bytes! You get the number of actually cached
1324 * samples by dividing it by the frame size of the sample:
1325 * @code
1326 * buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(acquired_samples, null_samples);
1327 * long cachedsamples = buf.Size / pSample->FrameSize;
1328 * @endcode
1329 * The method will add \a NullSamplesCount silence samples past the
1330 * official buffer end (this won't affect the 'Size' member of the
1331 * buffer_t structure, that means 'Size' always reflects the size of the
1332 * actual sample data, the buffer might be bigger though). Silence
1333 * samples past the official buffer are needed for differential
1334 * algorithms that always have to take subsequent samples into account
1335 * (resampling/interpolation would be an important example) and avoids
1336 * memory access faults in such cases.
1337 *
1338 * @param SampleCount - number of sample points to load into RAM
1339 * @param NullSamplesCount - number of silence samples the buffer should
1340 * be extended past it's data end
1341 * @returns buffer_t structure with start address and
1342 * size of the cached sample data in bytes
1343 * @see ReleaseSampleData(), Read(), SetPos()
1344 */
1345 Sample::buffer_t Sample::LoadSampleDataWithNullSamplesExtension(unsigned long SampleCount, uint NullSamplesCount) {
1346 if (SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount();
1347 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
1348 unsigned long allocationsize = (SampleCount + NullSamplesCount) * GetFrameSize();
1349 SetPos(0); // reset read position to begin of sample
1350 RAMCache.pStart = new int8_t[allocationsize];
1351 RAMCache.Size = Read(RAMCache.pStart, SampleCount) * GetFrameSize();
1352 RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
1353 // fill the remaining buffer space with silence samples
1354 memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
1355 return GetCache();
1356 }
1357
1358 /**
1359 * Returns current cached sample points. A buffer_t structure will be
1360 * returned which contains address pointer to the begin of the cache and
1361 * the size of the cached sample data in bytes. Use
1362 * <i>LoadSampleData()</i> to cache a specific amount of sample points in
1363 * RAM.
1364 *
1365 * @returns buffer_t structure with current cached sample points
1366 * @see LoadSampleData();
1367 */
1368 Sample::buffer_t Sample::GetCache() {
1369 // return a copy of the buffer_t structure
1370 buffer_t result;
1371 result.Size = this->RAMCache.Size;
1372 result.pStart = this->RAMCache.pStart;
1373 result.NullExtensionSize = this->RAMCache.NullExtensionSize;
1374 return result;
1375 }
1376
1377 /**
1378 * Frees the cached sample from RAM if loaded with
1379 * <i>LoadSampleData()</i> previously.
1380 *
1381 * @see LoadSampleData();
1382 */
1383 void Sample::ReleaseSampleData() {
1384 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
1385 RAMCache.pStart = NULL;
1386 RAMCache.Size = 0;
1387 RAMCache.NullExtensionSize = 0;
1388 }
1389
1390 /**
1391 * Sets the position within the sample (in sample points, not in
1392 * bytes). Use this method and <i>Read()</i> if you don't want to load
1393 * the sample into RAM, thus for disk streaming.
1394 *
1395 * @param SampleCount number of sample points to jump
1396 * @returns the new sample position
1397 * @see Read()
1398 */
1399 unsigned long Sample::SetPos(unsigned long SampleCount) {
1400 pCkSmpl->SetPos((Start * 2) + (SampleCount * 2), RIFF::stream_start);
1401 if(pCkSm24) pCkSm24->SetPos(Start + SampleCount, RIFF::stream_start);
1402 return SampleCount;
1403 }
1404
1405 /**
1406 * Returns the current position in the sample (in sample points).
1407 */
1408 unsigned long Sample::GetPos() {
1409 return (pCkSmpl->GetPos() - (Start * 2)) / 2;
1410 }
1411
1412 // Actual implementation of Sample::Read*() code. Wrapped into a template for a) runtime effeciency and b) code redundancy reasons.
1413 template<bool CLEAR>
1414 inline unsigned long ReadSample(Sample* pSample, void* pBuffer, unsigned long SampleCount, Sample::buffer_t* tempBuffer = NULL) {
1415 // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
1416 if (SampleCount == 0) return 0;
1417 long pos = pSample->GetPos();
1418 if (pos + SampleCount > pSample->GetTotalFrameCount())
1419 SampleCount = pSample->GetTotalFrameCount() - pos;
1420 if (!CLEAR) {
1421 if (tempBuffer->Size < SampleCount * pSample->GetFrameSize()) {
1422 std::cerr << "sf2::Sample error: tempBuffer too small. This is a BUG!" << std::endl;
1423 return 0;
1424 }
1425 }
1426
1427 if (pSample->GetFrameSize() / pSample->GetChannelCount() == 3 /* 24 bit */) {
1428 uint8_t* const pTmpBuf = (uint8_t*) ((CLEAR) ? pBuffer : tempBuffer->pStart);
1429 uint8_t* const pBuf = (uint8_t*)pBuffer;
1430 if (pSample->SampleType == Sample::MONO_SAMPLE || pSample->SampleType == Sample::ROM_MONO_SAMPLE) {
1431 pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1432 pSample->pCkSm24->Read(pTmpBuf + SampleCount * 2, SampleCount, 1);
1433 for (long i = SampleCount - 1; i >= 0; i--) {
1434 pBuf[i*3] = pTmpBuf[(SampleCount * 2) + i];
1435 pBuf[i*3 + 2] = pTmpBuf[i*2 + 1];
1436 pBuf[i*3 + 1] = pTmpBuf[i*2];
1437 }
1438 } else if (pSample->SampleType == Sample::LEFT_SAMPLE || pSample->SampleType == Sample::ROM_LEFT_SAMPLE) {
1439 pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1440 pSample->pCkSm24->Read(pTmpBuf + SampleCount * 2, SampleCount, 1);
1441 for (long i = SampleCount - 1; i >= 0; i--) {
1442 pBuf[i*6] = pTmpBuf[(SampleCount * 2) + i];
1443 pBuf[i*6 + 2] = pTmpBuf[i*2 + 1];
1444 pBuf[i*6 + 1] = pTmpBuf[i*2];
1445 if (CLEAR)
1446 pBuf[i*6 + 3] = pBuf[i*6 + 4] = pBuf[i*6 + 5] = 0;
1447 }
1448 } else if (pSample->SampleType == Sample::RIGHT_SAMPLE || pSample->SampleType == Sample::ROM_RIGHT_SAMPLE) {
1449 pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1450 pSample->pCkSm24->Read(pTmpBuf + SampleCount * 2, SampleCount, 1);
1451 for (long i = SampleCount - 1; i >= 0; i--) {
1452 pBuf[i*6 + 3] = pTmpBuf[(SampleCount * 2) + i];
1453 pBuf[i*6 + 5] = pTmpBuf[i*2 + 1];
1454 pBuf[i*6 + 4] = pTmpBuf[i*2];
1455 if (CLEAR)
1456 pBuf[i*6] = pBuf[i*6 + 1] = pBuf[i*6 + 2] = 0;
1457 }
1458 }
1459 } else {
1460 if (pSample->SampleType == Sample::MONO_SAMPLE || pSample->SampleType == Sample::ROM_MONO_SAMPLE) {
1461 return pSample->pCkSmpl->Read(pBuffer, SampleCount, 2);
1462 }
1463
1464 int16_t* const pTmpBuf = (int16_t*) ((CLEAR) ? pBuffer : tempBuffer->pStart);
1465 int16_t* const pBuf = (int16_t*) pBuffer;
1466 if (pSample->SampleType == Sample::LEFT_SAMPLE || pSample->SampleType == Sample::ROM_LEFT_SAMPLE) {
1467 pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1468 for (long i = SampleCount - 1; i >= 0; i--) {
1469 pBuf[i*2] = pTmpBuf[i];
1470 if (CLEAR)
1471 pBuf[i*2 + 1] = 0;
1472 }
1473 } else if (pSample->SampleType == Sample::RIGHT_SAMPLE || pSample->SampleType == Sample::ROM_RIGHT_SAMPLE) {
1474 pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1475 for (long i = SampleCount - 1; i >= 0; i--) {
1476 if (CLEAR)
1477 pBuf[i*2] = 0;
1478 pBuf[i*2 + 1] = pTmpBuf[i];
1479 }
1480 }
1481 }
1482
1483 if (pSample->pCkSmpl->GetPos() > (pSample->End * 2)) {
1484 std::cerr << "Read after the sample end. This is a BUG!" << std::endl;
1485 std::cerr << "Current position: " << pSample->GetPos() << std::endl;
1486 std::cerr << "Total number of frames: " << pSample->GetTotalFrameCount() << std::endl << std::endl;
1487 }
1488 return SampleCount;
1489 }
1490
1491 /**
1492 * Reads \a SampleCount number of sample points from the current
1493 * position into the buffer pointed by \a pBuffer and increments the
1494 * position within the sample. Use this method
1495 * and <i>SetPos()</i> if you don't want to load the sample into RAM,
1496 * thus for disk streaming.
1497 *
1498 * For 16 bit samples, the data in the buffer will be int16_t
1499 * (using native endianness). For 24 bit, the buffer will
1500 * contain three bytes per sample, little-endian.
1501 *
1502 * Stereo Samples: stereo samples are stored as a pair of mono samples with
1503 * SoundFont 2. Due to historical reasons, this Read() method expects
1504 * @a pBuffer to be a stereo buffer, however only the audio channel covered
1505 * by the sample data of this sample will be filled. The other audio channel
1506 * of @a pBuffer will be set to zero. This is probably not what you want.
1507 * So you might want to use ReadNoClear() instead.
1508 *
1509 * @param pBuffer destination buffer
1510 * @param SampleCount number of sample points to read
1511 * @returns number of successfully read sample points
1512 * @see SetPos(), ReadNoClear()
1513 */
1514 unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
1515 return ReadSample<true>(this, pBuffer, SampleCount);
1516 }
1517
1518 /**
1519 * Reads \a SampleCount number of sample points from the current
1520 * position into the buffer pointed by \a pBuffer and increments the
1521 * position within the sample. Use this method
1522 * and <i>SetPos()</i> if you don't want to load the sample into RAM,
1523 * thus for disk streaming.
1524 *
1525 * For 16 bit samples, the data in the buffer will be int16_t
1526 * (using native endianness). For 24 bit, the buffer will
1527 * contain three bytes per sample, little-endian.
1528 *
1529 * Stereo Samples: stereo samples are stored as a pair of mono samples with
1530 * SoundFont 2. This ReadNoClear() method expects @a pBuffer to be a stereo
1531 * buffer, however only the audio channel covered by the sample data of this
1532 * sample will be filled. The other audio channel
1533 * of @a pBuffer will remain untouched. So you might pass the same
1534 * @a pBuffer to the other, linked sample to actually get the interleaved
1535 * stereo audio stream. To avoid destroying the other audio channel's data
1536 * you must pass an external, tempoary working buffer @a tempBuffer, which
1537 * should already be allocated to the size required to decode the requested
1538 * length of sample data. That @a tempBuffer is only used by ReadNoClear()
1539 * to fulfill its work, it does not contain any useful data after this
1540 * method returned.
1541 *
1542 * @param pBuffer destination buffer
1543 * @param SampleCount number of sample points to read
1544 * @param tempBuffer temporary work buffer (must be pre-allocated large enough)
1545 * @returns number of successfully read sample points
1546 * @see SetPos(), Read()
1547 */
1548 unsigned long Sample::ReadNoClear(void* pBuffer, unsigned long SampleCount, buffer_t& tempBuffer) {
1549 return ReadSample<false>(this, pBuffer, SampleCount, &tempBuffer);
1550 }
1551
1552
1553 // *************** functions ***************
1554 // *
1555
1556 /**
1557 * Returns the name of this C++ library.
1558 */
1559 String libraryName() {
1560 return PACKAGE;
1561 }
1562
1563 /**
1564 * Returns version of this C++ library.
1565 */
1566 String libraryVersion() {
1567 return VERSION;
1568 }
1569
1570 } // namespace sf2

  ViewVC Help
Powered by ViewVC