/[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 2019 by iliev, Tue Oct 27 18:34:06 2009 UTC revision 2020 by iliev, Fri Oct 30 16:25:27 2009 UTC
# Line 229  namespace sf2 { Line 229  namespace sf2 {
229      unsigned long Sample::ReadAndLoop (      unsigned long Sample::ReadAndLoop (
230          void*           pBuffer,          void*           pBuffer,
231          unsigned long   FrameCount,          unsigned long   FrameCount,
232          PlaybackState*  pPlaybackState          PlaybackState*  pPlaybackState,
233            Region*         pRegion
234      ) {      ) {
235            // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
236            unsigned long samplestoread = FrameCount, totalreadsamples = 0, readsamples, samplestoloopend;
237            uint8_t* pDst = (uint8_t*) pBuffer;
238          SetPos(pPlaybackState->position);          SetPos(pPlaybackState->position);
239          long frames = Read(pBuffer, FrameCount);          if (pRegion->HasLoop) {
240                do {
241                    samplestoloopend  = pRegion->LoopEnd - GetPos();
242                    readsamples       = Read(&pDst[totalreadsamples * GetFrameSize()], Min(samplestoread, samplestoloopend));
243                    samplestoread    -= readsamples;
244                    totalreadsamples += readsamples;
245                    if (readsamples == samplestoloopend) {
246                        SetPos(pRegion->LoopStart);
247                    }
248                } while (samplestoread && readsamples);
249            } else {
250                totalreadsamples = Read(pBuffer, FrameCount);
251            }
252    
253          pPlaybackState->position = GetPos();          pPlaybackState->position = GetPos();
254          // TODO: Implement looping  
255          return frames;          return totalreadsamples;
256      }      }
257    
258      Region::Region() {      Region::Region() {
# Line 243  namespace sf2 { Line 260  namespace sf2 {
260          pInstrument = NULL;          pInstrument = NULL;
261          loKey = hiKey = NONE;          loKey = hiKey = NONE;
262          minVel = maxVel = NONE;          minVel = maxVel = NONE;
263          startAddrsOffset = startAddrsCoarseOffset = endAddrsOffset = 0;          startAddrsOffset = startAddrsCoarseOffset = endAddrsOffset = endAddrsCoarseOffset = 0;
264          startloopAddrsOffset = endloopAddrsOffset = 0;          startloopAddrsOffset = startloopAddrsCoarseOffset = endloopAddrsOffset = endloopAddrsCoarseOffset = 0;
265          pan = fineTune = 0;          pan = fineTune = coarseTune = 0;
266            overridingRootKey = -1; // -1 means not used
267    
268            HasLoop = false;
269            LoopStart = LoopEnd = 0;
270    
271          EG1PreAttackDelay = EG1Attack = EG1Hold = EG1Decay = EG1Release = ToSeconds(-12000);          EG1PreAttackDelay = EG1Attack = EG1Hold = EG1Decay = EG1Release = ToSeconds(-12000);
272          EG1Sustain = 0;          EG1Sustain = 0;
# Line 253  namespace sf2 { Line 274  namespace sf2 {
274          EG2Sustain = 0;          EG2Sustain = 0;
275      }      }
276    
277        int Region::GetUnityNote() {
278            return overridingRootKey != -1 ? overridingRootKey : pSample->OriginalPitch;
279        }
280    
281      void Region::SetGenerator(sf2::File* pFile, GenList& Gen) {      void Region::SetGenerator(sf2::File* pFile, GenList& Gen) {
282          switch(Gen.GenOper) {          switch(Gen.GenOper) {
283              case START_ADDRS_OFFSET:              case START_ADDRS_OFFSET:
# Line 267  namespace sf2 { Line 292  namespace sf2 {
292                  break;                  break;
293              case STARTLOOP_ADDRS_OFFSET:              case STARTLOOP_ADDRS_OFFSET:
294                  startloopAddrsOffset = Gen.GenAmount.shAmount;                  startloopAddrsOffset = Gen.GenAmount.shAmount;
295                    LoopStart += startloopAddrsOffset;
296                  break;                  break;
297              case ENDLOOP_ADDRS_OFFSET:              case ENDLOOP_ADDRS_OFFSET:
298                  endloopAddrsOffset = Gen.GenAmount.shAmount;                  endloopAddrsOffset = Gen.GenAmount.shAmount;
299                    LoopEnd += endloopAddrsOffset;
300                  break;                  break;
301              case START_ADDRS_COARSE_OFFSET:              case START_ADDRS_COARSE_OFFSET:
302                  startAddrsCoarseOffset = Gen.GenAmount.wAmount;                  startAddrsCoarseOffset = Gen.GenAmount.wAmount;
# Line 289  namespace sf2 { Line 316  namespace sf2 {
316              case MOD_ENV_TO_FILTER_FC:              case MOD_ENV_TO_FILTER_FC:
317                  break;                  break;
318              case END_ADDRS_COARSE_OFFSET:              case END_ADDRS_COARSE_OFFSET:
319                    endAddrsCoarseOffset = Gen.GenAmount.wAmount;
320                  break;                  break;
321              case MOD_LFO_TO_VOLUME:              case MOD_LFO_TO_VOLUME:
322                  break;                  break;
# Line 371  namespace sf2 { Line 399  namespace sf2 {
399                  maxVel = Gen.GenAmount.ranges.byHi;                  maxVel = Gen.GenAmount.ranges.byHi;
400                  break;                  break;
401              case STARTLOOP_ADDRS_COARSE_OFFSET:              case STARTLOOP_ADDRS_COARSE_OFFSET:
402                    startloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
403                    LoopStart += startloopAddrsCoarseOffset * 32768;
404                  break;                  break;
405              case KEYNUM:              case KEYNUM:
406                  break;                  break;
# Line 379  namespace sf2 { Line 409  namespace sf2 {
409              case INITIAL_ATTENUATION:              case INITIAL_ATTENUATION:
410                  break;                  break;
411              case ENDLOOP_ADDRS_COARSE_OFFSET:              case ENDLOOP_ADDRS_COARSE_OFFSET:
412                    endloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
413                    LoopEnd += endloopAddrsCoarseOffset * 32768;
414                  break;                  break;
415              case COARSE_TUNE:              case COARSE_TUNE:
416                    coarseTune = Gen.GenAmount.shAmount;
417                  break;                  break;
418              case FINE_TUNE:              case FINE_TUNE:
419                  fineTune = Gen.GenAmount.shAmount;                  fineTune = Gen.GenAmount.shAmount;
# Line 391  namespace sf2 { Line 424  namespace sf2 {
424                      throw Exception("Broken SF2 file (missing samples)");                      throw Exception("Broken SF2 file (missing samples)");
425                  }                  }
426                  pSample = pFile->Samples[sid];                  pSample = pFile->Samples[sid];
427    
428                    if (HasLoop) {
429                        LoopStart += pSample->StartLoop;
430                        LoopEnd   += pSample->EndLoop;
431                        if ( LoopStart < pSample->Start || LoopStart > pSample->End ||
432                             LoopStart > LoopEnd        || LoopEnd   > pSample->End    ) {
433                            throw Exception("Broken SF2 file (invalid loops)");
434                        }
435                        LoopStart -= pSample->Start; // Relative to the sample start
436                        LoopEnd   -= pSample->Start; // Relative to the sample start
437                    }
438                  break;                  break;
439              }              }
440              case SAMPLE_MODES:              case SAMPLE_MODES:
441                    HasLoop = Gen.GenAmount.wAmount & 1;
442                    // TODO: 3 indicates a sound which loops for the duration of key depression
443                    //       then proceeds to play the remainder of the sample.
444                  break;                  break;
445              case SCALE_TUNING:              case SCALE_TUNING:
446                  break;                  break;
447              case EXCLUSIVE_CLASS:              case EXCLUSIVE_CLASS:
448                  break;                  break;
449              case OVERRIDING_ROOT_KEY:              case OVERRIDING_ROOT_KEY:
450                    overridingRootKey = Gen.GenAmount.shAmount;
451                  break;                  break;
452          }          }
453      }      }
# Line 440  namespace sf2 { Line 488  namespace sf2 {
488      }      }
489    
490      int InstrumentBase::GetRegionCount() {      int InstrumentBase::GetRegionCount() {
491          return regions.size() - 1; // exclude terminal region          return regions.size();
492      }      }
493    
494      Region* InstrumentBase::GetRegion(int idx) {      Region* InstrumentBase::GetRegion(int idx) {
# Line 476  namespace sf2 { Line 524  namespace sf2 {
524                    
525      }      }
526    
527        Region* Instrument::CreateRegion() {
528            Region* r = new Region;
529            if (pGlobalRegion != NULL) {
530                r->loKey       = pGlobalRegion->loKey;
531                r->hiKey       = pGlobalRegion->hiKey;
532                r->minVel      = pGlobalRegion->minVel;
533                r->maxVel      = pGlobalRegion->maxVel;
534                r->pan         = pGlobalRegion->pan;
535                r->fineTune    = pGlobalRegion->fineTune;
536                r->coarseTune  = pGlobalRegion->coarseTune;
537                r->overridingRootKey = pGlobalRegion->overridingRootKey;
538                r->startAddrsOffset            = pGlobalRegion->startAddrsOffset;
539                r->startAddrsCoarseOffset      = pGlobalRegion->startAddrsCoarseOffset;
540                r->endAddrsOffset              = pGlobalRegion->endAddrsOffset;
541                r->endAddrsCoarseOffset        = pGlobalRegion->endAddrsCoarseOffset;
542                r->startloopAddrsOffset        = pGlobalRegion->startloopAddrsOffset;
543                r->startloopAddrsCoarseOffset  = pGlobalRegion->startloopAddrsCoarseOffset;
544                r->endloopAddrsOffset          = pGlobalRegion->endloopAddrsOffset;
545                r->endloopAddrsCoarseOffset    = pGlobalRegion->endloopAddrsCoarseOffset;
546    
547                r->EG1PreAttackDelay  = pGlobalRegion->EG1PreAttackDelay;
548                r->EG1Attack          = pGlobalRegion->EG1Attack;
549                r->EG1Hold            = pGlobalRegion->EG1Hold;
550                r->EG1Decay           = pGlobalRegion->EG1Decay;
551                r->EG1Sustain         = pGlobalRegion->EG1Sustain;
552                r->EG1Release         = pGlobalRegion->EG1Release;
553    
554                r->EG2PreAttackDelay  = pGlobalRegion->EG2PreAttackDelay;
555                r->EG2Attack          = pGlobalRegion->EG2Attack;
556                r->EG2Hold            = pGlobalRegion->EG2Hold;
557                r->EG2Decay           = pGlobalRegion->EG2Decay;
558                r->EG2Sustain         = pGlobalRegion->EG2Sustain;
559                r->EG2Release         = pGlobalRegion->EG2Release;
560    
561                r->HasLoop    = pGlobalRegion->HasLoop;
562                r->LoopStart  = pGlobalRegion->LoopStart;
563                r->LoopEnd    = pGlobalRegion->LoopEnd;
564            }
565    
566            return r;
567        }
568    
569        void Instrument::DeleteRegion(Region* pRegion) {
570            for (int i = 0; i < regions.size(); i++) {
571                if (regions[i] == pRegion) {
572                    delete pRegion;
573                    regions[i] = NULL;
574                    return;
575                }
576            }
577    
578            std::cerr << "Can't remove unknown Region" << std::endl;
579        }
580    
581      void Instrument::LoadRegions(int idx1, int idx2) {      void Instrument::LoadRegions(int idx1, int idx2) {
582          for (int i = idx1; i < idx2 - 1; i++) {          for (int i = idx1; i < idx2; i++) {
583              int gIdx1 = pFile->InstBags[i].InstGenNdx;              int gIdx1 = pFile->InstBags[i].InstGenNdx;
584              int gIdx2 = pFile->InstBags[i + 1].InstGenNdx;              int gIdx2 = pFile->InstBags[i + 1].InstGenNdx;
585    
# Line 492  namespace sf2 { Line 594  namespace sf2 {
594                  throw Exception("Broken SF2 file (invalid InstModNdx)");                  throw Exception("Broken SF2 file (invalid InstModNdx)");
595              }              }
596    
597              Region* reg = new Region;              Region* reg = CreateRegion();
598                            
599              for (int j = gIdx1; j < gIdx2; j++) {              for (int j = gIdx1; j < gIdx2; j++) {
600                  reg->SetGenerator(pFile, pFile->InstGenLists[j]);                  reg->SetGenerator(pFile, pFile->InstGenLists[j]);
# Line 504  namespace sf2 { Line 606  namespace sf2 {
606              }              }
607    
608              if (reg->pSample == NULL) {              if (reg->pSample == NULL) {
609                  if (i == idx1) {                  if (i == idx1 && idx2 - idx1 > 1) {
610                      pGlobalRegion = reg;  // global zone                      pGlobalRegion = reg;  // global zone
611                  } else {                  } else {
612                      std::cerr << "Ignoring instrument's region without sample" << std::endl;                      std::cerr << "Ignoring instrument's region without sample" << std::endl;
# Line 532  namespace sf2 { Line 634  namespace sf2 {
634      }      }
635    
636      void Preset::LoadRegions(int idx1, int idx2) {      void Preset::LoadRegions(int idx1, int idx2) {
637          for (int i = idx1; i < idx2 - 1; i++) {          for (int i = idx1; i < idx2; i++) {
638              int gIdx1 = pFile->PresetBags[i].GenNdx;              int gIdx1 = pFile->PresetBags[i].GenNdx;
639              int gIdx2 = pFile->PresetBags[i + 1].GenNdx;              int gIdx2 = pFile->PresetBags[i + 1].GenNdx;
640    
# Line 546  namespace sf2 { Line 648  namespace sf2 {
648                  reg->SetGenerator(pFile, pFile->PresetGenLists[j]);                  reg->SetGenerator(pFile, pFile->PresetGenLists[j]);
649              }              }
650              if (reg->pInstrument == NULL) {              if (reg->pInstrument == NULL) {
651                  if (i == idx1) {                  if (i == idx1 && idx2 - idx1 > 1) {
652                      pGlobalRegion = reg;  // global zone                      pGlobalRegion = reg;  // global zone
653                  } else {                  } else {
654                      std::cerr << "Ignoring preset's region without instrument" << std::endl;                      std::cerr << "Ignoring preset's region without instrument" << std::endl;
# Line 780  namespace sf2 { Line 882  namespace sf2 {
882          return Instruments[idx];          return Instruments[idx];
883      }      }
884    
885        void File::DeleteInstrument(Instrument* pInstrument) {
886            for (int i = 0; i < GetPresetCount(); i++) {
887                Preset* p = GetPreset(i);
888                if (p == NULL) continue;
889                for (int j = p->GetRegionCount() - 1; j >= 0 ; j--) {
890                    if (p->GetRegion(j) && p->GetRegion(j)->pInstrument == pInstrument) {
891                        p->GetRegion(j)->pInstrument = NULL;
892                    }
893                }
894            }
895    
896            for (int i = 0; i < GetInstrumentCount(); i++) {
897                if (GetInstrument(i) == pInstrument) {
898                    Instruments[i] = NULL;
899                    delete pInstrument;
900                }
901            }
902        }
903    
904      int File::GetSampleCount() {      int File::GetSampleCount() {
905          return Samples.size() - 1; // exclude terminal sample (EOS)          return Samples.size() - 1; // exclude terminal sample (EOS)
906      }      }
# Line 793  namespace sf2 { Line 914  namespace sf2 {
914      }      }
915    
916      void File::DeleteSample(Sample* pSample) {      void File::DeleteSample(Sample* pSample) {
917            // Sanity check
918            for (int i = GetInstrumentCount() - 1; i >= 0; i--) {
919                Instrument* pInstr = GetInstrument(i);
920                if (pInstr == NULL) continue;
921    
922                for (int j = pInstr->GetRegionCount() - 1; j >= 0 ; j--) {
923                    if (pInstr->GetRegion(j) && pInstr->GetRegion(j)->GetSample() == pSample) {
924                        std::cerr << "Deleting sample which is still in use" << std::endl;
925                    }
926                }
927            }
928            ///////
929    
930          for (int i = 0; i < GetSampleCount(); i++) {          for (int i = 0; i < GetSampleCount(); i++) {
931              if (Samples[i] == pSample) {              if (Samples[i] == pSample) {
932                  delete pSample;                  delete pSample;
# Line 982  namespace sf2 { Line 1116  namespace sf2 {
1116       * @see                SetPos()       * @see                SetPos()
1117       */       */
1118      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
1119            // TODO: startAddrsCoarseOffset, endAddrsCoarseOffset
1120          if (SampleCount == 0) return 0;          if (SampleCount == 0) return 0;
1121          long pos = GetPos();          long pos = GetPos();
1122          if (pos + SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount() - pos;          if (pos + SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount() - pos;
# Line 989  namespace sf2 { Line 1124  namespace sf2 {
1124          if (GetFrameSize() / GetChannelCount() == 3 /* 24 bit */) {          if (GetFrameSize() / GetChannelCount() == 3 /* 24 bit */) {
1125              uint8_t* pBuf = (uint8_t*)pBuffer;              uint8_t* pBuf = (uint8_t*)pBuffer;
1126              if (SampleType == MONO_SAMPLE || SampleType == ROM_MONO_SAMPLE) {              if (SampleType == MONO_SAMPLE || SampleType == ROM_MONO_SAMPLE) {
1127                  for (int i = 0; i < SampleCount; i++) {                  pCkSmpl->Read(pBuf, SampleCount, 2);
1128                      pBuf[i*3] = pCkSmpl->ReadInt16();                  pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
1129                      pBuf[i*3 + 2] = pCkSm24->ReadInt8();                  for (int i = SampleCount - 1; i >= 0; i--) {
1130                        pBuf[i*3] = pBuf[(SampleCount * 2) + i];
1131                        pBuf[i*3 + 2] = pBuf[i*2 + 1];
1132                        pBuf[i*3 + 1] = pBuf[i*2];
1133                  }                  }
1134              } else if (SampleType == LEFT_SAMPLE || SampleType == ROM_LEFT_SAMPLE) {              } else if (SampleType == LEFT_SAMPLE || SampleType == ROM_LEFT_SAMPLE) {
1135                  for (int i = 0; i < SampleCount; i++) {                  pCkSmpl->Read(pBuf, SampleCount, 2);
1136                      pBuf[i*6] = pCkSmpl->ReadInt16();                  pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
1137                      pBuf[i*6 + 2] = pCkSm24->ReadInt8();                  for (int i = SampleCount - 1; i >= 0; i--) {
1138                        pBuf[i*6] = pBuf[(SampleCount * 2) + i];
1139                        pBuf[i*6 + 2] = pBuf[i*2 + 1];
1140                        pBuf[i*6 + 1] = pBuf[i*2];
1141                      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;
1142                  }                  }
1143              } else if (SampleType == RIGHT_SAMPLE || SampleType == ROM_RIGHT_SAMPLE) {              } else if (SampleType == RIGHT_SAMPLE || SampleType == ROM_RIGHT_SAMPLE) {
1144                  for (int i = 0; i < SampleCount; i++) {                  pCkSmpl->Read(pBuf, SampleCount, 2);
1145                    pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
1146                    for (int i = SampleCount - 1; i >= 0; i--) {
1147                        pBuf[i*6 + 3] = pBuf[(SampleCount * 2) + i];
1148                        pBuf[i*6 + 5] = pBuf[i*2 + 1];
1149                        pBuf[i*6 + 4] = pBuf[i*2];
1150                      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();  
1151                  }                  }
1152              }              }
1153          } else {          } else {

Legend:
Removed from v.2019  
changed lines
  Added in v.2020

  ViewVC Help
Powered by ViewVC