libgig  4.3.0
SF.cpp
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 
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 
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 
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 
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 
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 
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  }
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 
1268  Sample::buffer_t Sample::LoadSampleData() {
1269  return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), 0); // 0 amount of NullSamples
1270  }
1271 
1290  Sample::buffer_t Sample::LoadSampleData(unsigned long SampleCount) {
1291  return LoadSampleDataWithNullSamplesExtension(SampleCount, 0); // 0 amount of NullSamples
1292  }
1293 
1313  Sample::buffer_t Sample::LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount) {
1314  return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), NullSamplesCount);
1315  }
1316 
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 
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 
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 
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 
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 
1514  unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
1515  return ReadSample<true>(this, pBuffer, SampleCount);
1516  }
1517 
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 
1559  String libraryName() {
1560  return PACKAGE;
1561  }
1562 
1566  String libraryVersion() {
1567  return VERSION;
1568  }
1569 
1570 } // namespace sf2
Ordinary RIFF Chunk.
Definition: RIFF.h:232
file_offset_t ReadInt8(int8_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 8 Bit signed integer words and copies it into the buffer pointed by pData.
Definition: RIFF.cpp:517
file_offset_t SetPos(file_offset_t Where, stream_whence_t Whence=stream_start)
Sets the position within the chunk body, thus within the data portion of the chunk (in bytes).
Definition: RIFF.cpp:280
file_offset_t GetPos() const
Position within the chunk data body (starting with 0).
Definition: RIFF.h:241
file_offset_t ReadUint16(uint16_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 16 Bit unsigned integer words and copies it into the buffer pointed by pDat...
Definition: RIFF.cpp:628
file_offset_t ReadInt16(int16_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 16 Bit signed integer words and copies it into the buffer pointed by pData.
Definition: RIFF.cpp:591
uint32_t GetChunkID() const
Chunk ID in unsigned integer representation.
Definition: RIFF.h:236
file_offset_t ReadInt32(int32_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 32 Bit signed integer words and copies it into the buffer pointed by pData.
Definition: RIFF.cpp:665
file_offset_t GetSize() const
Chunk size in bytes (without header, thus the chunk data body)
Definition: RIFF.h:239
RIFF File.
Definition: RIFF.h:358
RIFF List Chunk.
Definition: RIFF.h:308
Chunk * GetSubChunk(uint32_t ChunkID)
Returns subchunk with chunk ID ChunkID within this chunk list.
Definition: RIFF.cpp:1128
List * GetSubList(uint32_t ListType)
Returns sublist chunk with list type ListType within this chunk list.
Definition: RIFF.cpp:1147
uint32_t GetListType() const
Returns unsigned integer representation of the list's ID.
Definition: RIFF.h:312
uint32_t Version
Version number data type.
SoundFont specific classes and definitions.
Definition: SF.h:62
void VerifySize(RIFF::Chunk *ck, int size)
Throws an error if the chunk is NULL or the chunk data size is less than size (in bytes).
Definition: SF.cpp:77
file_offset_t Size
Size of the actual data in the buffer in bytes.
Definition: gig.h:116