libgig  4.0.0
SF.cpp
Go to the documentation of this file.
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 
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 
94  ModSrcOper(Modulator(mod.ModSrcOper)),
95  ModAmtSrcOper(Modulator(mod.ModAmtSrcOper))
96  {
97 
98  }
99 
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 
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);
126  LoadString(CHUNK_ID_IPRD, lstINFO, Product);
128  LoadString(CHUNK_ID_ICMT, lstINFO, Comments);
129  LoadString(CHUNK_ID_ISFT, lstINFO, Software);
130 
131  }
132  }
133  }
134 
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 
151  this->pCkSmpl = pCkSmpl;
152  this->pCkSm24 = pCkSm24;
153 
154  LoadString(ck, Name, 20);
155  Start = ck->ReadInt32();
156  End = ck->ReadInt32();
157  StartLoop = ck->ReadInt32();
158  EndLoop = ck->ReadInt32();
159  SampleRate = ck->ReadInt32();
160  OriginalPitch = ck->ReadInt8();
161  PitchCorrection = ck->ReadInt8();
162  SampleLink = ck->ReadInt16();
163  SampleType = ck->ReadInt16();
164 
165  if (Start > End || !pCkSmpl || pCkSmpl->GetSize() <= End) {
166  throw Exception("Broken SF2 file (invalid sample info)");
167  }
168 
169  ChannelCount = 1;
170  switch(SampleType) {
171  case 0 : // terminal sample
173  case sf2::Sample::ROM_MONO_SAMPLE : break;
177  case sf2::Sample::ROM_LEFT_SAMPLE : ChannelCount = 2; break;
179  case sf2::Sample::ROM_LINKED_SAMPLE : std::cerr << "Linked samples not implemented yet"; break;
180  default: throw Exception("Broken SF2 file (invalid sample type)");
181  }
182 
183  RAMCache.Size = 0;
184  RAMCache.pStart = NULL;
186  }
187 
189  return ChannelCount;
190  }
191 
193  return (End - Start);
194  }
195 
200  return ChannelCount * ((pCkSm24 != NULL) ? 3 : 2);
201  }
202 
204  return StartLoop != 0 && EndLoop != 0;
205  }
206 
233  unsigned long Sample::ReadAndLoop (
234  void* pBuffer,
235  unsigned long FrameCount,
236  PlaybackState* pPlaybackState,
237  Region* pRegion
238  ) {
239  // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
240  unsigned long samplestoread = FrameCount, totalreadsamples = 0, readsamples, samplestoloopend;
241  uint8_t* pDst = (uint8_t*) pBuffer;
242  SetPos(pPlaybackState->position);
243  if (pRegion->HasLoop) {
244  do {
245  samplestoloopend = pRegion->LoopEnd - GetPos();
246  readsamples = Read(&pDst[totalreadsamples * GetFrameSize()], Min(samplestoread, samplestoloopend));
247  samplestoread -= readsamples;
248  totalreadsamples += readsamples;
249  if (readsamples == samplestoloopend) {
250  SetPos(pRegion->LoopStart);
251  }
252  } while (samplestoread && readsamples);
253  } else {
254  totalreadsamples = Read(pBuffer, FrameCount);
255  }
256 
257  pPlaybackState->position = GetPos();
258 
259  return totalreadsamples;
260  }
261 
263  pSample = NULL;
264  pInstrument = NULL;
265  pParentInstrument = NULL;
266  loKey = hiKey = NONE;
267  minVel = maxVel = NONE;
270  pan = fineTune = coarseTune = 0;
271  overridingRootKey = -1; // -1 means not used
272 
273  HasLoop = false;
274  LoopStart = LoopEnd = 0;
275 
276  EG1PreAttackDelay = EG1Attack = EG1Hold = EG1Decay = EG1Release = -12000;
277  EG1Sustain = 0;
278  EG2PreAttackDelay = EG2Attack = EG2Hold = EG2Decay = EG2Release = -12000;
279  EG2Sustain = 0;
280 
282  freqModLfo = 0;
283  delayModLfo = -12000;
284  vibLfoToPitch = 0;
285  freqVibLfo = 0;
286  delayVibLfo = -12000;
287 
288  exclusiveClass = 0;
289 
290  initialFilterFc = 13500;
291  initialFilterQ = 0;
292  }
293 
296  }
297 
298  int CheckRange(std::string genName, int min, int max, int& gen) {
299  if (gen == NONE) return gen;
300 
301  if (gen < min) {
302  std::cerr << "sf2: " << genName;
303  std::cerr << " is below the minimum allowed value (min=" << min << "): " << gen << std::endl;
304  gen = min;
305  }
306  if (gen > max) {
307  std::cerr << "sf2: " << genName;
308  std::cerr << " is above the maximum allowed value (max=" << max << "): " << gen << std::endl;
309  gen = max;
310  }
311 
312  return gen;
313  }
314 
315  void Region::SetGenerator(sf2::File* pFile, GenList& Gen) {
316  switch(Gen.GenOper) {
317  case START_ADDRS_OFFSET:
318  startAddrsOffset = Gen.GenAmount.wAmount;
319  break;
320  case END_ADDRS_OFFSET:
321  if (Gen.GenAmount.shAmount <= 0) {
322  endAddrsOffset = Gen.GenAmount.shAmount;
323  } else {
324  std::cerr << "Ignoring invalid endAddrsOffset" << std::endl;
325  }
326  break;
328  startloopAddrsOffset = Gen.GenAmount.shAmount;
330  break;
332  endloopAddrsOffset = Gen.GenAmount.shAmount;
334  break;
336  startAddrsCoarseOffset = Gen.GenAmount.wAmount;
337  break;
338  case MOD_LFO_TO_PITCH:
339  modLfoToPitch = Gen.GenAmount.shAmount;
340  CheckRange("modLfoToPitch", -12000, 12000, modLfoToPitch);
341  break;
342  case VIB_LFO_TO_PITCH:
343  vibLfoToPitch = Gen.GenAmount.shAmount;
344  CheckRange("vibLfoToPitch", -12000, 12000, vibLfoToPitch);
345  break;
346  case MOD_ENV_TO_PITCH:
347  modEnvToPitch = Gen.GenAmount.shAmount;
348  CheckRange("modEnvToPitch", -12000, 12000, modEnvToPitch);
349  break;
350  case INITIAL_FILTER_FC:
351  initialFilterFc = Gen.GenAmount.wAmount;
352  CheckRange("initialFilterFc", 1500, 13500, initialFilterFc);
353  break;
354  case INITIAL_FILTER_Q:
355  initialFilterQ = Gen.GenAmount.wAmount;
356  CheckRange("initialFilterQ", 0, 960, initialFilterQ);
357  break;
359  modLfoToFilterFc = Gen.GenAmount.shAmount;
360  CheckRange("modLfoToFilterFc", -12000, 12000, modLfoToFilterFc);
361  break;
363  modEnvToFilterFc = Gen.GenAmount.shAmount;
364  CheckRange("modEnvToFilterFc", -12000, 12000, modEnvToFilterFc);
365  break;
367  endAddrsCoarseOffset = Gen.GenAmount.wAmount;
368  break;
369  case MOD_LFO_TO_VOLUME:
370  modLfoToVolume = Gen.GenAmount.shAmount;
371  CheckRange("modLfoToVolume", -960, 960, modLfoToVolume);
372  break;
373  case CHORUS_EFFECTS_SEND:
374  break;
375  case REVERB_EFFECTS_SEND:
376  break;
377  case PAN:
378  pan = Gen.GenAmount.shAmount;
379  CheckRange("pan", -500, 500, pan);
380  pan = pan * 64 / 500;
381  if (pan > 63) pan = 63;
382  break;
383  case DELAY_MOD_LFO:
384  delayModLfo = Gen.GenAmount.shAmount;
385  CheckRange("delayModLfo", -12000, 5000, delayModLfo);
386  break;
387  case FREQ_MOD_LFO:
388  freqModLfo = Gen.GenAmount.shAmount;
389  CheckRange("freqModLfo", -16000, 4500, freqModLfo);
390  break;
391  case DELAY_VIB_LFO:
392  delayVibLfo = Gen.GenAmount.shAmount;
393  CheckRange("delayVibLfo", -12000, 5000, delayVibLfo);
394  break;
395  case FREQ_VIB_LFO:
396  freqVibLfo = Gen.GenAmount.shAmount;
397  CheckRange("freqModLfo", -16000, 4500, freqModLfo);
398  break;
399  case DELAY_MOD_ENV:
400  EG2PreAttackDelay = Gen.GenAmount.shAmount;
401  CheckRange("delayModEnv", -12000, 5000, EG2PreAttackDelay);
402  break;
403  case ATTACK_MOD_ENV:
404  EG2Attack = Gen.GenAmount.shAmount;
405  CheckRange("attackModEnv", -12000, 8000, EG2Attack);
406  break;
407  case HOLD_MOD_ENV:
408  EG2Hold = Gen.GenAmount.shAmount;
409  CheckRange("holdModEnv", -12000, 5000, EG2Hold);
410  break;
411  case DECAY_MOD_ENV:
412  EG2Decay = Gen.GenAmount.shAmount;
413  CheckRange("decayModEnv", -12000, 8000, EG2Decay);
414  break;
415  case SUSTAIN_MOD_ENV:
416  EG2Sustain = Gen.GenAmount.shAmount;
417  CheckRange("sustainModEnv", 0, 1000, EG2Sustain);
418  break;
419  case RELEASE_MOD_ENV:
420  EG2Release = Gen.GenAmount.shAmount;
421  CheckRange("releaseModEnv", -12000, 8000, EG2Release);
422  break;
424  break;
426  break;
427  case DELAY_VOL_ENV:
428  EG1PreAttackDelay = Gen.GenAmount.shAmount;
429  CheckRange("delayVolEnv", -12000, 5000, EG1PreAttackDelay);
430  break;
431  case ATTACK_VOL_ENV:
432  EG1Attack = Gen.GenAmount.shAmount;
433  CheckRange("attackVolEnv", -12000, 8000, EG1Attack);
434  break;
435  case HOLD_VOL_ENV:
436  EG1Hold = Gen.GenAmount.shAmount;
437  CheckRange("holdVolEnv", -12000, 5000, EG1Hold);
438  break;
439  case DECAY_VOL_ENV:
440  EG1Decay = Gen.GenAmount.shAmount;
441  CheckRange("decayVolEnv", -12000, 8000, EG1Decay);
442  break;
443  case SUSTAIN_VOL_ENV:
444  EG1Sustain = Gen.GenAmount.shAmount;
445  CheckRange("sustainVolEnv", 0, 1440, EG1Sustain);
446  break;
447  case RELEASE_VOL_ENV:
448  EG1Release = Gen.GenAmount.shAmount;
449  CheckRange("releaseVolEnv", -12000, 8000, EG1Release);
450  break;
452  break;
454  break;
455  case INSTRUMENT: {
456  uint16_t id = Gen.GenAmount.wAmount;
457  if (id >= pFile->Instruments.size()) {
458  throw Exception("Broken SF2 file (missing instruments)");
459  }
460  pInstrument = pFile->Instruments[id];
461  break;
462  }
463  case KEY_RANGE:
464  loKey = Gen.GenAmount.ranges.byLo;
465  CheckRange("loKey", 0, 127, loKey);
466  hiKey = Gen.GenAmount.ranges.byHi;
467  CheckRange("hiKey", 0, 127, hiKey);
468  break;
469  case VEL_RANGE:
470  minVel = Gen.GenAmount.ranges.byLo;
471  CheckRange("minVel", 0, 127, minVel);
472  maxVel = Gen.GenAmount.ranges.byHi;
473  CheckRange("maxVel", 0, 127, maxVel);
474  break;
476  startloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
478  break;
479  case KEYNUM:
480  break;
481  case VELOCITY:
482  break;
483  case INITIAL_ATTENUATION:
484  break;
486  endloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
488  break;
489  case COARSE_TUNE:
490  coarseTune = Gen.GenAmount.shAmount;
491  CheckRange("coarseTune", -120, 120, coarseTune);
492  break;
493  case FINE_TUNE:
494  fineTune = Gen.GenAmount.shAmount;
495  CheckRange("fineTune", -99, 99, fineTune);
496  break;
497  case SAMPLE_ID: {
498  uint16_t sid = Gen.GenAmount.wAmount;
499  if (sid >= pFile->Samples.size()) {
500  throw Exception("Broken SF2 file (missing samples)");
501  }
502  pSample = pFile->Samples[sid];
503 
504  if (HasLoop) {
506  LoopEnd += pSample->EndLoop;
507  if ( LoopStart < pSample->Start || LoopStart > pSample->End ||
508  LoopStart > LoopEnd || LoopEnd > pSample->End ) {
509  throw Exception("Broken SF2 file (invalid loops)");
510  }
511  LoopStart -= pSample->Start; // Relative to the sample start
512  LoopEnd -= pSample->Start; // Relative to the sample start
513  }
514  break;
515  }
516  case SAMPLE_MODES:
517  HasLoop = Gen.GenAmount.wAmount & 1;
518  // TODO: 3 indicates a sound which loops for the duration of key depression
519  // then proceeds to play the remainder of the sample.
520  break;
521  case SCALE_TUNING:
522  break;
523  case EXCLUSIVE_CLASS:
524  exclusiveClass = Gen.GenAmount.wAmount;
525  break;
526  case OVERRIDING_ROOT_KEY:
527  overridingRootKey = Gen.GenAmount.shAmount;
528  CheckRange("overridingRootKey", -1, 127, overridingRootKey);
529  break;
530  }
531  }
532 
533  void Region::SetModulator(sf2::File* pFile, ModList& Mod) {
534  modulators.push_back(ModulatorItem(Mod));
535  /*switch(srcType) {
536  case NO_CONTROLLER:
537  break;
538  case NOTE_ON_VELOCITY:
539  break;
540  case NOTE_ON_KEY_NUMBER:
541  break;
542  case POLY_PRESSURE:
543  break;
544  case CHANNEL_PRESSURE:
545  break;
546  case PITCH_WHEEL:
547  break;
548  case PITCH_WHEEL_SENSITIVITY:
549  break;
550  case LINK:
551  break;
552  default: std::cout << "Unknown controller source: " << srcType << std::endl;
553  }*/
554  }
555 
556  int Region::GetPan(Region* pPresetRegion) {
557  if (pPresetRegion == NULL) return pan;
558  int p = pPresetRegion->pan + pan;
559  if (p < -64) p = -64;
560  if (p > 63) p = 63;
561  return p;
562  }
563 
564  int Region::GetFineTune(Region* pPresetRegion) {
565  if (pPresetRegion == NULL) return fineTune;
566  int t = pPresetRegion->fineTune + fineTune;
567  if (t < -99) t = -99;
568  if (t > 99) t = 99;
569  return t;
570  }
571 
572  int Region::GetCoarseTune(Region* pPresetRegion) {
573  if (pPresetRegion == NULL) return coarseTune;
574  int t = pPresetRegion->coarseTune + coarseTune;
575  if (t < -120) t = -120;
576  if (t > 120) t = 120;
577  return t;
578  }
579 
580  double Region::GetEG1PreAttackDelay(Region* pPresetRegion) {
581  int val = (pPresetRegion == NULL || pPresetRegion->EG1PreAttackDelay == NONE) ?
582  EG1PreAttackDelay : pPresetRegion->EG1PreAttackDelay + EG1PreAttackDelay;
583  return ToSeconds(CheckRange("GetEG1PreAttackDelay()", -12000, 5000, val));
584  }
585 
586  double Region::GetEG1Attack(Region* pPresetRegion) {
587  int val = (pPresetRegion == NULL || pPresetRegion->EG1Attack == NONE) ?
588  EG1Attack : pPresetRegion->EG1Attack + EG1Attack;
589  return ToSeconds(CheckRange("GetEG1Attack()", -12000, 8000, val));
590  }
591 
592  double Region::GetEG1Hold(Region* pPresetRegion) {
593  int val = (pPresetRegion == NULL || pPresetRegion->EG1Hold == NONE) ?
594  EG1Hold : pPresetRegion->EG1Hold + EG1Hold;
595  return ToSeconds(CheckRange("GetEG1Hold()", -12000, 5000, val));
596  }
597 
598  double Region::GetEG1Decay(Region* pPresetRegion) {
599  int val = (pPresetRegion == NULL || pPresetRegion->EG1Decay == NONE) ?
600  EG1Decay : pPresetRegion->EG1Decay + EG1Decay;
601  return ToSeconds(CheckRange("GetEG1Decay()", -12000, 8000, val));
602  }
603 
604  int Region::GetEG1Sustain(Region* pPresetRegion) {
605  int val = (pPresetRegion == NULL || pPresetRegion->EG1Sustain == NONE) ?
606  EG1Sustain : pPresetRegion->EG1Sustain + EG1Sustain;
607  return CheckRange("GetEG1Sustain()", 0, 1440, val);
608  }
609 
610  double Region::GetEG1Release(Region* pPresetRegion) {
611  int val = (pPresetRegion == NULL || pPresetRegion->EG1Release == NONE) ?
612  EG1Release : pPresetRegion->EG1Release + EG1Release;
613  return ToSeconds(CheckRange("GetEG1Release()", -12000, 8000, val));
614  }
615 
616  double Region::GetEG2PreAttackDelay(Region* pPresetRegion) {
617  int val = (pPresetRegion == NULL || pPresetRegion->EG2PreAttackDelay == NONE) ?
618  EG2PreAttackDelay : pPresetRegion->EG2PreAttackDelay + EG2PreAttackDelay;
619  return ToSeconds(CheckRange("GetEG2PreAttackDelay()", -12000, 5000, val));
620  }
621 
622  double Region::GetEG2Attack(Region* pPresetRegion) {
623  int val = (pPresetRegion == NULL || pPresetRegion->EG2Attack == NONE) ?
624  EG2Attack : pPresetRegion->EG2Attack + EG2Attack;
625  return ToSeconds(CheckRange("GetEG2Attack()", -12000, 8000, val));
626  }
627 
628  double Region::GetEG2Hold(Region* pPresetRegion) {
629  int val = (pPresetRegion == NULL || pPresetRegion->EG2Hold == NONE) ?
630  EG2Hold : pPresetRegion->EG2Hold + EG2Hold;
631  return ToSeconds(CheckRange("GetEG2Hold()", -12000, 5000, val));
632  }
633 
634  double Region::GetEG2Decay(Region* pPresetRegion) {
635  int val = (pPresetRegion == NULL || pPresetRegion->EG2Decay == NONE) ?
636  EG2Decay : pPresetRegion->EG2Decay + EG2Decay;
637  return ToSeconds(CheckRange("GetEG2Decay()", -12000, 8000, val));
638  }
639 
640  int Region::GetEG2Sustain(Region* pPresetRegion) {
641  int val = (pPresetRegion == NULL || pPresetRegion->EG2Sustain == NONE) ?
642  EG2Sustain : pPresetRegion->EG2Sustain + EG2Sustain;
643  return CheckRange("GetEG2Sustain()", 0, 1000, val);
644  }
645 
646  double Region::GetEG2Release(Region* pPresetRegion) {
647  int val = (pPresetRegion == NULL || pPresetRegion->EG2Release == NONE) ?
648  EG2Release : pPresetRegion->EG2Release + EG2Release;
649  return ToSeconds(CheckRange("GetEG2Release()", -12000, 8000, val));
650  }
651 
652  int Region::GetModEnvToPitch(Region* pPresetRegion) {
653  int val = (pPresetRegion == NULL || pPresetRegion->modEnvToPitch == NONE) ?
654  modEnvToPitch : pPresetRegion->modEnvToPitch + modEnvToPitch;
655  return CheckRange("GetModEnvToPitch()", -12000, 12000, val);
656  }
657 
658  int Region::GetModLfoToPitch(Region* pPresetRegion) {
659  int val = (pPresetRegion == NULL || pPresetRegion->modLfoToPitch == NONE) ?
660  modLfoToPitch : pPresetRegion->modLfoToPitch + modLfoToPitch;
661  return CheckRange("GetModLfoToPitch()", -12000, 12000, val);
662  }
663 
664  int Region::GetModEnvToFilterFc(Region* pPresetRegion) {
665  int val = (pPresetRegion == NULL || pPresetRegion->modEnvToFilterFc == NONE) ?
667  return CheckRange("GetModEnvToFilterFc()", -12000, +12000, val);
668  }
669 
670  int Region::GetModLfoToFilterFc(Region* pPresetRegion) {
671  int val = (pPresetRegion == NULL || pPresetRegion->modLfoToFilterFc == NONE) ?
673  return CheckRange("GetModLfoToFilterFc()", -12000, +12000, val);
674  }
675 
676  double Region::GetModLfoToVolume(Region* pPresetRegion) {
677  int val = (pPresetRegion == NULL || pPresetRegion->modLfoToVolume == NONE) ?
678  modLfoToVolume : pPresetRegion->modLfoToVolume + modLfoToVolume;
679  return CheckRange("GetModLfoToVolume()", -960, 960, val);
680  }
681 
682  double Region::GetFreqModLfo(Region* pPresetRegion) {
683  int val = (pPresetRegion == NULL || pPresetRegion->freqModLfo == NONE) ?
684  freqModLfo : pPresetRegion->freqModLfo + freqModLfo;
685  return ToHz(CheckRange("GetFreqModLfo()", -16000, 4500, val));
686  }
687 
688  double Region::GetDelayModLfo(Region* pPresetRegion) {
689  int val = (pPresetRegion == NULL || pPresetRegion->delayModLfo == NONE) ?
690  delayModLfo : pPresetRegion->delayModLfo + delayModLfo;
691  return ToSeconds(CheckRange("GetDelayModLfo()", -12000, 5000, val));
692  }
693 
694  int Region::GetVibLfoToPitch(Region* pPresetRegion) {
695  int val = (pPresetRegion == NULL || pPresetRegion->vibLfoToPitch == NONE) ?
696  vibLfoToPitch : pPresetRegion->vibLfoToPitch + vibLfoToPitch;
697  return CheckRange("GetVibLfoToPitch()", -12000, 12000, val);
698  }
699 
700  double Region::GetFreqVibLfo(Region* pPresetRegion) {
701  int val = (pPresetRegion == NULL || pPresetRegion->freqVibLfo == NONE) ?
702  freqVibLfo : pPresetRegion->freqVibLfo + freqVibLfo;
703  return ToHz(CheckRange("GetFreqVibLfo()", -16000, 4500, val));
704  }
705 
706  double Region::GetDelayVibLfo(Region* pPresetRegion) {
707  int val = (pPresetRegion == NULL || pPresetRegion->delayVibLfo == NONE) ?
708  delayVibLfo : pPresetRegion->delayVibLfo + delayVibLfo;
709  return ToSeconds(CheckRange("GetDelayVibLfo()", -12000, 5000, val));
710  }
711 
712  int Region::GetInitialFilterFc(Region* pPresetRegion) {
713  if (pPresetRegion == NULL || pPresetRegion->initialFilterFc == NONE) return initialFilterFc;
714  int val = pPresetRegion->initialFilterFc + initialFilterFc;
715  return CheckRange("GetInitialFilterFc()", 1500, 13500, val);
716  }
717 
718  int Region::GetInitialFilterQ(Region* pPresetRegion) {
719  int val = (pPresetRegion == NULL || pPresetRegion->initialFilterQ == NONE) ?
720  initialFilterQ : pPresetRegion->initialFilterQ + initialFilterQ;
721  return CheckRange("GetInitialFilterQ()", 0, 960, val);
722  }
723 
725  this->pFile = pFile;
726  pGlobalRegion = NULL;
727  }
728 
730  if (pGlobalRegion) delete pGlobalRegion;
731  for (int i = regions.size() - 1; i >= 0; i--) {
732  if (regions[i]) delete (regions[i]);
733  }
734  }
735 
737  return regions.size();
738  }
739 
741  if (idx < 0 || idx >= GetRegionCount()) {
742  throw Exception("Region index out of bounds");
743  }
744 
745  return regions[idx];
746  }
747 
748  Query::Query(InstrumentBase& instrument) : instrument(instrument) {
749  i = 0;
750  }
751 
753  while (i < instrument.GetRegionCount()) {
754  Region* r = instrument.GetRegion(i++);
755  if (((r->loKey == NONE && r->hiKey == NONE) || (key >= r->loKey && key <= r->hiKey)) &&
756  ((r->minVel == NONE && r->maxVel == NONE) || (vel >= r->minVel && vel <= r->maxVel))) {
757  return r;
758  }
759  }
760  return 0;
761  }
762 
764  this->pFile = pFile;
765  LoadString(ck, Name, 20);
766  InstBagNdx = ck->ReadInt16();
767  }
768 
770  }
771 
773  Region* r = new Region;
774  r->pParentInstrument = this;
775 
776  if (pGlobalRegion != NULL) {
777  r->loKey = pGlobalRegion->loKey;
778  r->hiKey = pGlobalRegion->hiKey;
781  r->pan = pGlobalRegion->pan;
793 
794  r->EG1PreAttackDelay = pGlobalRegion->EG1PreAttackDelay;
795  r->EG1Attack = pGlobalRegion->EG1Attack;
796  r->EG1Hold = pGlobalRegion->EG1Hold;
797  r->EG1Decay = pGlobalRegion->EG1Decay;
798  r->EG1Sustain = pGlobalRegion->EG1Sustain;
799  r->EG1Release = pGlobalRegion->EG1Release;
800 
801  r->EG2PreAttackDelay = pGlobalRegion->EG2PreAttackDelay;
802  r->EG2Attack = pGlobalRegion->EG2Attack;
803  r->EG2Hold = pGlobalRegion->EG2Hold;
804  r->EG2Decay = pGlobalRegion->EG2Decay;
805  r->EG2Sustain = pGlobalRegion->EG2Sustain;
806  r->EG2Release = pGlobalRegion->EG2Release;
807 
820 
824 
826  }
827 
828  return r;
829  }
830 
832  for (int i = 0; i < regions.size(); i++) {
833  if (regions[i] == pRegion) {
834  delete pRegion;
835  regions[i] = NULL;
836  return;
837  }
838  }
839 
840  std::cerr << "Can't remove unknown Region" << std::endl;
841  }
842 
843  void Instrument::LoadRegions(int idx1, int idx2) {
844  for (int i = idx1; i < idx2; i++) {
845  int gIdx1 = pFile->InstBags[i].InstGenNdx;
846  int gIdx2 = pFile->InstBags[i + 1].InstGenNdx;
847 
848  if (gIdx1 < 0 || gIdx2 < 0 || gIdx1 > gIdx2 || gIdx2 >= pFile->InstGenLists.size()) {
849  throw Exception("Broken SF2 file (invalid InstGenNdx)");
850  }
851 
852  int mIdx1 = pFile->InstBags[i].InstModNdx;
853  int mIdx2 = pFile->InstBags[i + 1].InstModNdx;
854 
855  if (mIdx1 < 0 || mIdx2 < 0 || mIdx1 > mIdx2 || mIdx2 >= pFile->InstModLists.size()) {
856  throw Exception("Broken SF2 file (invalid InstModNdx)");
857  }
858 
859  Region* reg = CreateRegion();
860 
861  for (int j = gIdx1; j < gIdx2; j++) {
862  reg->SetGenerator(pFile, pFile->InstGenLists[j]);
863  // TODO: ignore generators following a sampleID generator
864  }
865 
866  for (int j = mIdx1; j < mIdx2; j++) {
867  reg->SetModulator(pFile, pFile->InstModLists[j]);
868  }
869 
870  if (reg->pSample == NULL) {
871  if (i == idx1 && idx2 - idx1 > 1) {
872  pGlobalRegion = reg; // global zone
873  } else {
874  std::cerr << "Ignoring instrument's region without sample" << std::endl;
875  delete reg;
876  }
877  } else {
878  regions.push_back(reg);
879  }
880  }
881  }
882 
884  this->pFile = pFile;
885  LoadString(ck, Name, 20);
886  PresetNum = ck->ReadInt16();
887  Bank = ck->ReadInt16();
888  PresetBagNdx = ck->ReadInt16();
889  Library = ck->ReadInt32();
890  Genre = ck->ReadInt32();
891  Morphology = ck->ReadInt32();
892  }
893 
895  }
896 
898  Region* r = new Region;
899 
900  r->EG1PreAttackDelay = r->EG1Attack = r->EG1Hold = r->EG1Decay = r->EG1Sustain = r->EG1Release = NONE;
901  r->EG2PreAttackDelay = r->EG2Attack = r->EG2Hold = r->EG2Decay = r->EG2Sustain = r->EG2Release = NONE;
902  r->freqModLfo = r->delayModLfo = r->freqVibLfo = r->delayVibLfo = NONE;
903  r->initialFilterFc = r->initialFilterQ = NONE;
904 
905  if (pGlobalRegion != NULL) {
906  r->pan = pGlobalRegion->pan;
909 
910  r->EG1PreAttackDelay = pGlobalRegion->EG1PreAttackDelay;
911  r->EG1Attack = pGlobalRegion->EG1Attack;
912  r->EG1Hold = pGlobalRegion->EG1Hold;
913  r->EG1Decay = pGlobalRegion->EG1Decay;
914  r->EG1Sustain = pGlobalRegion->EG1Sustain;
915  r->EG1Release = pGlobalRegion->EG1Release;
916 
917  r->EG2PreAttackDelay = pGlobalRegion->EG2PreAttackDelay;
918  r->EG2Attack = pGlobalRegion->EG2Attack;
919  r->EG2Hold = pGlobalRegion->EG2Hold;
920  r->EG2Decay = pGlobalRegion->EG2Decay;
921  r->EG2Sustain = pGlobalRegion->EG2Sustain;
922  r->EG2Release = pGlobalRegion->EG2Release;
923 
936  }
937 
938  return r;
939  }
940 
941  void Preset::LoadRegions(int idx1, int idx2) {
942  for (int i = idx1; i < idx2; i++) {
943  int gIdx1 = pFile->PresetBags[i].GenNdx;
944  int gIdx2 = pFile->PresetBags[i + 1].GenNdx;
945 
946  if (gIdx1 < 0 || gIdx2 < 0 || gIdx1 > gIdx2 || gIdx2 >= pFile->PresetGenLists.size()) {
947  throw Exception("Broken SF2 file (invalid PresetGenNdx)");
948  }
949 
950  Region* reg = CreateRegion();
951 
952  for (int j = gIdx1; j < gIdx2; j++) {
953  reg->SetGenerator(pFile, pFile->PresetGenLists[j]);
954  }
955  if (reg->pInstrument == NULL) {
956  if (i == idx1 && idx2 - idx1 > 1) {
957  pGlobalRegion = reg; // global zone
958  } else {
959  std::cerr << "Ignoring preset's region without instrument" << std::endl;
960  delete reg;
961  }
962  } else {
963  regions.push_back(reg);
964  }
965  }
966  }
967 
978  if (!pRIFF) throw Exception("NULL pointer reference to RIFF::File object.");
979  this->pRIFF = pRIFF;
980 
981  if (pRIFF->GetListType() != RIFF_TYPE_SF2) {
982  throw Exception("Not a SF2 file");
983  }
984 
985  pInfo = new Info(pRIFF);
986  if (pInfo->pVer->Major != 2) {
987  throw Exception("Unsupported version: " + ToString(pInfo->pVer->Major));
988  }
989 
991  if (lstSDTA == NULL) {
992  throw Exception("Broken SF2 file (missing sdta)");
993  }
994 
995  RIFF::Chunk* pCkSmpl = lstSDTA->GetSubChunk(CHUNK_ID_SMPL);
996  RIFF::Chunk* pCkSm24 = lstSDTA->GetSubChunk(CHUNK_ID_SM24);
997  if (pCkSmpl != NULL && pCkSm24 != NULL) {
998  long l = pCkSmpl->GetSize() / 2;
999  if (l%2) l++;
1000  if (pCkSm24->GetSize() != l) {
1001  pCkSm24 = NULL; // ignoring sm24 due to invalid size
1002  }
1003  }
1004 
1006  if (lstPDTA == NULL) {
1007  throw Exception("Broken SF2 file (missing pdta)");
1008  }
1009 
1010  RIFF::Chunk* ck = lstPDTA->GetSubChunk(CHUNK_ID_PHDR);
1011  if (ck->GetSize() < 38) {
1012  throw Exception("Broken SF2 file (broken phdr)");
1013  }
1014 
1015  int count = ck->GetSize() / 38;
1016  for (int i = 0; i < count; i++) {
1017  Presets.push_back(new Preset(this, ck));
1018  }
1019 
1020  ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_PBAG);
1021  if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
1022  throw Exception("Broken SF2 file (broken pbag)");
1023  }
1024 
1025  count = ck->GetSize() / 4;
1026  for (int i = 0; i < count; i++) {
1027  PresetBag pb;
1028  pb.GenNdx = ck->ReadInt16();
1029  pb.ModNdx = ck->ReadInt16();
1030  PresetBags.push_back(pb);
1031  }
1032  //std::cout << "Preset bags: " << PresetBags.size() << std::endl;
1033 
1034  ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_PMOD);
1035  if (ck->GetSize() % 10) {
1036  throw Exception("Broken SF2 file (broken pmod)");
1037  }
1038 
1039  count = ck->GetSize() / 10;
1040  for (int i = 0; i < count; i++) {
1041  ModList ml;
1042  ml.ModSrcOper = ck->ReadInt16();
1043  ml.ModDestOper = ck->ReadInt16();
1044  ml.ModAmount = ck->ReadInt16();
1045  ml.ModAmtSrcOper = ck->ReadInt16();
1046  ml.ModTransOper = ck->ReadInt16();
1047  PresetModLists.push_back(ml);
1048  }
1049  //std::cout << "Preset mod lists: " << PresetModLists.size() << std::endl;
1050 
1051  ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_PGEN);
1052  if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
1053  throw Exception("Broken SF2 file (broken pgen)");
1054  }
1055 
1056  count = ck->GetSize() / 4;
1057  for (int i = 0; i < count; i++) {
1058  GenList gl;
1059  gl.GenOper = ck->ReadInt16();
1060  gl.GenAmount.wAmount = ck->ReadInt16();
1061  PresetGenLists.push_back(gl);
1062  }
1063  //std::cout << "Preset gen lists: " << PresetGenLists.size() << std::endl;
1064 
1065  ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_INST);
1066  if (ck->GetSize() < (22 * 2) || (ck->GetSize() % 22)) {
1067  throw Exception("Broken SF2 file (broken inst)");
1068  }
1069  count = ck->GetSize() / 22;
1070  for (int i = 0; i < count; i++) {
1071  Instruments.push_back(new Instrument(this, ck));
1072  }
1073 
1074  ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_IBAG);
1075  if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
1076  throw Exception("Broken SF2 file (broken ibag)");
1077  }
1078 
1079  count = ck->GetSize() / 4;
1080  for (int i = 0; i < count; i++) {
1081  InstBag ib;
1082  ib.InstGenNdx = ck->ReadInt16();
1083  ib.InstModNdx = ck->ReadInt16();
1084  InstBags.push_back(ib);
1085  }
1086  //std::cout << "Instrument bags: " << InstBags.size() << std::endl;
1087 
1088  ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_IMOD);
1089  if (ck->GetSize() % 10) {
1090  throw Exception("Broken SF2 file (broken imod)");
1091  }
1092 
1093  count = ck->GetSize() / 10;
1094  for (int i = 0; i < count; i++) {
1095  ModList ml;
1096  ml.ModSrcOper = ck->ReadInt16();
1097  ml.ModDestOper = ck->ReadInt16();
1098  ml.ModAmount = ck->ReadInt16();
1099  ml.ModAmtSrcOper = ck->ReadInt16();
1100  ml.ModTransOper = ck->ReadInt16();
1101  InstModLists.push_back(ml);
1102  }
1103  //std::cout << "Instrument mod lists: " << InstModLists.size() << std::endl;
1104 
1105  ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_IGEN);
1106  if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
1107  throw Exception("Broken SF2 file (broken igen)");
1108  }
1109 
1110  count = ck->GetSize() / 4;
1111  for (int i = 0; i < count; i++) {
1112  GenList gl;
1113  gl.GenOper = ck->ReadInt16();
1114  gl.GenAmount.wAmount = ck->ReadInt16();
1115  InstGenLists.push_back(gl);
1116  }
1117  //std::cout << "Instrument gen lists: " << InstGenLists.size() << std::endl;
1118 
1119  ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_SHDR);
1120  if ((ck->GetSize() % 46)) {
1121  throw Exception("Broken SF2 file (broken shdr)");
1122  }
1123  count = ck->GetSize() / 46;
1124  for (int i = 0; i < count; i++) {
1125  Samples.push_back(new Sample(ck, pCkSmpl, pCkSm24));
1126  }
1127 
1128  // Loading instrument regions
1129  for (int i = 0; i < Instruments.size() - 1; i++) {
1130  Instrument* instr = Instruments[i];
1131  int x1 = instr->InstBagNdx;
1132  int x2 = Instruments[i + 1]->InstBagNdx;
1133  if (x1 < 0 || x2 < 0 || x1 > x2 || x2 >= InstBags.size()) {
1134  throw Exception("Broken SF2 file (invalid InstBagNdx)");
1135  }
1136 
1137  instr->LoadRegions(x1, x2);
1138  }
1139 
1140  // Loading preset regions
1141  for (int i = 0; i < Presets.size() - 1; i++) {
1142  Preset* preset = Presets[i];
1143  int x1 = preset->PresetBagNdx;
1144  int x2 = Presets[i + 1]->PresetBagNdx;
1145  if (x1 < 0 || x2 < 0 || x1 > x2 || x2 >= PresetBags.size()) {
1146  throw Exception("Broken SF2 file (invalid PresetBagNdx)");
1147  }
1148 
1149  preset->LoadRegions(x1, x2);
1150  }
1151  }
1152 
1154  delete pInfo;
1155  for (int i = Presets.size() - 1; i >= 0; i--) {
1156  if (Presets[i]) delete (Presets[i]);
1157  }
1158  for (int i = Instruments.size() - 1; i >= 0; i--) {
1159  if (Instruments[i]) delete (Instruments[i]);
1160  }
1161  for (int i = Samples.size() - 1; i >= 0; i--) {
1162  if (Samples[i]) delete (Samples[i]);
1163  }
1164  }
1165 
1167  return Presets.size() - 1; // exclude terminal preset (EOP)
1168  }
1169 
1171  if (idx < 0 || idx >= GetPresetCount()) {
1172  throw Exception("Preset index out of bounds");
1173  }
1174 
1175  return Presets[idx];
1176  }
1177 
1179  return Instruments.size() - 1; // exclude terminal instrument (EOI)
1180  }
1181 
1183  if (idx < 0 || idx >= GetInstrumentCount()) {
1184  throw Exception("Instrument index out of bounds");
1185  }
1186 
1187  return Instruments[idx];
1188  }
1189 
1190  void File::DeleteInstrument(Instrument* pInstrument) {
1191  for (int i = 0; i < GetPresetCount(); i++) {
1192  Preset* p = GetPreset(i);
1193  if (p == NULL) continue;
1194  for (int j = p->GetRegionCount() - 1; j >= 0 ; j--) {
1195  if (p->GetRegion(j) && p->GetRegion(j)->pInstrument == pInstrument) {
1196  p->GetRegion(j)->pInstrument = NULL;
1197  }
1198  }
1199  }
1200 
1201  for (int i = 0; i < GetInstrumentCount(); i++) {
1202  if (GetInstrument(i) == pInstrument) {
1203  Instruments[i] = NULL;
1204  delete pInstrument;
1205  }
1206  }
1207  }
1208 
1210  return Samples.size() - 1; // exclude terminal sample (EOS)
1211  }
1212 
1214  if (idx < 0 || idx >= GetSampleCount()) {
1215  throw Exception("Sample index out of bounds");
1216  }
1217 
1218  return Samples[idx];
1219  }
1220 
1221  void File::DeleteSample(Sample* pSample) {
1222  // Sanity check
1223  for (int i = GetInstrumentCount() - 1; i >= 0; i--) {
1224  Instrument* pInstr = GetInstrument(i);
1225  if (pInstr == NULL) continue;
1226 
1227  for (int j = pInstr->GetRegionCount() - 1; j >= 0 ; j--) {
1228  if (pInstr->GetRegion(j) && pInstr->GetRegion(j)->GetSample() == pSample) {
1229  std::cerr << "Deleting sample which is still in use" << std::endl;
1230  }
1231  }
1232  }
1234 
1235  for (int i = 0; i < GetSampleCount(); i++) {
1236  if (Samples[i] == pSample) {
1237  delete pSample;
1238  Samples[i] = NULL;
1239  return;
1240  }
1241  }
1242 
1243  throw Exception("Unknown sample: " + pSample->Name);
1244  }
1245 
1247  for (int i = 0; i < GetSampleCount(); i++) {
1248  if (Samples[i] != NULL) return true;
1249  }
1250 
1251  return false;
1252  }
1253 
1264  return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), 0); // 0 amount of NullSamples
1265  }
1266 
1285  Sample::buffer_t Sample::LoadSampleData(unsigned long SampleCount) {
1286  return LoadSampleDataWithNullSamplesExtension(SampleCount, 0); // 0 amount of NullSamples
1287  }
1288 
1309  return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), NullSamplesCount);
1310  }
1311 
1340  Sample::buffer_t Sample::LoadSampleDataWithNullSamplesExtension(unsigned long SampleCount, uint NullSamplesCount) {
1341  if (SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount();
1342  if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
1343  unsigned long allocationsize = (SampleCount + NullSamplesCount) * GetFrameSize();
1344  SetPos(0); // reset read position to begin of sample
1345  RAMCache.pStart = new int8_t[allocationsize];
1346  RAMCache.Size = Read(RAMCache.pStart, SampleCount) * GetFrameSize();
1347  RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
1348  // fill the remaining buffer space with silence samples
1349  memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
1350  return GetCache();
1351  }
1352 
1364  // return a copy of the buffer_t structure
1365  buffer_t result;
1366  result.Size = this->RAMCache.Size;
1367  result.pStart = this->RAMCache.pStart;
1369  return result;
1370  }
1371 
1379  if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
1380  RAMCache.pStart = NULL;
1381  RAMCache.Size = 0;
1383  }
1384 
1394  unsigned long Sample::SetPos(unsigned long SampleCount) {
1395  pCkSmpl->SetPos((Start * 2) + (SampleCount * 2), RIFF::stream_start);
1396  if(pCkSm24) pCkSm24->SetPos(Start + SampleCount, RIFF::stream_start);
1397  return SampleCount;
1398  }
1399 
1403  unsigned long Sample::GetPos() {
1404  return (pCkSmpl->GetPos() - (Start * 2)) / 2;
1405  }
1406 
1407  // Actual implementation of Sample::Read*() code. Wrapped into a template for a) runtime effeciency and b) code redundancy reasons.
1408  template<bool CLEAR>
1409  inline unsigned long ReadSample(Sample* pSample, void* pBuffer, unsigned long SampleCount, Sample::buffer_t* tempBuffer = NULL) {
1410  // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
1411  if (SampleCount == 0) return 0;
1412  long pos = pSample->GetPos();
1413  if (pos + SampleCount > pSample->GetTotalFrameCount())
1414  SampleCount = pSample->GetTotalFrameCount() - pos;
1415  if (!CLEAR) {
1416  if (tempBuffer->Size < SampleCount * pSample->GetFrameSize()) {
1417  std::cerr << "sf2::Sample error: tempBuffer too small. This is a BUG!" << std::endl;
1418  return 0;
1419  }
1420  }
1421 
1422  if (pSample->GetFrameSize() / pSample->GetChannelCount() == 3 /* 24 bit */) {
1423  uint8_t* const pTmpBuf = (uint8_t*) ((CLEAR) ? pBuffer : tempBuffer->pStart);
1424  uint8_t* const pBuf = (uint8_t*)pBuffer;
1425  if (pSample->SampleType == Sample::MONO_SAMPLE || pSample->SampleType == Sample::ROM_MONO_SAMPLE) {
1426  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1427  pSample->pCkSm24->Read(pTmpBuf + SampleCount * 2, SampleCount, 1);
1428  for (int i = SampleCount - 1; i >= 0; i--) {
1429  pBuf[i*3] = pTmpBuf[(SampleCount * 2) + i];
1430  pBuf[i*3 + 2] = pTmpBuf[i*2 + 1];
1431  pBuf[i*3 + 1] = pTmpBuf[i*2];
1432  }
1433  } else if (pSample->SampleType == Sample::LEFT_SAMPLE || pSample->SampleType == Sample::ROM_LEFT_SAMPLE) {
1434  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1435  pSample->pCkSm24->Read(pTmpBuf + SampleCount * 2, SampleCount, 1);
1436  for (int i = SampleCount - 1; i >= 0; i--) {
1437  pBuf[i*6] = pTmpBuf[(SampleCount * 2) + i];
1438  pBuf[i*6 + 2] = pTmpBuf[i*2 + 1];
1439  pBuf[i*6 + 1] = pTmpBuf[i*2];
1440  if (CLEAR)
1441  pBuf[i*6 + 3] = pBuf[i*6 + 4] = pBuf[i*6 + 5] = 0;
1442  }
1443  } else if (pSample->SampleType == Sample::RIGHT_SAMPLE || pSample->SampleType == Sample::ROM_RIGHT_SAMPLE) {
1444  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1445  pSample->pCkSm24->Read(pTmpBuf + SampleCount * 2, SampleCount, 1);
1446  for (int i = SampleCount - 1; i >= 0; i--) {
1447  pBuf[i*6 + 3] = pTmpBuf[(SampleCount * 2) + i];
1448  pBuf[i*6 + 5] = pTmpBuf[i*2 + 1];
1449  pBuf[i*6 + 4] = pTmpBuf[i*2];
1450  if (CLEAR)
1451  pBuf[i*6] = pBuf[i*6 + 1] = pBuf[i*6 + 2] = 0;
1452  }
1453  }
1454  } else {
1455  if (pSample->SampleType == Sample::MONO_SAMPLE || pSample->SampleType == Sample::ROM_MONO_SAMPLE) {
1456  return pSample->pCkSmpl->Read(pBuffer, SampleCount, 2);
1457  }
1458 
1459  int16_t* const pTmpBuf = (int16_t*) ((CLEAR) ? pBuffer : tempBuffer->pStart);
1460  int16_t* const pBuf = (int16_t*) pBuffer;
1461  if (pSample->SampleType == Sample::LEFT_SAMPLE || pSample->SampleType == Sample::ROM_LEFT_SAMPLE) {
1462  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1463  for (int i = SampleCount - 1; i >= 0; i--) {
1464  pBuf[i*2] = pTmpBuf[i];
1465  if (CLEAR)
1466  pBuf[i*2 + 1] = 0;
1467  }
1468  } else if (pSample->SampleType == Sample::RIGHT_SAMPLE || pSample->SampleType == Sample::ROM_RIGHT_SAMPLE) {
1469  pSample->pCkSmpl->Read(pTmpBuf, SampleCount, 2);
1470  for (int i = SampleCount - 1; i >= 0; i--) {
1471  if (CLEAR)
1472  pBuf[i*2] = 0;
1473  pBuf[i*2 + 1] = pTmpBuf[i];
1474  }
1475  }
1476  }
1477 
1478  if (pSample->pCkSmpl->GetPos() > (pSample->End * 2)) {
1479  std::cerr << "Read after the sample end. This is a BUG!" << std::endl;
1480  std::cerr << "Current position: " << pSample->GetPos() << std::endl;
1481  std::cerr << "Total number of frames: " << pSample->GetTotalFrameCount() << std::endl << std::endl;
1482  }
1483  return SampleCount;
1484  }
1485 
1509  unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
1510  return ReadSample<true>(this, pBuffer, SampleCount);
1511  }
1512 
1543  unsigned long Sample::ReadNoClear(void* pBuffer, unsigned long SampleCount, buffer_t& tempBuffer) {
1544  return ReadSample<false>(this, pBuffer, SampleCount, &tempBuffer);
1545  }
1546 
1547 
1548 // *************** functions ***************
1549 // *
1550 
1555  return PACKAGE;
1556  }
1557 
1562  return VERSION;
1563  }
1564 
1565 } // namespace sf2
double GetEG1Release(Region *pPresetRegion=NULL)
Definition: SF.cpp:610
int delayVibLfo
Definition: SF.h:367
double ToHz(int cents)
Definition: SF.cpp:48
Region * CreateRegion()
Definition: SF.cpp:772
int GetPresetCount()
Definition: SF.cpp:1166
Definition: SF.h:520
int Major
Definition: SF.h:234
int GetVibLfoToPitch(Region *pPresetRegion=NULL)
Definition: SF.cpp:694
int modLfoToVolume
Definition: SF.h:364
~File()
Definition: SF.cpp:1153
SFGenerator GenOper
Definition: SF.h:104
int GetInitialFilterFc(Region *pPresetRegion)
Definition: SF.cpp:712
uint16_t InstGenNdx
Definition: SF.h:109
String Software
[<ISFT-ck>] ; The SoundFont tools used to create and alter the bank
Definition: SF.h:252
double GetEG1Attack(Region *pPresetRegion=NULL)
Definition: SF.cpp:586
Definition: SF.h:240
Info * pInfo
Definition: SF.h:522
Region * pGlobalRegion
Definition: SF.h:451
unsigned long Read(void *pData, unsigned long WordCount, unsigned long WordSize)
Reads WordCount number of data words with given WordSize and copies it into a buffer pointed by pData...
Definition: RIFF.cpp:296
double GetFreqVibLfo(Region *pPresetRegion=NULL)
Definition: SF.cpp:700
String Name
Definition: SF.h:296
sf2::File * pFile
Definition: SF.h:464
void DeleteSample(Sample *pSample)
Definition: SF.cpp:1221
unsigned long SetPos(unsigned long SampleCount)
Sets the position within the sample (in sample points, not in bytes).
Definition: SF.cpp:1394
#define CHUNK_ID_SMPL
Definition: RIFF.h:107
SFModulator ModSrcOper
Definition: SF.h:80
int key
Definition: SF.h:469
int GetRegionCount()
Definition: SF.cpp:736
friend class Instrument
Definition: SF.h:538
uint32_t GetChunkID()
Chunk ID in unsigned integer representation.
Definition: RIFF.h:209
#define CHUNK_ID_PBAG
Definition: SF.h:52
void DeleteRegion(Region *pRegion)
Definition: SF.cpp:831
uint32_t SampleRate
Definition: SF.h:337
int GetEG2Sustain(Region *pPresetRegion=NULL)
Definition: SF.cpp:640
String RomName
[<irom-ck>] ; Refers to the Sound ROM Name
Definition: SF.h:245
double GetEG2Decay(Region *pPresetRegion=NULL)
Definition: SF.cpp:634
Instrument zone.
Definition: SF.h:352
String libraryVersion()
Returns version of this C++ library.
Definition: SF.cpp:1561
uint16_t ModNdx
Definition: SF.h:72
double ToRatio(int Centibels)
Definition: SF.cpp:42
uint16_t GenNdx
Definition: SF.h:71
int startloopAddrsCoarseOffset
Definition: SF.h:361
Sample(RIFF::Chunk *ck, RIFF::Chunk *pCkSmpl, RIFF::Chunk *pCkSm24)
Definition: SF.cpp:150
uint16_t PresetNum
Definition: SF.h:499
int GetCoarseTune(Region *pPresetRegion=NULL)
Definition: SF.cpp:572
#define CHUNK_ID_PGEN
Definition: SF.h:54
String libraryName()
Returns the name of this C++ library.
Definition: SF.cpp:1554
unsigned long SetPos(unsigned long 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:215
#define CHUNK_ID_ISNG
Definition: SF.h:43
#define CHUNK_ID_ICMT
Definition: RIFF.h:99
#define CHUNK_ID_ISFT
Definition: RIFF.h:105
int startAddrsCoarseOffset
Definition: SF.h:360
uint16_t PresetBagNdx
Definition: SF.h:510
int GetModLfoToPitch(Region *pPresetRegion=NULL)
Definition: SF.cpp:658
#define CHUNK_ID_IPRD
Definition: RIFF.h:104
unsigned long position
Current position within the sample.
Definition: SF.h:279
std::string String
Definition: SF.h:226
Modulator(SFModulator mod)
Definition: SF.cpp:84
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
struct sf2::_ModList ModList
int delayModLfo
Definition: SF.h:365
int GetFrameSize()
Definition: SF.cpp:199
List * GetSubList(uint32_t ListType)
Returns sublist chunk with list type ListType within this chunk list.
Definition: RIFF.cpp:1045
int Type
Definition: SF.h:205
uint32_t Library
Definition: SF.h:501
int Index
Definition: SF.h:209
String Copyright
[<ICOP-ck>] ; Contains any Copyright message
Definition: SF.h:250
bool HasSamples()
Definition: SF.cpp:1246
bool MidiPalete
Definition: SF.h:206
void LoadString(RIFF::Chunk *ck, std::string &s, int strLength)
Definition: SF.cpp:60
Query(InstrumentBase &instrument)
Definition: SF.cpp:748
String Comments
[<ICMT-ck>] ; Contains any Comments on the Bank
Definition: SF.h:251
uint LoopEnd
Definition: SF.h:375
SoundFont specific classes and definitions.
Definition: SF.h:62
Version(RIFF::Chunk *ck)
Definition: SF.cpp:100
int hiKey
Definition: SF.h:354
int GetInstrumentCount()
Definition: SF.cpp:1178
String Product
[<IPRD-ck>] ; Product for which the Bank was intended
Definition: SF.h:249
unsigned long NullExtensionSize
The buffer might be bigger than the actual data, if that's the case that unused space at the end of t...
Definition: SF.h:288
buffer_t GetCache()
Returns current cached sample points.
Definition: SF.cpp:1363
SFGenerator ModDestOper
Definition: SF.h:81
int modEnvToPitch
Definition: SF.h:363
uint32_t Start
Definition: SF.h:333
double GetDelayModLfo(Region *pPresetRegion=NULL)
Definition: SF.cpp:688
friend class Preset
Definition: SF.h:539
uint32_t End
Definition: SF.h:334
#define CHUNK_ID_IENG
Definition: RIFF.h:102
double GetEG2Release(Region *pPresetRegion=NULL)
Definition: SF.cpp:646
unsigned long GetPos()
Position within the chunk data body.
Definition: RIFF.h:214
std::vector< Region * > regions
Definition: SF.h:463
uint16_t ModAmount
Definition: SF.h:82
Reflects the current playback state for a sample.
Definition: SF.h:277
RIFF::Chunk * GetMandatoryChunk(RIFF::List *list, uint32_t chunkId)
Definition: SF.cpp:54
Sample * pSample
Definition: SF.h:372
int coarseTune
Definition: SF.h:358
RIFF List Chunk.
Definition: RIFF.h:302
int initialFilterFc
Definition: SF.h:368
RIFF::Chunk * pCkSmpl
Definition: SF.h:327
int endloopAddrsOffset
Definition: SF.h:361
#define RIFF_TYPE_SF2
Definition: SF.h:34
#define CHUNK_ID_SM24
Definition: SF.h:48
#define CHUNK_ID_IROM
Definition: SF.h:44
int freqModLfo
Definition: SF.h:364
Region * CreateRegion()
Definition: SF.cpp:897
GenAmountType GenAmount
Definition: SF.h:105
double GetEG2PreAttackDelay(Region *pPresetRegion=NULL)
Definition: SF.cpp:616
uint32_t EndLoop
Definition: SF.h:336
bool Direction
Definition: SF.h:207
~Info()
Definition: SF.cpp:135
double GetModLfoToVolume(Region *pPresetRegion=NULL)
Definition: SF.cpp:676
#define CHUNK_ID_IMOD
Definition: SF.h:57
#define CHUNK_ID_IFIL
Definition: SF.h:42
int modLfoToFilterFc
Definition: SF.h:363
double GetDelayVibLfo(Region *pPresetRegion=NULL)
Definition: SF.cpp:706
int loKey
Definition: SF.h:354
Version * pRomVer
[<iver-ck>] ; Refers to the Sound ROM Version
Definition: SF.h:246
uint8_t PitchCorrection
Definition: SF.h:339
double GetEG1Hold(Region *pPresetRegion=NULL)
Definition: SF.cpp:592
uint exclusiveClass
Definition: SF.h:370
unsigned long ReadInt32(int32_t *pData, unsigned long WordCount=1)
Reads WordCount number of 32 Bit signed integer words and copies it into the buffer pointed by pData.
Definition: RIFF.cpp:574
void DeleteInstrument(Instrument *pInstrument)
Definition: SF.cpp:1190
void LoadRegions(int idx1, int idx2)
Load all regions (zones, bags) in the range idx1 - idx2.
Definition: SF.cpp:843
uint32_t Genre
Definition: SF.h:502
int fineTune
Definition: SF.h:357
sf2::File * pFile
Definition: SF.h:509
Chunk * GetSubChunk(uint32_t ChunkID)
Returns subchunk with chunk ID ChunkID within this chunk list.
Definition: RIFF.cpp:1026
void LoadRegions(int idx1, int idx2)
Load all regions (zones, bags) in the range idx1 - idx2.
Definition: SF.cpp:941
int startAddrsOffset
Definition: SF.h:360
int initialFilterQ
Definition: SF.h:368
#define CHUNK_ID_ICRD
Definition: RIFF.h:101
uint16_t InstModNdx
Definition: SF.h:110
std::vector< GenList > PresetGenLists
Definition: SF.h:545
std::vector< InstBag > InstBags
Definition: SF.h:546
std::vector< ModulatorItem > modulators
Definition: SF.h:390
#define LIST_TYPE_PDTA
Definition: SF.h:38
buffer_t LoadSampleData()
Loads the whole sample wave into RAM.
Definition: SF.cpp:1263
Preset * GetPreset(int idx)
Definition: SF.cpp:1170
unsigned long Read(void *pBuffer, unsigned long SampleCount)
Reads SampleCount number of sample points from the current position into the buffer pointed by pBuffe...
Definition: SF.cpp:1509
#define CHUNK_ID_SHDR
Definition: SF.h:59
Ordinary RIFF Chunk.
Definition: RIFF.h:205
uint32_t GetListType()
Returns unsigned integer representation of the list's ID.
Definition: RIFF.h:306
std::vector< ModList > PresetModLists
Definition: SF.h:544
int endloopAddrsCoarseOffset
Definition: SF.h:361
int endAddrsCoarseOffset
Definition: SF.h:360
int minVel
Definition: SF.h:355
int freqVibLfo
Definition: SF.h:366
#define CHUNK_ID_INAM
Definition: RIFF.h:103
#define CHUNK_ID_IVER
Definition: SF.h:45
int vibLfoToPitch
Definition: SF.h:366
bool HasLoops()
Definition: SF.cpp:203
uint8_t OriginalPitch
Definition: SF.h:338
double GetEG2Hold(Region *pPresetRegion=NULL)
Definition: SF.cpp:628
Preset(sf2::File *pFile, RIFF::Chunk *ck)
Definition: SF.cpp:883
#define _200TH_ROOT_OF_10
Definition: SF.cpp:32
ModulatorItem(ModList &mod)
Definition: SF.cpp:93
unsigned long ReadInt16(int16_t *pData, unsigned long WordCount=1)
Reads WordCount number of 16 Bit signed integer words and copies it into the buffer pointed by pData.
Definition: RIFF.cpp:500
unsigned long GetPos()
Returns the current position in the sample (in sample points).
Definition: SF.cpp:1403
uint LoopStart
Definition: SF.h:374
String Name
Definition: SF.h:450
void * pStart
Points to the beginning of the buffer.
Definition: SF.h:286
#define CHUNK_ID_IGEN
Definition: SF.h:58
Instrument(sf2::File *pFile, RIFF::Chunk *ck)
Definition: SF.cpp:763
std::vector< ModList > InstModLists
Definition: SF.h:547
buffer_t LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount)
Loads the whole sample wave into RAM.
Definition: SF.cpp:1308
int GetPan(Region *pPresetRegion=NULL)
Definition: SF.cpp:556
uint8_t vel
Definition: SF.h:470
int GetFineTune(Region *pPresetRegion=NULL)
Definition: SF.cpp:564
Instrument * GetInstrument(int idx)
Definition: SF.cpp:1182
#define _1200TH_ROOT_OF_2
Definition: SF.cpp:31
Version * pVer
<ifil-ck> ; Refers to the version of the Sound Font RIFF file
Definition: SF.h:242
File(RIFF::File *pRIFF)
Constructor.
Definition: SF.cpp:977
uint16_t SFModulator
Definition: SF.h:75
double GetEG1PreAttackDelay(Region *pPresetRegion=NULL)
Definition: SF.cpp:580
uint16_t Bank
Definition: SF.h:500
buffer_t RAMCache
Buffers samples (already uncompressed) in RAM.
Definition: SF.h:326
int modLfoToPitch
Definition: SF.h:363
int Minor
Definition: SF.h:235
uint32_t StartLoop
Definition: SF.h:335
Pointer address and size of a buffer.
Definition: SF.h:285
virtual ~InstrumentBase()
Definition: SF.cpp:729
uint16_t SampleType
Definition: SF.h:343
uint16_t SampleLink
Definition: SF.h:340
~Preset()
Definition: SF.cpp:894
#define CHUNK_ID_PHDR
Definition: SF.h:51
String CreationDate
[<ICRD-ck>] ; Refers to the Date of Creation of the Bank
Definition: SF.h:247
uint32_t Morphology
Definition: SF.h:503
#define CHUNK_ID_ICOP
Definition: RIFF.h:100
RIFF File.
Definition: RIFF.h:351
struct sf2::_GenList GenList
int GetInitialFilterQ(Region *pPresetRegion)
Definition: SF.cpp:718
unsigned long GetSize() const
Chunk size in bytes (without header, thus the chunk data body)
Definition: RIFF.h:212
#define LIST_TYPE_SDTA
Definition: SF.h:37
#define CHUNK_ID_IBAG
Definition: SF.h:56
int GetChannelCount()
Definition: SF.cpp:188
uint16_t wAmount
Definition: SF.h:100
int pan
Definition: SF.h:356
int GetEG1Sustain(Region *pPresetRegion=NULL)
Definition: SF.cpp:604
long GetTotalFrameCount()
Definition: SF.cpp:192
double GetEG1Decay(Region *pPresetRegion=NULL)
Definition: SF.cpp:598
double ToSeconds(int Timecents)
Definition: SF.cpp:35
unsigned long ReadNoClear(void *pBuffer, unsigned long SampleCount, buffer_t &tempBuffer)
Reads SampleCount number of sample points from the current position into the buffer pointed by pBuffe...
Definition: SF.cpp:1543
int modEnvToFilterFc
Definition: SF.h:363
bool HasLoop
Definition: SF.h:373
int ChannelCount
Definition: SF.h:331
SFModulator ModAmtSrcOper
Definition: SF.h:83
int overridingRootKey
Definition: SF.h:359
InstrumentBase(sf2::File *pFile)
Definition: SF.cpp:724
unsigned long ReadUint16(uint16_t *pData, unsigned long WordCount=1)
Reads WordCount number of 16 Bit unsigned integer words and copies it into the buffer pointed by pDat...
Definition: RIFF.cpp:537
String SoundEngine
<isng-ck> ; Refers to the target Sound Engine
Definition: SF.h:243
String Engineers
[<IENG-ck>] ; Sound Designers and Engineers for the Bank
Definition: SF.h:248
std::vector< PresetBag > PresetBags
Definition: SF.h:543
int startloopAddrsOffset
Definition: SF.h:361
#define LIST_TYPE_INFO
Definition: RIFF.h:98
#define CHUNK_ID_PMOD
Definition: SF.h:53
double GetFreqModLfo(Region *pPresetRegion=NULL)
Definition: SF.cpp:682
Sample * GetSample()
Definition: SF.h:379
int GetSampleCount()
Definition: SF.cpp:1209
Instrument * pInstrument
Definition: SF.h:376
double GetEG2Attack(Region *pPresetRegion=NULL)
Definition: SF.cpp:622
Definition: SF.h:131
unsigned long Size
Size of the actual data in the buffer in bytes.
Definition: SF.h:287
Region * GetRegion(int idx)
Definition: SF.cpp:740
int GetModEnvToPitch(Region *pPresetRegion=NULL)
Definition: SF.cpp:652
Region()
Definition: SF.cpp:262
SFTransform ModTransOper
Definition: SF.h:84
int GetModLfoToFilterFc(Region *pPresetRegion=NULL)
Definition: SF.cpp:670
#define CHUNK_ID_INST
Definition: SF.h:55
unsigned long ReadAndLoop(void *pBuffer, unsigned long FrameCount, PlaybackState *pPlaybackState, Region *pRegion)
Reads SampleCount number of sample points from the position stored in pPlaybackState into the buffer ...
Definition: SF.cpp:233
int endAddrsOffset
Definition: SF.h:360
Region * next()
Definition: SF.cpp:752
int GetUnityNote()
Definition: SF.cpp:294
RIFF::Chunk * pCkSm24
Definition: SF.h:328
bool Polarity
Definition: SF.h:208
unsigned long ReadSample(Sample *pSample, void *pBuffer, unsigned long SampleCount, Sample::buffer_t *tempBuffer=NULL)
Definition: SF.cpp:1409
std::vector< GenList > InstGenLists
Definition: SF.h:548
String BankName
<INAM-ck> ; Refers to the Sound Font Bank Name
Definition: SF.h:244
Info(RIFF::List *list)
Constructor.
Definition: SF.cpp:115
uint16_t InstBagNdx
Definition: SF.h:487
void ReleaseSampleData()
Frees the cached sample from RAM if loaded with LoadSampleData() previously.
Definition: SF.cpp:1378
int GetModEnvToFilterFc(Region *pPresetRegion=NULL)
Definition: SF.cpp:664
int maxVel
Definition: SF.h:355
Sample * GetSample(int idx)
Definition: SF.cpp:1213
unsigned long ReadInt8(int8_t *pData, unsigned long WordCount=1)
Reads WordCount number of 8 Bit signed integer words and copies it into the buffer pointed by pData.
Definition: RIFF.cpp:426
RIFF::File * pRIFF
Definition: SF.h:542
int CheckRange(std::string genName, int min, int max, int &gen)
Definition: SF.cpp:298