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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2016 by iliev, Tue Oct 27 18:34:06 2009 UTC revision 2100 by persson, Sun May 30 11:39:36 2010 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   libsf2 - C++ cross-platform SF2 format file access library            *   *   libsf2 - C++ cross-platform SF2 format file access library            *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2009 Grigor Iliev  <grigor@grigoriliev.com>             *   *   Copyright (C) 2009-2010 Grigor Iliev  <grigor@grigoriliev.com>,       *
6   *   Copyright (C) 2009 Christian Schoenebeck                              *   *    Christian Schoenebeck and Andreas Persson                            *
  *   Copyright (C) 2009 Andreas Persson                                    *  
7   *                                                                         *   *                                                                         *
8   *   This library is free software; you can redistribute it and/or modify  *   *   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  *   *   it under the terms of the GNU General Public License as published by  *
# Line 22  Line 21 
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
 #include <vector>  
   
24  #include "RIFF.h"  #include "RIFF.h"
25    
26  #include "SF.h"  #include "SF.h"
# Line 36  Line 33 
33    
34  namespace sf2 {  namespace sf2 {
35      double ToSeconds(int Timecents) {      double ToSeconds(int Timecents) {
36            if (Timecents == NONE) return NONE;
37          if (Timecents == 0) return 1.0;          if (Timecents == 0) return 1.0;
38          if (Timecents == -32768) return 0.0;          if (Timecents == -32768) return 0.0;
39          return pow(_1200TH_ROOT_OF_2, Timecents);          return pow(_1200TH_ROOT_OF_2, Timecents);
40      }      }
41    
42      double ToPermilles(int Centibels) {      double ToPermilles(int Centibels) {
43            if (Centibels == NONE) return NONE;
44          if (Centibels == 0) return 1000.0;          if (Centibels == 0) return 1000.0;
45          if (Centibels < 0) return 0.0;          if (Centibels < 0) return 0.0;
46          return pow(_200TH_ROOT_OF_10, Centibels);          return pow(_200TH_ROOT_OF_10, Centibels);
47      }      }
48    
49        double ToHz(int cents) {
50            if (cents == NONE) return NONE;
51            if (cents == 0) return 8.176;
52            return pow(_1200TH_ROOT_OF_2, cents) * 8.176;
53        }
54    
55      RIFF::Chunk* GetMandatoryChunk(RIFF::List* list, uint32_t chunkId) {      RIFF::Chunk* GetMandatoryChunk(RIFF::List* list, uint32_t chunkId) {
56          RIFF::Chunk* ck = list->GetSubChunk(chunkId);          RIFF::Chunk* ck = list->GetSubChunk(chunkId);
57          if(ck == NULL) throw Exception("Mandatory chunk in RIFF list chunk not found: " + ToString(chunkId));          if(ck == NULL) throw Exception("Mandatory chunk in RIFF list chunk not found: " + ToString(chunkId));
# Line 229  namespace sf2 { Line 234  namespace sf2 {
234      unsigned long Sample::ReadAndLoop (      unsigned long Sample::ReadAndLoop (
235          void*           pBuffer,          void*           pBuffer,
236          unsigned long   FrameCount,          unsigned long   FrameCount,
237          PlaybackState*  pPlaybackState          PlaybackState*  pPlaybackState,
238            Region*         pRegion
239      ) {      ) {
240            // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
241            unsigned long samplestoread = FrameCount, totalreadsamples = 0, readsamples, samplestoloopend;
242            uint8_t* pDst = (uint8_t*) pBuffer;
243          SetPos(pPlaybackState->position);          SetPos(pPlaybackState->position);
244          long frames = Read(pBuffer, FrameCount);          if (pRegion->HasLoop) {
245                do {
246                    samplestoloopend  = pRegion->LoopEnd - GetPos();
247                    readsamples       = Read(&pDst[totalreadsamples * GetFrameSize()], Min(samplestoread, samplestoloopend));
248                    samplestoread    -= readsamples;
249                    totalreadsamples += readsamples;
250                    if (readsamples == samplestoloopend) {
251                        SetPos(pRegion->LoopStart);
252                    }
253                } while (samplestoread && readsamples);
254            } else {
255                totalreadsamples = Read(pBuffer, FrameCount);
256            }
257    
258          pPlaybackState->position = GetPos();          pPlaybackState->position = GetPos();
259          // TODO: Implement looping  
260          return frames;          return totalreadsamples;
261      }      }
262    
263      Region::Region() {      Region::Region() {
264          pSample = NULL;          pSample = NULL;
265          pInstrument = NULL;          pInstrument = NULL;
266            pParentInstrument = NULL;
267          loKey = hiKey = NONE;          loKey = hiKey = NONE;
268          minVel = maxVel = NONE;          minVel = maxVel = NONE;
269          startAddrsOffset = startAddrsCoarseOffset = endAddrsOffset = 0;          startAddrsOffset = startAddrsCoarseOffset = endAddrsOffset = endAddrsCoarseOffset = 0;
270          startloopAddrsOffset = endloopAddrsOffset = 0;          startloopAddrsOffset = startloopAddrsCoarseOffset = endloopAddrsOffset = endloopAddrsCoarseOffset = 0;
271          pan = fineTune = 0;          pan = fineTune = coarseTune = 0;
272            overridingRootKey = -1; // -1 means not used
273    
274            HasLoop = false;
275            LoopStart = LoopEnd = 0;
276    
277          EG1PreAttackDelay = EG1Attack = EG1Hold = EG1Decay = EG1Release = ToSeconds(-12000);          EG1PreAttackDelay = EG1Attack = EG1Hold = EG1Decay = EG1Release = -12000;
278          EG1Sustain = 0;          EG1Sustain = 0;
279          EG2PreAttackDelay = EG2Attack = EG2Hold = EG2Decay = EG2Release = ToSeconds(-12000);          EG2PreAttackDelay = EG2Attack = EG2Hold = EG2Decay = EG2Release = -12000;
280          EG2Sustain = 0;          EG2Sustain = 0;
281    
282            modEnvToPitch = modLfoToPitch = modEnvToFilterFc = modLfoToFilterFc = modLfoToVolume = 0;
283            freqModLfo = 0;
284            delayModLfo = -12000;
285            vibLfoToPitch = 0;
286            freqVibLfo = 0;
287            delayVibLfo = -12000;
288    
289            exclusiveClass = 0;
290        }
291    
292        int Region::GetUnityNote() {
293            return overridingRootKey != -1 ? overridingRootKey : pSample->OriginalPitch;
294      }      }
295    
296      void Region::SetGenerator(sf2::File* pFile, GenList& Gen) {      void Region::SetGenerator(sf2::File* pFile, GenList& Gen) {
# Line 267  namespace sf2 { Line 307  namespace sf2 {
307                  break;                  break;
308              case STARTLOOP_ADDRS_OFFSET:              case STARTLOOP_ADDRS_OFFSET:
309                  startloopAddrsOffset = Gen.GenAmount.shAmount;                  startloopAddrsOffset = Gen.GenAmount.shAmount;
310                    LoopStart += startloopAddrsOffset;
311                  break;                  break;
312              case ENDLOOP_ADDRS_OFFSET:              case ENDLOOP_ADDRS_OFFSET:
313                  endloopAddrsOffset = Gen.GenAmount.shAmount;                  endloopAddrsOffset = Gen.GenAmount.shAmount;
314                    LoopEnd += endloopAddrsOffset;
315                  break;                  break;
316              case START_ADDRS_COARSE_OFFSET:              case START_ADDRS_COARSE_OFFSET:
317                  startAddrsCoarseOffset = Gen.GenAmount.wAmount;                  startAddrsCoarseOffset = Gen.GenAmount.wAmount;
318                  break;                  break;
319              case MOD_LFO_TO_PITCH:              case MOD_LFO_TO_PITCH:
320                    modLfoToPitch = Gen.GenAmount.shAmount;
321                  break;                  break;
322              case VIB_LFO_TO_PITCH:              case VIB_LFO_TO_PITCH:
323                    vibLfoToPitch = Gen.GenAmount.shAmount;
324                  break;                  break;
325              case MOD_ENV_TO_PITCH:              case MOD_ENV_TO_PITCH:
326                    modEnvToPitch = Gen.GenAmount.shAmount;
327                  break;                  break;
328              case INITIAL_FILTER_FC:              case INITIAL_FILTER_FC:
329                  break;                  break;
330              case INITIAL_FILTER_Q:              case INITIAL_FILTER_Q:
331                  break;                  break;
332              case MOD_LFO_TO_FILTER_FC:              case MOD_LFO_TO_FILTER_FC:
333                    modLfoToFilterFc = Gen.GenAmount.shAmount;
334                  break;                  break;
335              case MOD_ENV_TO_FILTER_FC:              case MOD_ENV_TO_FILTER_FC:
336                    modEnvToFilterFc = Gen.GenAmount.shAmount;
337                  break;                  break;
338              case END_ADDRS_COARSE_OFFSET:              case END_ADDRS_COARSE_OFFSET:
339                    endAddrsCoarseOffset = Gen.GenAmount.wAmount;
340                  break;                  break;
341              case MOD_LFO_TO_VOLUME:              case MOD_LFO_TO_VOLUME:
342                    modLfoToVolume = Gen.GenAmount.shAmount;
343                  break;                  break;
344              case CHORUS_EFFECTS_SEND:              case CHORUS_EFFECTS_SEND:
345                  break;                  break;
# Line 303  namespace sf2 { Line 352  namespace sf2 {
352                  if (pan >  63) pan =  63;                  if (pan >  63) pan =  63;
353                  break;                  break;
354              case DELAY_MOD_LFO:              case DELAY_MOD_LFO:
355                    delayModLfo = Gen.GenAmount.shAmount;
356                  break;                  break;
357              case FREQ_MOD_LFO:              case FREQ_MOD_LFO:
358                    freqModLfo = Gen.GenAmount.shAmount;
359                  break;                  break;
360              case DELAY_VIB_LFO:              case DELAY_VIB_LFO:
361                    delayVibLfo = Gen.GenAmount.shAmount;
362                  break;                  break;
363              case FREQ_VIB_LFO:              case FREQ_VIB_LFO:
364                    freqVibLfo = Gen.GenAmount.shAmount;
365                  break;                  break;
366              case DELAY_MOD_ENV:              case DELAY_MOD_ENV:
367                  EG2PreAttackDelay = ToSeconds(Gen.GenAmount.shAmount);                  EG2PreAttackDelay = Gen.GenAmount.shAmount;
368                  break;                  break;
369              case ATTACK_MOD_ENV:              case ATTACK_MOD_ENV:
370                  EG2Attack = ToSeconds(Gen.GenAmount.shAmount);                  EG2Attack = Gen.GenAmount.shAmount;
371                  break;                  break;
372              case HOLD_MOD_ENV:              case HOLD_MOD_ENV:
373                  EG2Hold = ToSeconds(Gen.GenAmount.shAmount);                  EG2Hold = Gen.GenAmount.shAmount;
374                  break;                  break;
375              case DECAY_MOD_ENV:              case DECAY_MOD_ENV:
376                  EG2Decay = ToSeconds(Gen.GenAmount.shAmount);                  EG2Decay = Gen.GenAmount.shAmount;
377                  break;                  break;
378              case SUSTAIN_MOD_ENV:              case SUSTAIN_MOD_ENV:
379                  EG2Sustain = 1000 - Gen.GenAmount.shAmount;                  EG2Sustain = Gen.GenAmount.shAmount;
380                  break;                  break;
381              case RELEASEMODENV:              case RELEASEMODENV:
382                  EG2Release = ToSeconds(Gen.GenAmount.shAmount);                  EG2Release = Gen.GenAmount.shAmount;
383                  break;                  break;
384              case KEYNUM_TO_MOD_ENV_HOLD:              case KEYNUM_TO_MOD_ENV_HOLD:
385                  break;                  break;
386              case KEYNUM_TO_MOD_ENV_DECAY:              case KEYNUM_TO_MOD_ENV_DECAY:
387                  break;                  break;
388              case DELAY_VOL_ENV:              case DELAY_VOL_ENV:
389                  EG1PreAttackDelay = ToSeconds(Gen.GenAmount.shAmount);                  EG1PreAttackDelay = Gen.GenAmount.shAmount;
390                  break;                  break;
391              case ATTACK_VOL_ENV:              case ATTACK_VOL_ENV:
392                  EG1Attack = ToSeconds(Gen.GenAmount.shAmount);                  EG1Attack = Gen.GenAmount.shAmount;
393                  break;                  break;
394              case HOLD_VOL_ENV:              case HOLD_VOL_ENV:
395                  EG1Hold = ToSeconds(Gen.GenAmount.shAmount);                  EG1Hold = Gen.GenAmount.shAmount;
396                  break;                  break;
397              case DECAY_VOL_ENV:              case DECAY_VOL_ENV:
398                  EG1Decay = ToSeconds(Gen.GenAmount.shAmount);                  EG1Decay = Gen.GenAmount.shAmount;
399                  break;                  break;
400              case SUSTAIN_VOL_ENV:              case SUSTAIN_VOL_ENV:
401                  EG1Sustain = ToPermilles(Gen.GenAmount.shAmount);                  EG1Sustain = Gen.GenAmount.shAmount;
402                  break;                  break;
403              case RELEASE_VOL_ENV:              case RELEASE_VOL_ENV:
404                  EG1Release = ToSeconds(Gen.GenAmount.shAmount);                  EG1Release = Gen.GenAmount.shAmount;
405                  break;                  break;
406              case KEYNUM_TO_VOL_ENV_HOLD:              case KEYNUM_TO_VOL_ENV_HOLD:
407                  break;                  break;
# Line 371  namespace sf2 { Line 424  namespace sf2 {
424                  maxVel = Gen.GenAmount.ranges.byHi;                  maxVel = Gen.GenAmount.ranges.byHi;
425                  break;                  break;
426              case STARTLOOP_ADDRS_COARSE_OFFSET:              case STARTLOOP_ADDRS_COARSE_OFFSET:
427                    startloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
428                    LoopStart += startloopAddrsCoarseOffset * 32768;
429                  break;                  break;
430              case KEYNUM:              case KEYNUM:
431                  break;                  break;
# Line 379  namespace sf2 { Line 434  namespace sf2 {
434              case INITIAL_ATTENUATION:              case INITIAL_ATTENUATION:
435                  break;                  break;
436              case ENDLOOP_ADDRS_COARSE_OFFSET:              case ENDLOOP_ADDRS_COARSE_OFFSET:
437                    endloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
438                    LoopEnd += endloopAddrsCoarseOffset * 32768;
439                  break;                  break;
440              case COARSE_TUNE:              case COARSE_TUNE:
441                    coarseTune = Gen.GenAmount.shAmount;
442                    if (coarseTune < -120) coarseTune = -120;
443                    if (coarseTune >  120) coarseTune =  120;
444                  break;                  break;
445              case FINE_TUNE:              case FINE_TUNE:
446                  fineTune = Gen.GenAmount.shAmount;                  fineTune = Gen.GenAmount.shAmount;
# Line 391  namespace sf2 { Line 451  namespace sf2 {
451                      throw Exception("Broken SF2 file (missing samples)");                      throw Exception("Broken SF2 file (missing samples)");
452                  }                  }
453                  pSample = pFile->Samples[sid];                  pSample = pFile->Samples[sid];
454    
455                    if (HasLoop) {
456                        LoopStart += pSample->StartLoop;
457                        LoopEnd   += pSample->EndLoop;
458                        if ( LoopStart < pSample->Start || LoopStart > pSample->End ||
459                             LoopStart > LoopEnd        || LoopEnd   > pSample->End    ) {
460                            throw Exception("Broken SF2 file (invalid loops)");
461                        }
462                        LoopStart -= pSample->Start; // Relative to the sample start
463                        LoopEnd   -= pSample->Start; // Relative to the sample start
464                    }
465                  break;                  break;
466              }              }
467              case SAMPLE_MODES:              case SAMPLE_MODES:
468                    HasLoop = Gen.GenAmount.wAmount & 1;
469                    // TODO: 3 indicates a sound which loops for the duration of key depression
470                    //       then proceeds to play the remainder of the sample.
471                  break;                  break;
472              case SCALE_TUNING:              case SCALE_TUNING:
473                  break;                  break;
474              case EXCLUSIVE_CLASS:              case EXCLUSIVE_CLASS:
475                    exclusiveClass = Gen.GenAmount.wAmount;
476                  break;                  break;
477              case OVERRIDING_ROOT_KEY:              case OVERRIDING_ROOT_KEY:
478                    overridingRootKey = Gen.GenAmount.shAmount;
479                  break;                  break;
480          }          }
481      }      }
# Line 427  namespace sf2 { Line 503  namespace sf2 {
503          }*/          }*/
504      }      }
505    
506        int Region::GetPan(Region* pPresetRegion) {
507            if (pPresetRegion == NULL) return pan;
508            int p = pPresetRegion->pan + pan;
509            if (p < -64) p = -64;
510            if (p >  63) p =  63;
511            return p;
512        }
513    
514        int Region::GetFineTune(Region* pPresetRegion) {
515            if (pPresetRegion == NULL) return fineTune;
516            int t = pPresetRegion->fineTune + fineTune;
517            if (t < -99) t = -99;
518            if (t >  99) t =  99;
519            return t;
520        }
521    
522        int Region::GetCoarseTune(Region* pPresetRegion) {
523             if (pPresetRegion == NULL) return coarseTune;
524            int t = pPresetRegion->coarseTune + coarseTune;
525            if (t < -120) t = -120;
526            if (t >  120) t =  120;
527            return t;
528        }
529    
530        double Region::GetEG1PreAttackDelay(Region* pPresetRegion) {
531            if (pPresetRegion == NULL || pPresetRegion->EG1PreAttackDelay == NONE) return ToSeconds(EG1PreAttackDelay);
532            return ToSeconds(pPresetRegion->EG1PreAttackDelay + EG1PreAttackDelay);
533        }
534    
535        double Region::GetEG1Attack(Region* pPresetRegion) {
536            if (pPresetRegion == NULL || pPresetRegion->EG1Attack == NONE) return ToSeconds(EG1Attack);
537            return ToSeconds(pPresetRegion->EG1Attack + EG1Attack);
538        }
539    
540        double Region::GetEG1Hold(Region* pPresetRegion) {
541            if (pPresetRegion == NULL || pPresetRegion->EG1Hold == NONE) return ToSeconds(EG1Hold);
542            return ToSeconds(pPresetRegion->EG1Hold + EG1Hold);
543        }
544    
545        double Region::GetEG1Decay(Region* pPresetRegion) {
546            if (pPresetRegion == NULL || pPresetRegion->EG1Decay == NONE) return ToSeconds(EG1Decay);
547            return ToSeconds(pPresetRegion->EG1Decay + EG1Decay);
548        }
549    
550        double Region::GetEG1Sustain(Region* pPresetRegion) {
551            if (pPresetRegion == NULL || pPresetRegion->EG1Sustain == NONE) return ToPermilles(EG1Sustain);
552            return ToPermilles(pPresetRegion->EG1Sustain + EG1Sustain);
553        }
554    
555        double Region::GetEG1Release(Region* pPresetRegion) {
556            if (pPresetRegion == NULL || pPresetRegion->EG1Release == NONE) return ToSeconds(EG1Release);
557            return ToSeconds(pPresetRegion->EG1Release + EG1Release);
558        }
559    
560        double Region::GetEG2PreAttackDelay(Region* pPresetRegion) {
561            if (pPresetRegion == NULL || pPresetRegion->EG2PreAttackDelay == NONE) return ToSeconds(EG2PreAttackDelay);
562            return ToSeconds(pPresetRegion->EG2PreAttackDelay + EG2PreAttackDelay);
563        }
564    
565        double Region::GetEG2Attack(Region* pPresetRegion) {
566            if (pPresetRegion == NULL || pPresetRegion->EG2Attack == NONE) return ToSeconds(EG2Attack);
567            return ToSeconds(pPresetRegion->EG2Attack + EG2Attack);
568        }
569    
570        double Region::GetEG2Hold(Region* pPresetRegion) {
571            if (pPresetRegion == NULL || pPresetRegion->EG2Hold == NONE) return ToSeconds(EG2Hold);
572            return ToSeconds(pPresetRegion->EG2Hold + EG2Hold);
573        }
574    
575        double Region::GetEG2Decay(Region* pPresetRegion) {
576            if (pPresetRegion == NULL || pPresetRegion->EG2Decay == NONE) return ToSeconds(EG2Decay);
577            return ToSeconds(pPresetRegion->EG2Decay + EG2Decay);
578        }
579    
580        double Region::GetEG2Sustain(Region* pPresetRegion) {
581            if (pPresetRegion == NULL || pPresetRegion->EG2Sustain == NONE) {
582                return EG2Sustain == NONE ? NONE : 1000 - EG2Sustain;
583            }
584            return 1000 - (pPresetRegion->EG2Sustain + EG2Sustain);
585        }
586    
587        double Region::GetEG2Release(Region* pPresetRegion) {
588            if (pPresetRegion == NULL || pPresetRegion->EG2Release == NONE) return ToSeconds(EG2Release);
589            return ToSeconds(pPresetRegion->EG2Release + EG2Release);
590        }
591    
592        int Region::GetModEnvToPitch(Region* pPresetRegion) {
593            return modEnvToPitch + (pPresetRegion ? pPresetRegion->modEnvToPitch : 0);
594        }
595    
596        int Region::GetModLfoToPitch(Region* pPresetRegion) {
597            return modLfoToPitch + (pPresetRegion ? pPresetRegion->modLfoToPitch : 0);
598        }
599    
600        int Region::GetModEnvToFilterFc(Region* pPresetRegion) {
601            return modEnvToFilterFc + (pPresetRegion ? pPresetRegion->modEnvToFilterFc : 0);
602        }
603    
604        int Region::GetModLfoToFilterFc(Region* pPresetRegion) {
605            return modLfoToFilterFc + (pPresetRegion ? pPresetRegion->modLfoToFilterFc : 0);
606        }
607    
608        double Region::GetModLfoToVolume(Region* pPresetRegion) {
609            return ToPermilles(modLfoToVolume + (pPresetRegion ? pPresetRegion->modLfoToVolume : 0));
610        }
611    
612        double Region::GetFreqModLfo(Region* pPresetRegion) {
613            if (pPresetRegion == NULL || pPresetRegion->freqModLfo == NONE) return ToHz(freqModLfo);
614            return ToHz(pPresetRegion->freqModLfo + freqModLfo);
615        }
616    
617        double Region::GetDelayModLfo(Region* pPresetRegion) {
618            if (pPresetRegion == NULL || pPresetRegion->delayModLfo == NONE) return ToSeconds(delayModLfo);
619            return ToSeconds(pPresetRegion->delayModLfo + delayModLfo);
620        }
621    
622        int Region::GetVibLfoToPitch(Region* pPresetRegion) {
623            return vibLfoToPitch + (pPresetRegion ? pPresetRegion->vibLfoToPitch : 0);
624        }
625    
626        double Region::GetFreqVibLfo(Region* pPresetRegion) {
627            if (pPresetRegion == NULL || pPresetRegion->freqVibLfo == NONE) return ToHz(freqVibLfo);
628            return ToHz(pPresetRegion->freqVibLfo + freqVibLfo);
629        }
630    
631        double Region::GetDelayVibLfo(Region* pPresetRegion) {
632            if (pPresetRegion == NULL || pPresetRegion->delayVibLfo == NONE) return ToSeconds(delayVibLfo);
633            return ToSeconds(pPresetRegion->delayVibLfo + delayVibLfo);
634        }
635    
636      InstrumentBase::InstrumentBase(sf2::File* pFile) {      InstrumentBase::InstrumentBase(sf2::File* pFile) {
637          this->pFile = pFile;          this->pFile = pFile;
638          pGlobalRegion = NULL;          pGlobalRegion = NULL;
# Line 440  namespace sf2 { Line 646  namespace sf2 {
646      }      }
647    
648      int InstrumentBase::GetRegionCount() {      int InstrumentBase::GetRegionCount() {
649          return regions.size() - 1; // exclude terminal region          return regions.size();
650      }      }
651    
652      Region* InstrumentBase::GetRegion(int idx) {      Region* InstrumentBase::GetRegion(int idx) {
# Line 451  namespace sf2 { Line 657  namespace sf2 {
657          return regions[idx];          return regions[idx];
658      }      }
659    
660      std::vector<Region*> InstrumentBase::GetRegionsOnKey(int key, uint8_t vel) {      Query::Query(InstrumentBase& instrument) : instrument(instrument) {
661          std::vector<Region*> v;          i = 0;
662          for (int i = 0; i < GetRegionCount(); i++) {      }
663              Region* r = GetRegion(i);  
664              if (      Region* Query::next() {
665                  key >= r->loKey && key <= r->hiKey &&          while (i < instrument.GetRegionCount()) {
666                  ((r->minVel == NONE && r->maxVel == NONE) || (vel >= r->minVel && vel <= r->maxVel))              Region* r = instrument.GetRegion(i++);
667              ) {              if (((r->loKey  == NONE && r->hiKey  == NONE) || (key >= r->loKey && key <= r->hiKey)) &&
668                  v.push_back(r);                  ((r->minVel == NONE && r->maxVel == NONE) || (vel >= r->minVel && vel <= r->maxVel))) {
669                    return r;
670              }              }
671          }          }
672            return 0;
         return v;  
673      }      }
674    
675      Instrument::Instrument(sf2::File* pFile, RIFF::Chunk* ck) : InstrumentBase(pFile) {      Instrument::Instrument(sf2::File* pFile, RIFF::Chunk* ck) : InstrumentBase(pFile) {
# Line 473  namespace sf2 { Line 679  namespace sf2 {
679      }      }
680    
681      Instrument::~Instrument() {      Instrument::~Instrument() {
682                }
683    
684        Region* Instrument::CreateRegion() {
685            Region* r = new Region;
686            r->pParentInstrument = this;
687    
688            if (pGlobalRegion != NULL) {
689                r->loKey       = pGlobalRegion->loKey;
690                r->hiKey       = pGlobalRegion->hiKey;
691                r->minVel      = pGlobalRegion->minVel;
692                r->maxVel      = pGlobalRegion->maxVel;
693                r->pan         = pGlobalRegion->pan;
694                r->fineTune    = pGlobalRegion->fineTune;
695                r->coarseTune  = pGlobalRegion->coarseTune;
696                r->overridingRootKey = pGlobalRegion->overridingRootKey;
697                r->startAddrsOffset            = pGlobalRegion->startAddrsOffset;
698                r->startAddrsCoarseOffset      = pGlobalRegion->startAddrsCoarseOffset;
699                r->endAddrsOffset              = pGlobalRegion->endAddrsOffset;
700                r->endAddrsCoarseOffset        = pGlobalRegion->endAddrsCoarseOffset;
701                r->startloopAddrsOffset        = pGlobalRegion->startloopAddrsOffset;
702                r->startloopAddrsCoarseOffset  = pGlobalRegion->startloopAddrsCoarseOffset;
703                r->endloopAddrsOffset          = pGlobalRegion->endloopAddrsOffset;
704                r->endloopAddrsCoarseOffset    = pGlobalRegion->endloopAddrsCoarseOffset;
705    
706                r->EG1PreAttackDelay  = pGlobalRegion->EG1PreAttackDelay;
707                r->EG1Attack          = pGlobalRegion->EG1Attack;
708                r->EG1Hold            = pGlobalRegion->EG1Hold;
709                r->EG1Decay           = pGlobalRegion->EG1Decay;
710                r->EG1Sustain         = pGlobalRegion->EG1Sustain;
711                r->EG1Release         = pGlobalRegion->EG1Release;
712    
713                r->EG2PreAttackDelay  = pGlobalRegion->EG2PreAttackDelay;
714                r->EG2Attack          = pGlobalRegion->EG2Attack;
715                r->EG2Hold            = pGlobalRegion->EG2Hold;
716                r->EG2Decay           = pGlobalRegion->EG2Decay;
717                r->EG2Sustain         = pGlobalRegion->EG2Sustain;
718                r->EG2Release         = pGlobalRegion->EG2Release;
719    
720                r->modEnvToPitch     = pGlobalRegion->modEnvToPitch;
721                r->modLfoToPitch     = pGlobalRegion->modLfoToPitch;
722                r->modEnvToFilterFc  = pGlobalRegion->modEnvToFilterFc;
723                r->modLfoToFilterFc  = pGlobalRegion->modLfoToFilterFc;
724                r->modLfoToVolume    = pGlobalRegion->modLfoToVolume;
725                r->freqModLfo        = pGlobalRegion->freqModLfo;
726                r->delayModLfo       = pGlobalRegion->delayModLfo;
727                r->vibLfoToPitch     = pGlobalRegion->vibLfoToPitch;
728                r->freqVibLfo        = pGlobalRegion->freqVibLfo;
729                r->delayVibLfo       = pGlobalRegion->delayVibLfo;
730    
731                r->HasLoop    = pGlobalRegion->HasLoop;
732                r->LoopStart  = pGlobalRegion->LoopStart;
733                r->LoopEnd    = pGlobalRegion->LoopEnd;
734    
735                r->exclusiveClass = pGlobalRegion->exclusiveClass;
736            }
737    
738            return r;
739        }
740    
741        void Instrument::DeleteRegion(Region* pRegion) {
742            for (int i = 0; i < regions.size(); i++) {
743                if (regions[i] == pRegion) {
744                    delete pRegion;
745                    regions[i] = NULL;
746                    return;
747                }
748            }
749    
750            std::cerr << "Can't remove unknown Region" << std::endl;
751      }      }
752    
753      void Instrument::LoadRegions(int idx1, int idx2) {      void Instrument::LoadRegions(int idx1, int idx2) {
754          for (int i = idx1; i < idx2 - 1; i++) {          for (int i = idx1; i < idx2; i++) {
755              int gIdx1 = pFile->InstBags[i].InstGenNdx;              int gIdx1 = pFile->InstBags[i].InstGenNdx;
756              int gIdx2 = pFile->InstBags[i + 1].InstGenNdx;              int gIdx2 = pFile->InstBags[i + 1].InstGenNdx;
757    
# Line 492  namespace sf2 { Line 766  namespace sf2 {
766                  throw Exception("Broken SF2 file (invalid InstModNdx)");                  throw Exception("Broken SF2 file (invalid InstModNdx)");
767              }              }
768    
769              Region* reg = new Region;              Region* reg = CreateRegion();
770                
771              for (int j = gIdx1; j < gIdx2; j++) {              for (int j = gIdx1; j < gIdx2; j++) {
772                  reg->SetGenerator(pFile, pFile->InstGenLists[j]);                  reg->SetGenerator(pFile, pFile->InstGenLists[j]);
773                  // TODO: ignore generators following a sampleID generator                  // TODO: ignore generators following a sampleID generator
# Line 504  namespace sf2 { Line 778  namespace sf2 {
778              }              }
779    
780              if (reg->pSample == NULL) {              if (reg->pSample == NULL) {
781                  if (i == idx1) {                  if (i == idx1 && idx2 - idx1 > 1) {
782                      pGlobalRegion = reg;  // global zone                      pGlobalRegion = reg;  // global zone
783                  } else {                  } else {
784                      std::cerr << "Ignoring instrument's region without sample" << std::endl;                      std::cerr << "Ignoring instrument's region without sample" << std::endl;
# Line 528  namespace sf2 { Line 802  namespace sf2 {
802      }      }
803    
804      Preset::~Preset() {      Preset::~Preset() {
805                }
806    
807        Region* Preset::CreateRegion() {
808            Region* r = new Region;
809    
810            r->EG1PreAttackDelay = r->EG1Attack = r->EG1Hold = r->EG1Decay = r->EG1Sustain = r->EG1Release = NONE;
811            r->EG2PreAttackDelay = r->EG2Attack = r->EG2Hold = r->EG2Decay = r->EG2Sustain = r->EG2Release = NONE;
812            r->freqModLfo = r->delayModLfo = r->freqVibLfo = r->delayVibLfo = NONE;
813    
814            if (pGlobalRegion != NULL) {
815                r->pan         = pGlobalRegion->pan;
816                r->fineTune    = pGlobalRegion->fineTune;
817                r->coarseTune  = pGlobalRegion->coarseTune;
818    
819                r->EG1PreAttackDelay  = pGlobalRegion->EG1PreAttackDelay;
820                r->EG1Attack          = pGlobalRegion->EG1Attack;
821                r->EG1Hold            = pGlobalRegion->EG1Hold;
822                r->EG1Decay           = pGlobalRegion->EG1Decay;
823                r->EG1Sustain         = pGlobalRegion->EG1Sustain;
824                r->EG1Release         = pGlobalRegion->EG1Release;
825    
826                r->EG2PreAttackDelay  = pGlobalRegion->EG2PreAttackDelay;
827                r->EG2Attack          = pGlobalRegion->EG2Attack;
828                r->EG2Hold            = pGlobalRegion->EG2Hold;
829                r->EG2Decay           = pGlobalRegion->EG2Decay;
830                r->EG2Sustain         = pGlobalRegion->EG2Sustain;
831                r->EG2Release         = pGlobalRegion->EG2Release;
832    
833                r->modEnvToPitch     = pGlobalRegion->modEnvToPitch;
834                r->modLfoToPitch     = pGlobalRegion->modLfoToPitch;
835                r->modEnvToFilterFc  = pGlobalRegion->modEnvToFilterFc;
836                r->modLfoToFilterFc  = pGlobalRegion->modLfoToFilterFc;
837                r->modLfoToVolume    = pGlobalRegion->modLfoToVolume;
838                r->freqModLfo        = pGlobalRegion->freqModLfo;
839                r->delayModLfo       = pGlobalRegion->delayModLfo;
840                r->vibLfoToPitch     = pGlobalRegion->vibLfoToPitch;
841                r->freqVibLfo        = pGlobalRegion->freqVibLfo;
842                r->delayVibLfo       = pGlobalRegion->delayVibLfo;
843            }
844    
845            return r;
846      }      }
847    
848      void Preset::LoadRegions(int idx1, int idx2) {      void Preset::LoadRegions(int idx1, int idx2) {
849          for (int i = idx1; i < idx2 - 1; i++) {          for (int i = idx1; i < idx2; i++) {
850              int gIdx1 = pFile->PresetBags[i].GenNdx;              int gIdx1 = pFile->PresetBags[i].GenNdx;
851              int gIdx2 = pFile->PresetBags[i + 1].GenNdx;              int gIdx2 = pFile->PresetBags[i + 1].GenNdx;
852    
# Line 540  namespace sf2 { Line 854  namespace sf2 {
854                  throw Exception("Broken SF2 file (invalid PresetGenNdx)");                  throw Exception("Broken SF2 file (invalid PresetGenNdx)");
855              }              }
856    
857              Region* reg = new Region;              Region* reg = CreateRegion();
858    
859              for (int j = gIdx1; j < gIdx2; j++) {              for (int j = gIdx1; j < gIdx2; j++) {
860                  reg->SetGenerator(pFile, pFile->PresetGenLists[j]);                  reg->SetGenerator(pFile, pFile->PresetGenLists[j]);
861              }              }
862              if (reg->pInstrument == NULL) {              if (reg->pInstrument == NULL) {
863                  if (i == idx1) {                  if (i == idx1 && idx2 - idx1 > 1) {
864                      pGlobalRegion = reg;  // global zone                      pGlobalRegion = reg;  // global zone
865                  } else {                  } else {
866                      std::cerr << "Ignoring preset's region without instrument" << std::endl;                      std::cerr << "Ignoring preset's region without instrument" << std::endl;
# Line 755  namespace sf2 { Line 1069  namespace sf2 {
1069              if (Samples[i]) delete (Samples[i]);              if (Samples[i]) delete (Samples[i]);
1070          }          }
1071      }      }
1072        
1073      int File::GetPresetCount() {      int File::GetPresetCount() {
1074          return Presets.size() - 1; // exclude terminal preset (EOP)          return Presets.size() - 1; // exclude terminal preset (EOP)
1075      }      }
# Line 780  namespace sf2 { Line 1094  namespace sf2 {
1094          return Instruments[idx];          return Instruments[idx];
1095      }      }
1096    
1097        void File::DeleteInstrument(Instrument* pInstrument) {
1098            for (int i = 0; i < GetPresetCount(); i++) {
1099                Preset* p = GetPreset(i);
1100                if (p == NULL) continue;
1101                for (int j = p->GetRegionCount() - 1; j >= 0 ; j--) {
1102                    if (p->GetRegion(j) && p->GetRegion(j)->pInstrument == pInstrument) {
1103                        p->GetRegion(j)->pInstrument = NULL;
1104                    }
1105                }
1106            }
1107    
1108            for (int i = 0; i < GetInstrumentCount(); i++) {
1109                if (GetInstrument(i) == pInstrument) {
1110                    Instruments[i] = NULL;
1111                    delete pInstrument;
1112                }
1113            }
1114        }
1115    
1116      int File::GetSampleCount() {      int File::GetSampleCount() {
1117          return Samples.size() - 1; // exclude terminal sample (EOS)          return Samples.size() - 1; // exclude terminal sample (EOS)
1118      }      }
# Line 793  namespace sf2 { Line 1126  namespace sf2 {
1126      }      }
1127    
1128      void File::DeleteSample(Sample* pSample) {      void File::DeleteSample(Sample* pSample) {
1129            // Sanity check
1130            for (int i = GetInstrumentCount() - 1; i >= 0; i--) {
1131                Instrument* pInstr = GetInstrument(i);
1132                if (pInstr == NULL) continue;
1133    
1134                for (int j = pInstr->GetRegionCount() - 1; j >= 0 ; j--) {
1135                    if (pInstr->GetRegion(j) && pInstr->GetRegion(j)->GetSample() == pSample) {
1136                        std::cerr << "Deleting sample which is still in use" << std::endl;
1137                    }
1138                }
1139            }
1140            ///////
1141    
1142          for (int i = 0; i < GetSampleCount(); i++) {          for (int i = 0; i < GetSampleCount(); i++) {
1143              if (Samples[i] == pSample) {              if (Samples[i] == pSample) {
1144                  delete pSample;                  delete pSample;
# Line 834  namespace sf2 { Line 1180  namespace sf2 {
1180       * that the size is given in bytes! You get the number of actually cached       * that the size is given in bytes! You get the number of actually cached
1181       * samples by dividing it by the frame size of the sample:       * samples by dividing it by the frame size of the sample:
1182       * @code       * @code
1183       *  buffer_t buf       = pSample->LoadSampleData(acquired_samples);       *  buffer_t buf       = pSample->LoadSampleData(acquired_samples);
1184       *  long cachedsamples = buf.Size / pSample->FrameSize;       *  long cachedsamples = buf.Size / pSample->FrameSize;
1185       * @endcode       * @endcode
1186       *       *
1187       * @param SampleCount - number of sample points to load into RAM       * @param SampleCount - number of sample points to load into RAM
# Line 879  namespace sf2 { Line 1225  namespace sf2 {
1225       * that the size is given in bytes! You get the number of actually cached       * that the size is given in bytes! You get the number of actually cached
1226       * samples by dividing it by the frame size of the sample:       * samples by dividing it by the frame size of the sample:
1227       * @code       * @code
1228       *  buffer_t buf       = pSample->LoadSampleDataWithNullSamplesExtension(acquired_samples, null_samples);       *  buffer_t buf       = pSample->LoadSampleDataWithNullSamplesExtension(acquired_samples, null_samples);
1229       *  long cachedsamples = buf.Size / pSample->FrameSize;       *  long cachedsamples = buf.Size / pSample->FrameSize;
1230       * @endcode       * @endcode
1231       * The method will add \a NullSamplesCount silence samples past the       * The method will add \a NullSamplesCount silence samples past the
1232       * official buffer end (this won't affect the 'Size' member of the       * official buffer end (this won't affect the 'Size' member of the
# Line 982  namespace sf2 { Line 1328  namespace sf2 {
1328       * @see                SetPos()       * @see                SetPos()
1329       */       */
1330      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
1331            // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
1332          if (SampleCount == 0) return 0;          if (SampleCount == 0) return 0;
1333          long pos = GetPos();          long pos = GetPos();
1334          if (pos + SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount() - pos;          if (pos + SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount() - pos;
1335            
1336          if (GetFrameSize() / GetChannelCount() == 3 /* 24 bit */) {          if (GetFrameSize() / GetChannelCount() == 3 /* 24 bit */) {
1337              uint8_t* pBuf = (uint8_t*)pBuffer;              uint8_t* pBuf = (uint8_t*)pBuffer;
1338              if (SampleType == MONO_SAMPLE || SampleType == ROM_MONO_SAMPLE) {              if (SampleType == MONO_SAMPLE || SampleType == ROM_MONO_SAMPLE) {
1339                  for (int i = 0; i < SampleCount; i++) {                  pCkSmpl->Read(pBuf, SampleCount, 2);
1340                      pBuf[i*3] = pCkSmpl->ReadInt16();                  pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
1341                      pBuf[i*3 + 2] = pCkSm24->ReadInt8();                  for (int i = SampleCount - 1; i >= 0; i--) {
1342                        pBuf[i*3] = pBuf[(SampleCount * 2) + i];
1343                        pBuf[i*3 + 2] = pBuf[i*2 + 1];
1344                        pBuf[i*3 + 1] = pBuf[i*2];
1345                  }                  }
1346              } else if (SampleType == LEFT_SAMPLE || SampleType == ROM_LEFT_SAMPLE) {              } else if (SampleType == LEFT_SAMPLE || SampleType == ROM_LEFT_SAMPLE) {
1347                  for (int i = 0; i < SampleCount; i++) {                  pCkSmpl->Read(pBuf, SampleCount, 2);
1348                      pBuf[i*6] = pCkSmpl->ReadInt16();                  pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
1349                      pBuf[i*6 + 2] = pCkSm24->ReadInt8();                  for (int i = SampleCount - 1; i >= 0; i--) {
1350                        pBuf[i*6] = pBuf[(SampleCount * 2) + i];
1351                        pBuf[i*6 + 2] = pBuf[i*2 + 1];
1352                        pBuf[i*6 + 1] = pBuf[i*2];
1353                      pBuf[i*6 + 3] = pBuf[i*6 + 4] = pBuf[i*6 + 5] = 0;                      pBuf[i*6 + 3] = pBuf[i*6 + 4] = pBuf[i*6 + 5] = 0;
1354                  }                  }
1355              } else if (SampleType == RIGHT_SAMPLE || SampleType == ROM_RIGHT_SAMPLE) {              } else if (SampleType == RIGHT_SAMPLE || SampleType == ROM_RIGHT_SAMPLE) {
1356                  for (int i = 0; i < SampleCount; i++) {                  pCkSmpl->Read(pBuf, SampleCount, 2);
1357                    pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
1358                    for (int i = SampleCount - 1; i >= 0; i--) {
1359                        pBuf[i*6 + 3] = pBuf[(SampleCount * 2) + i];
1360                        pBuf[i*6 + 5] = pBuf[i*2 + 1];
1361                        pBuf[i*6 + 4] = pBuf[i*2];
1362                      pBuf[i*6] = pBuf[i*6 + 1] = pBuf[i*6 + 2] = 0;                      pBuf[i*6] = pBuf[i*6 + 1] = pBuf[i*6 + 2] = 0;
                     pBuf[i*6 + 3] = pCkSmpl->ReadInt16();  
                     pBuf[i*6 + 5] = pCkSm24->ReadInt8();  
1363                  }                  }
1364              }              }
1365          } else {          } else {

Legend:
Removed from v.2016  
changed lines
  Added in v.2100

  ViewVC Help
Powered by ViewVC