libgig  4.4.1
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  if (!pInstrument) return;
1193 
1194  for (int i = 0; i < GetPresetCount(); i++) {
1195  Preset* p = GetPreset(i);
1196  if (p == NULL) continue;
1197  for (int j = p->GetRegionCount() - 1; j >= 0 ; j--) {
1198  if (p->GetRegion(j) && p->GetRegion(j)->pInstrument == pInstrument) {
1199  p->GetRegion(j)->pInstrument = NULL;
1200  }
1201  }
1202  }
1203 
1204  for (int i = 0; i < GetInstrumentCount(); i++) {
1205  if (GetInstrument(i) == pInstrument) {
1206  Instruments[i] = NULL;
1207  delete pInstrument;
1208  // an instrument instance only exists once in the list, so stop
1209  // here (which also silences a clang sanatizer warning about
1210  // potential multiple memory releases of pInstrument above)
1211  return;
1212  }
1213  }
1214  }
1215 
1216  int File::GetSampleCount() {
1217  return (int) Samples.size() - 1; // exclude terminal sample (EOS)
1218  }
1219 
1220  Sample* File::GetSample(int idx) {
1221  if (idx < 0 || idx >= GetSampleCount()) {
1222  throw Exception("Sample index out of bounds");
1223  }
1224 
1225  return Samples[idx];
1226  }
1227 
1228  void File::DeleteSample(Sample* pSample) {
1229  // Sanity check
1230  for (int i = GetInstrumentCount() - 1; i >= 0; i--) {
1231  Instrument* pInstr = GetInstrument(i);
1232  if (pInstr == NULL) continue;
1233 
1234  for (int j = pInstr->GetRegionCount() - 1; j >= 0 ; j--) {
1235  if (pInstr->GetRegion(j) && pInstr->GetRegion(j)->GetSample() == pSample) {
1236  std::cerr << "Deleting sample which is still in use" << std::endl;
1237  }
1238  }
1239  }
1241 
1242  for (int i = 0; i < GetSampleCount(); i++) {
1243  if (Samples[i] == pSample) {
1244  delete pSample;
1245  Samples[i] = NULL;
1246  return;
1247  }
1248  }
1249 
1250  throw Exception("Unknown sample: " + pSample->Name);
1251  }
1252 
1253  bool File::HasSamples() {
1254  for (int i = 0; i < GetSampleCount(); i++) {
1255  if (Samples[i] != NULL) return true;
1256  }
1257 
1258  return false;
1259  }
1260 
1261  RIFF::File* File::GetRiffFile() {
1262  return pRIFF;
1263  }
1264 
1274  Sample::buffer_t Sample::LoadSampleData() {
1275  return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), 0); // 0 amount of NullSamples
1276  }
1277 
1296  Sample::buffer_t Sample::LoadSampleData(unsigned long SampleCount) {
1297  return LoadSampleDataWithNullSamplesExtension(SampleCount, 0); // 0 amount of NullSamples
1298  }
1299 
1319  Sample::buffer_t Sample::LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount) {
1320  return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), NullSamplesCount);
1321  }
1322 
1351  Sample::buffer_t Sample::LoadSampleDataWithNullSamplesExtension(unsigned long SampleCount, uint NullSamplesCount) {
1352  if (SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount();
1353  if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
1354  unsigned long allocationsize = (SampleCount + NullSamplesCount) * GetFrameSize();
1355  SetPos(0); // reset read position to begin of sample
1356  RAMCache.pStart = new int8_t[allocationsize];
1357  RAMCache.Size = Read(RAMCache.pStart, SampleCount) * GetFrameSize();
1358  RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
1359  // fill the remaining buffer space with silence samples
1360  memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
1361  return GetCache();
1362  }
1363 
1374  Sample::buffer_t Sample::GetCache() {
1375  // return a copy of the buffer_t structure
1376  buffer_t result;
1377  result.Size = this->RAMCache.Size;
1378  result.pStart = this->RAMCache.pStart;
1379  result.NullExtensionSize = this->RAMCache.NullExtensionSize;
1380  return result;
1381  }
1382 
1389  void Sample::ReleaseSampleData() {
1390  if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
1391  RAMCache.pStart = NULL;
1392  RAMCache.Size = 0;
1393  RAMCache.NullExtensionSize = 0;
1394  }
1395 
1405  unsigned long Sample::SetPos(unsigned long SampleCount) {
1406  pCkSmpl->SetPos((Start * 2) + (SampleCount * 2), RIFF::stream_start);
1407  if(pCkSm24) pCkSm24->SetPos(Start + SampleCount, RIFF::stream_start);
1408  return SampleCount;
1409  }
1410 
1414  unsigned long Sample::GetPos() {
1415  return (pCkSmpl->GetPos() - (Start * 2)) / 2;
1416  }
1417 
1418  // Actual implementation of Sample::Read*() code. Wrapped into a template for a) runtime effeciency and b) code redundancy reasons.
1419  template<bool CLEAR>
1420  inline unsigned long ReadSample(Sample* pSample, void* pBuffer, unsigned long SampleCount, Sample::buffer_t* tempBuffer = NULL) {
1421  // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
1422  if (SampleCount == 0) return 0;
1423  long pos = pSample->GetPos();
1424  if (pos + SampleCount > pSample->GetTotalFrameCount())
1425  SampleCount = pSample->GetTotalFrameCount() - pos;
1426  if (!CLEAR) {
1427  if (tempBuffer->Size < SampleCount * pSample->GetFrameSize()) {
1428  std::cerr << "sf2::Sample error: tempBuffer too small. This is a BUG!" << std::endl;
1429  return 0;
1430  }
1431  }
1432 
1433  if (pSample->GetFrameSize() / pSample->GetChannelCount() == 3 /* 24 bit */) {
1434  uint8_t* const pTmpBuf = (uint8_t*) ((CLEAR) ? pBuffer : tempBuffer->pStart);
1435  uint8_t* const pBuf = (uint8_t*)pBuffer;
1436  if (pSample->SampleType == Sample::MONO_SAMPLE || pSample->SampleType == Sample::ROM_MONO_SAMPLE) {
1437  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1438  pSample->pCkSm24->Read(pTmpBuf + SampleCount * 2, SampleCount, 1);
1439  for (long i = SampleCount - 1; i >= 0; i--) {
1440  pBuf[i*3] = pTmpBuf[(SampleCount * 2) + i];
1441  pBuf[i*3 + 2] = pTmpBuf[i*2 + 1];
1442  pBuf[i*3 + 1] = pTmpBuf[i*2];
1443  }
1444  } else if (pSample->SampleType == Sample::LEFT_SAMPLE || pSample->SampleType == Sample::ROM_LEFT_SAMPLE) {
1445  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1446  pSample->pCkSm24->Read(pTmpBuf + SampleCount * 2, SampleCount, 1);
1447  for (long i = SampleCount - 1; i >= 0; i--) {
1448  pBuf[i*6] = pTmpBuf[(SampleCount * 2) + i];
1449  pBuf[i*6 + 2] = pTmpBuf[i*2 + 1];
1450  pBuf[i*6 + 1] = pTmpBuf[i*2];
1451  if (CLEAR)
1452  pBuf[i*6 + 3] = pBuf[i*6 + 4] = pBuf[i*6 + 5] = 0;
1453  }
1454  } else if (pSample->SampleType == Sample::RIGHT_SAMPLE || pSample->SampleType == Sample::ROM_RIGHT_SAMPLE) {
1455  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1456  pSample->pCkSm24->Read(pTmpBuf + SampleCount * 2, SampleCount, 1);
1457  for (long i = SampleCount - 1; i >= 0; i--) {
1458  pBuf[i*6 + 3] = pTmpBuf[(SampleCount * 2) + i];
1459  pBuf[i*6 + 5] = pTmpBuf[i*2 + 1];
1460  pBuf[i*6 + 4] = pTmpBuf[i*2];
1461  if (CLEAR)
1462  pBuf[i*6] = pBuf[i*6 + 1] = pBuf[i*6 + 2] = 0;
1463  }
1464  }
1465  } else {
1466  if (pSample->SampleType == Sample::MONO_SAMPLE || pSample->SampleType == Sample::ROM_MONO_SAMPLE) {
1467  return pSample->pCkSmpl->Read(pBuffer, SampleCount, 2);
1468  }
1469 
1470  int16_t* const pTmpBuf = (int16_t*) ((CLEAR) ? pBuffer : tempBuffer->pStart);
1471  int16_t* const pBuf = (int16_t*) pBuffer;
1472  if (pSample->SampleType == Sample::LEFT_SAMPLE || pSample->SampleType == Sample::ROM_LEFT_SAMPLE) {
1473  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1474  for (long i = SampleCount - 1; i >= 0; i--) {
1475  pBuf[i*2] = pTmpBuf[i];
1476  if (CLEAR)
1477  pBuf[i*2 + 1] = 0;
1478  }
1479  } else if (pSample->SampleType == Sample::RIGHT_SAMPLE || pSample->SampleType == Sample::ROM_RIGHT_SAMPLE) {
1480  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1481  for (long i = SampleCount - 1; i >= 0; i--) {
1482  if (CLEAR)
1483  pBuf[i*2] = 0;
1484  pBuf[i*2 + 1] = pTmpBuf[i];
1485  }
1486  }
1487  }
1488 
1489  if (pSample->pCkSmpl->GetPos() > (pSample->End * 2)) {
1490  std::cerr << "Read after the sample end. This is a BUG!" << std::endl;
1491  std::cerr << "Current position: " << pSample->GetPos() << std::endl;
1492  std::cerr << "Total number of frames: " << pSample->GetTotalFrameCount() << std::endl << std::endl;
1493  }
1494  return SampleCount;
1495  }
1496 
1520  unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
1521  return ReadSample<true>(this, pBuffer, SampleCount);
1522  }
1523 
1554  unsigned long Sample::ReadNoClear(void* pBuffer, unsigned long SampleCount, buffer_t& tempBuffer) {
1555  return ReadSample<false>(this, pBuffer, SampleCount, &tempBuffer);
1556  }
1557 
1558 
1559 // *************** functions ***************
1560 // *
1561 
1565  String libraryName() {
1566  return PACKAGE;
1567  }
1568 
1572  String libraryVersion() {
1573  return VERSION;
1574  }
1575 
1576 } // namespace sf2
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:710
file_offset_t GetSize() const
Chunk size in bytes (without header, thus the chunk data body)
Definition: RIFF.h:186
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:749
Instrument zone.
Definition: SF.h:355
String libraryVersion()
Returns version of this C++ library.
Definition: SF.cpp:1572
file_offset_t Size
Size of the actual data in the buffer in bytes.
Definition: gig.h:116
String libraryName()
Returns the name of this C++ library.
Definition: SF.cpp:1565
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
List * GetSubList(uint32_t ListType)
Returns sublist chunk with list type ListType within this chunk list.
Definition: RIFF.cpp:1287
SoundFont specific classes and definitions.
Definition: SF.h:62
RIFF List Chunk.
Definition: RIFF.h:261
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:341
Chunk * GetSubChunk(uint32_t ChunkID)
Returns subchunk with chunk ID ChunkID within this chunk list.
Definition: RIFF.cpp:1246
Ordinary RIFF Chunk.
Definition: RIFF.h:179
uint32_t GetChunkID() const
Chunk ID in unsigned integer representation.
Definition: RIFF.h:183
uint32_t GetListType() const
Returns unsigned integer representation of the list&#39;s ID.
Definition: RIFF.h:265
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:593
Pointer address and size of a buffer.
Definition: SF.h:288
RIFF File.
Definition: RIFF.h:313
file_offset_t GetPos() const
Current read/write position within the chunk data body (starting with 0).
Definition: RIFF.cpp:311
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:671