libgig  3.3.0.svn3
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);
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 
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 * 64; pan /= 500;
381  if (pan < -64) pan = -64;
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;
425  break;
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;
453  break;
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;
477  startloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
479  break;
480  case KEYNUM:
481  break;
482  case VELOCITY:
483  break;
484  case INITIAL_ATTENUATION:
485  break;
487  endloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
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) {
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) ?
668  return CheckRange("GetModEnvToFilterFc()", -12000, +12000, val);
669  }
670 
671  int Region::GetModLfoToFilterFc(Region* pPresetRegion) {
672  int val = (pPresetRegion == NULL || pPresetRegion->modLfoToFilterFc == NONE) ?
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 
726  this->pFile = pFile;
727  pGlobalRegion = NULL;
728  }
729 
731  if (pGlobalRegion) delete pGlobalRegion;
732  for (int i = regions.size() - 1; i >= 0; i--) {
733  if (regions[i]) delete (regions[i]);
734  }
735  }
736 
738  return regions.size();
739  }
740 
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 
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 
765  this->pFile = pFile;
766  LoadString(ck, Name, 20);
767  InstBagNdx = ck->ReadInt16();
768  }
769 
771  }
772 
774  Region* r = new Region;
775  r->pParentInstrument = this;
776 
777  if (pGlobalRegion != NULL) {
778  r->loKey = pGlobalRegion->loKey;
779  r->hiKey = pGlobalRegion->hiKey;
782  r->pan = pGlobalRegion->pan;
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 
821 
825 
827  }
828 
829  return r;
830  }
831 
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 
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 
896  }
897 
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;
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 
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 
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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = ck->GetSize() / 46;
1125  for (int i = 0; i < count; i++) {
1126  Samples.push_back(new Sample(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 
1155  delete pInfo;
1156  for (int i = Presets.size() - 1; i >= 0; i--) {
1157  if (Presets[i]) delete (Presets[i]);
1158  }
1159  for (int i = Instruments.size() - 1; i >= 0; i--) {
1160  if (Instruments[i]) delete (Instruments[i]);
1161  }
1162  for (int i = Samples.size() - 1; i >= 0; i--) {
1163  if (Samples[i]) delete (Samples[i]);
1164  }
1165  }
1166 
1168  return Presets.size() - 1; // exclude terminal preset (EOP)
1169  }
1170 
1172  if (idx < 0 || idx >= GetPresetCount()) {
1173  throw Exception("Preset index out of bounds");
1174  }
1175 
1176  return Presets[idx];
1177  }
1178 
1180  return Instruments.size() - 1; // exclude terminal instrument (EOI)
1181  }
1182 
1184  if (idx < 0 || idx >= GetInstrumentCount()) {
1185  throw Exception("Instrument index out of bounds");
1186  }
1187 
1188  return Instruments[idx];
1189  }
1190 
1191  void File::DeleteInstrument(Instrument* pInstrument) {
1192  for (int i = 0; i < GetPresetCount(); i++) {
1193  Preset* p = GetPreset(i);
1194  if (p == NULL) continue;
1195  for (int j = p->GetRegionCount() - 1; j >= 0 ; j--) {
1196  if (p->GetRegion(j) && p->GetRegion(j)->pInstrument == pInstrument) {
1197  p->GetRegion(j)->pInstrument = NULL;
1198  }
1199  }
1200  }
1201 
1202  for (int i = 0; i < GetInstrumentCount(); i++) {
1203  if (GetInstrument(i) == pInstrument) {
1204  Instruments[i] = NULL;
1205  delete pInstrument;
1206  }
1207  }
1208  }
1209 
1211  return Samples.size() - 1; // exclude terminal sample (EOS)
1212  }
1213 
1215  if (idx < 0 || idx >= GetSampleCount()) {
1216  throw Exception("Sample index out of bounds");
1217  }
1218 
1219  return Samples[idx];
1220  }
1221 
1222  void File::DeleteSample(Sample* pSample) {
1223  // Sanity check
1224  for (int i = GetInstrumentCount() - 1; i >= 0; i--) {
1225  Instrument* pInstr = GetInstrument(i);
1226  if (pInstr == NULL) continue;
1227 
1228  for (int j = pInstr->GetRegionCount() - 1; j >= 0 ; j--) {
1229  if (pInstr->GetRegion(j) && pInstr->GetRegion(j)->GetSample() == pSample) {
1230  std::cerr << "Deleting sample which is still in use" << std::endl;
1231  }
1232  }
1233  }
1235 
1236  for (int i = 0; i < GetSampleCount(); i++) {
1237  if (Samples[i] == pSample) {
1238  delete pSample;
1239  Samples[i] = NULL;
1240  return;
1241  }
1242  }
1243 
1244  throw Exception("Unknown sample: " + pSample->Name);
1245  }
1246 
1248  for (int i = 0; i < GetSampleCount(); i++) {
1249  if (Samples[i] != NULL) return true;
1250  }
1251 
1252  return false;
1253  }
1254 
1265  return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), 0); // 0 amount of NullSamples
1266  }
1267 
1286  Sample::buffer_t Sample::LoadSampleData(unsigned long SampleCount) {
1287  return LoadSampleDataWithNullSamplesExtension(SampleCount, 0); // 0 amount of NullSamples
1288  }
1289 
1310  return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), NullSamplesCount);
1311  }
1312 
1341  Sample::buffer_t Sample::LoadSampleDataWithNullSamplesExtension(unsigned long SampleCount, uint NullSamplesCount) {
1342  if (SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount();
1343  if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
1344  unsigned long allocationsize = (SampleCount + NullSamplesCount) * GetFrameSize();
1345  SetPos(0); // reset read position to begin of sample
1346  RAMCache.pStart = new int8_t[allocationsize];
1347  RAMCache.Size = Read(RAMCache.pStart, SampleCount) * GetFrameSize();
1348  RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
1349  // fill the remaining buffer space with silence samples
1350  memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
1351  return GetCache();
1352  }
1353 
1365  // return a copy of the buffer_t structure
1366  buffer_t result;
1367  result.Size = this->RAMCache.Size;
1368  result.pStart = this->RAMCache.pStart;
1370  return result;
1371  }
1372 
1380  if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
1381  RAMCache.pStart = NULL;
1382  RAMCache.Size = 0;
1384  }
1385 
1395  unsigned long Sample::SetPos(unsigned long SampleCount) {
1396  pCkSmpl->SetPos((Start * 2) + (SampleCount * 2), RIFF::stream_start);
1397  if(pCkSm24) pCkSm24->SetPos(Start + SampleCount, RIFF::stream_start);
1398  return SampleCount;
1399  }
1400 
1404  unsigned long Sample::GetPos() {
1405  return (pCkSmpl->GetPos() - (Start * 2)) / 2;
1406  }
1407 
1424  unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
1425  // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
1426  if (SampleCount == 0) return 0;
1427  long pos = GetPos();
1428  if (pos + SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount() - pos;
1429 
1430  if (GetFrameSize() / GetChannelCount() == 3 /* 24 bit */) {
1431  uint8_t* pBuf = (uint8_t*)pBuffer;
1433  pCkSmpl->Read(pBuf, SampleCount, 2);
1434  pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
1435  for (int i = SampleCount - 1; i >= 0; i--) {
1436  pBuf[i*3] = pBuf[(SampleCount * 2) + i];
1437  pBuf[i*3 + 2] = pBuf[i*2 + 1];
1438  pBuf[i*3 + 1] = pBuf[i*2];
1439  }
1440  } else if (SampleType == LEFT_SAMPLE || SampleType == ROM_LEFT_SAMPLE) {
1441  pCkSmpl->Read(pBuf, SampleCount, 2);
1442  pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
1443  for (int i = SampleCount - 1; i >= 0; i--) {
1444  pBuf[i*6] = pBuf[(SampleCount * 2) + i];
1445  pBuf[i*6 + 2] = pBuf[i*2 + 1];
1446  pBuf[i*6 + 1] = pBuf[i*2];
1447  pBuf[i*6 + 3] = pBuf[i*6 + 4] = pBuf[i*6 + 5] = 0;
1448  }
1449  } else if (SampleType == RIGHT_SAMPLE || SampleType == ROM_RIGHT_SAMPLE) {
1450  pCkSmpl->Read(pBuf, SampleCount, 2);
1451  pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
1452  for (int i = SampleCount - 1; i >= 0; i--) {
1453  pBuf[i*6 + 3] = pBuf[(SampleCount * 2) + i];
1454  pBuf[i*6 + 5] = pBuf[i*2 + 1];
1455  pBuf[i*6 + 4] = pBuf[i*2];
1456  pBuf[i*6] = pBuf[i*6 + 1] = pBuf[i*6 + 2] = 0;
1457  }
1458  }
1459  } else {
1461  return pCkSmpl->Read(pBuffer, SampleCount, 2);
1462  }
1463 
1464  int16_t* pBuf = (int16_t*)pBuffer;
1466  pCkSmpl->Read(pBuf, SampleCount, 2);
1467  for (int i = SampleCount - 1; i >= 0; i--) {
1468  pBuf[i*2] = pBuf[i];
1469  pBuf[i*2 + 1] = 0;
1470  }
1471  } else if (SampleType == RIGHT_SAMPLE || SampleType == ROM_RIGHT_SAMPLE) {
1472  pCkSmpl->Read(pBuf, SampleCount, 2);
1473  for (int i = SampleCount - 1; i >= 0; i--) {
1474  pBuf[i*2] = 0;
1475  pBuf[i*2 + 1] = pBuf[i];
1476  }
1477  }
1478  }
1479 
1480  if (pCkSmpl->GetPos() > (End * 2)) {
1481  std::cerr << "Read after the sample end. This is a BUG!" << std::endl;
1482  std::cerr << "Current position: " << GetPos() << std::endl;
1483  std::cerr << "Total number of frames: " << GetTotalFrameCount() << std::endl << std::endl;
1484  }
1485  return SampleCount;
1486  }
1487 
1488 
1489 // *************** functions ***************
1490 // *
1491 
1496  return PACKAGE;
1497  }
1498 
1503  return VERSION;
1504  }
1505 
1506 } // namespace sf2