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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2381 - (show annotations) (download)
Sun Dec 2 16:30:30 2012 UTC (11 years, 4 months ago) by persson
File size: 60671 byte(s)
* sf2 bugfix: GetPan always returned -1, 0 or 1

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

  ViewVC Help
Powered by ViewVC