00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "RIFF.h"
00025
00026 #include "SF.h"
00027
00028 #include "helper.h"
00029 #include <math.h>
00030
00031 #define _1200TH_ROOT_OF_2 1.000577789506555
00032 #define _200TH_ROOT_OF_10 1.011579454259899
00033
00034 namespace sf2 {
00035 double ToSeconds(int Timecents) {
00036 if (Timecents == NONE) return NONE;
00037 if (Timecents == 0) return 1.0;
00038 if (Timecents == -32768) return 0.0;
00039 return pow(_1200TH_ROOT_OF_2, Timecents);
00040 }
00041
00042 double ToPermilles(int Centibels) {
00043 if (Centibels == NONE) return NONE;
00044 if (Centibels == 0) return 1000.0;
00045 if (Centibels < 0) return 0.0;
00046 return pow(_200TH_ROOT_OF_10, Centibels);
00047 }
00048
00049 double ToHz(int cents) {
00050 if (cents == NONE) return NONE;
00051 if (cents == 0) return 8.176;
00052 return pow(_1200TH_ROOT_OF_2, cents) * 8.176;
00053 }
00054
00055 RIFF::Chunk* GetMandatoryChunk(RIFF::List* list, uint32_t chunkId) {
00056 RIFF::Chunk* ck = list->GetSubChunk(chunkId);
00057 if(ck == NULL) throw Exception("Mandatory chunk in RIFF list chunk not found: " + ToString(chunkId));
00058 return ck;
00059 }
00060
00061 void LoadString(RIFF::Chunk* ck, std::string& s, int strLength) {
00062 if(ck == NULL) return;
00063 char* buf = new char[strLength];
00064 int len = 0;
00065 for(int i = 0; i < strLength; i++) {
00066 buf[i] = ck->ReadInt8();
00067 if(buf[i] == 0 && !len) len = i;
00068 }
00069 if(!len) len = strLength;
00070 s.assign(buf, len);
00071 delete [] buf;
00072 }
00073
00078 void VerifySize(RIFF::Chunk* ck, int size) {
00079 if (ck == NULL) throw Exception("NULL chunk");
00080 if (ck->GetSize() < size) {
00081 throw Exception("Invalid chunk size. Chunk ID: " + ToString(ck->GetChunkID()));
00082 }
00083 }
00084
00085 Modulator::Modulator(SFModulator mod) {
00086 Type = mod >> 10;
00087 Polarity = mod & (1 << 9);
00088 Direction = mod & (1 << 8);
00089 MidiPalete = mod & (1 << 7);
00090 Index = mod & 0x7f; ;
00091
00092 }
00093
00094 ModulatorItem::ModulatorItem(ModList& mod) :
00095 ModSrcOper(Modulator(mod.ModSrcOper)),
00096 ModAmtSrcOper(Modulator(mod.ModAmtSrcOper))
00097 {
00098
00099 }
00100
00101 Version::Version(RIFF::Chunk* ck) {
00102 if(ck != NULL) VerifySize(ck, 4);
00103 Major = ck ? ck->ReadUint16() : 0;
00104 Minor = ck ? ck->ReadUint16() : 0;
00105 }
00106
00107
00108
00109
00116 Info::Info(RIFF::List* list) {
00117 if (list) {
00118 RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);
00119 if (lstINFO) {
00120 pVer = new Version(GetMandatoryChunk(lstINFO, CHUNK_ID_IFIL));
00121 LoadString(CHUNK_ID_ISNG, lstINFO, SoundEngine);
00122 LoadString(CHUNK_ID_INAM, lstINFO, BankName);
00123 LoadString(CHUNK_ID_IROM, lstINFO, RomName);
00124 pRomVer = new Version(lstINFO->GetSubChunk(CHUNK_ID_IVER));
00125 LoadString(CHUNK_ID_ICRD, lstINFO, CreationDate);
00126 LoadString(CHUNK_ID_IENG, lstINFO, Engineers);
00127 LoadString(CHUNK_ID_IPRD, lstINFO, Product);
00128 LoadString(CHUNK_ID_ICOP, lstINFO, Copyright);
00129 LoadString(CHUNK_ID_ICMT, lstINFO, Comments);
00130 LoadString(CHUNK_ID_ISFT, lstINFO, Software);
00131
00132 }
00133 }
00134 }
00135
00136 Info::~Info() {
00137 delete pVer;
00138 delete pRomVer;
00139 }
00140
00146 void Info::LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s) {
00147 RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
00148 ::LoadString(ck, s);
00149 }
00150
00151 Sample::Sample(RIFF::Chunk* ck, RIFF::Chunk* pCkSmpl, RIFF::Chunk* pCkSm24) {
00152 this->pCkSmpl = pCkSmpl;
00153 this->pCkSm24 = pCkSm24;
00154
00155 LoadString(ck, Name, 20);
00156 Start = ck->ReadInt32();
00157 End = ck->ReadInt32();
00158 StartLoop = ck->ReadInt32();
00159 EndLoop = ck->ReadInt32();
00160 SampleRate = ck->ReadInt32();
00161 OriginalPitch = ck->ReadInt8();
00162 PitchCorrection = ck->ReadInt8();
00163 SampleLink = ck->ReadInt16();
00164 SampleType = ck->ReadInt16();
00165
00166 if (Start > End || !pCkSmpl || pCkSmpl->GetSize() <= End) {
00167 throw Exception("Broken SF2 file (invalid sample info)");
00168 }
00169
00170 ChannelCount = 1;
00171 switch(SampleType) {
00172 case 0 :
00173 case sf2::Sample::MONO_SAMPLE :
00174 case sf2::Sample::ROM_MONO_SAMPLE : break;
00175 case sf2::Sample::RIGHT_SAMPLE :
00176 case sf2::Sample::LEFT_SAMPLE :
00177 case sf2::Sample::ROM_RIGHT_SAMPLE :
00178 case sf2::Sample::ROM_LEFT_SAMPLE : ChannelCount = 2; break;
00179 case sf2::Sample::LINKED_SAMPLE :
00180 case sf2::Sample::ROM_LINKED_SAMPLE : std::cerr << "Linked samples not implemented yet"; break;
00181 default: throw Exception("Broken SF2 file (invalid sample type)");
00182 }
00183
00184 RAMCache.Size = 0;
00185 RAMCache.pStart = NULL;
00186 RAMCache.NullExtensionSize = 0;
00187 }
00188
00189 int Sample::GetChannelCount() {
00190 return ChannelCount;
00191 }
00192
00193 long Sample::GetTotalFrameCount() {
00194 return (End - Start);
00195 }
00196
00200 int Sample::GetFrameSize() {
00201 return ChannelCount * ((pCkSm24 != NULL) ? 3 : 2);
00202 }
00203
00204 bool Sample::HasLoops() {
00205 return StartLoop != 0 && EndLoop != 0;
00206 }
00207
00234 unsigned long Sample::ReadAndLoop (
00235 void* pBuffer,
00236 unsigned long FrameCount,
00237 PlaybackState* pPlaybackState,
00238 Region* pRegion
00239 ) {
00240
00241 unsigned long samplestoread = FrameCount, totalreadsamples = 0, readsamples, samplestoloopend;
00242 uint8_t* pDst = (uint8_t*) pBuffer;
00243 SetPos(pPlaybackState->position);
00244 if (pRegion->HasLoop) {
00245 do {
00246 samplestoloopend = pRegion->LoopEnd - GetPos();
00247 readsamples = Read(&pDst[totalreadsamples * GetFrameSize()], Min(samplestoread, samplestoloopend));
00248 samplestoread -= readsamples;
00249 totalreadsamples += readsamples;
00250 if (readsamples == samplestoloopend) {
00251 SetPos(pRegion->LoopStart);
00252 }
00253 } while (samplestoread && readsamples);
00254 } else {
00255 totalreadsamples = Read(pBuffer, FrameCount);
00256 }
00257
00258 pPlaybackState->position = GetPos();
00259
00260 return totalreadsamples;
00261 }
00262
00263 Region::Region() {
00264 pSample = NULL;
00265 pInstrument = NULL;
00266 pParentInstrument = NULL;
00267 loKey = hiKey = NONE;
00268 minVel = maxVel = NONE;
00269 startAddrsOffset = startAddrsCoarseOffset = endAddrsOffset = endAddrsCoarseOffset = 0;
00270 startloopAddrsOffset = startloopAddrsCoarseOffset = endloopAddrsOffset = endloopAddrsCoarseOffset = 0;
00271 pan = fineTune = coarseTune = 0;
00272 overridingRootKey = -1;
00273
00274 HasLoop = false;
00275 LoopStart = LoopEnd = 0;
00276
00277 EG1PreAttackDelay = EG1Attack = EG1Hold = EG1Decay = EG1Release = -12000;
00278 EG1Sustain = 0;
00279 EG2PreAttackDelay = EG2Attack = EG2Hold = EG2Decay = EG2Release = -12000;
00280 EG2Sustain = 0;
00281
00282 modEnvToPitch = modLfoToPitch = modEnvToFilterFc = modLfoToFilterFc = modLfoToVolume = 0;
00283 freqModLfo = 0;
00284 delayModLfo = -12000;
00285 vibLfoToPitch = 0;
00286 freqVibLfo = 0;
00287 delayVibLfo = -12000;
00288
00289 exclusiveClass = 0;
00290 }
00291
00292 int Region::GetUnityNote() {
00293 return overridingRootKey != -1 ? overridingRootKey : pSample->OriginalPitch;
00294 }
00295
00296 void Region::SetGenerator(sf2::File* pFile, GenList& Gen) {
00297 switch(Gen.GenOper) {
00298 case START_ADDRS_OFFSET:
00299 startAddrsOffset = Gen.GenAmount.wAmount;
00300 break;
00301 case END_ADDRS_OFFSET:
00302 if (Gen.GenAmount.shAmount <= 0) {
00303 endAddrsOffset = Gen.GenAmount.shAmount;
00304 } else {
00305 std::cerr << "Ignoring invalid endAddrsOffset" << std::endl;
00306 }
00307 break;
00308 case STARTLOOP_ADDRS_OFFSET:
00309 startloopAddrsOffset = Gen.GenAmount.shAmount;
00310 LoopStart += startloopAddrsOffset;
00311 break;
00312 case ENDLOOP_ADDRS_OFFSET:
00313 endloopAddrsOffset = Gen.GenAmount.shAmount;
00314 LoopEnd += endloopAddrsOffset;
00315 break;
00316 case START_ADDRS_COARSE_OFFSET:
00317 startAddrsCoarseOffset = Gen.GenAmount.wAmount;
00318 break;
00319 case MOD_LFO_TO_PITCH:
00320 modLfoToPitch = Gen.GenAmount.shAmount;
00321 break;
00322 case VIB_LFO_TO_PITCH:
00323 vibLfoToPitch = Gen.GenAmount.shAmount;
00324 break;
00325 case MOD_ENV_TO_PITCH:
00326 modEnvToPitch = Gen.GenAmount.shAmount;
00327 break;
00328 case INITIAL_FILTER_FC:
00329 break;
00330 case INITIAL_FILTER_Q:
00331 break;
00332 case MOD_LFO_TO_FILTER_FC:
00333 modLfoToFilterFc = Gen.GenAmount.shAmount;
00334 break;
00335 case MOD_ENV_TO_FILTER_FC:
00336 modEnvToFilterFc = Gen.GenAmount.shAmount;
00337 break;
00338 case END_ADDRS_COARSE_OFFSET:
00339 endAddrsCoarseOffset = Gen.GenAmount.wAmount;
00340 break;
00341 case MOD_LFO_TO_VOLUME:
00342 modLfoToVolume = Gen.GenAmount.shAmount;
00343 break;
00344 case CHORUS_EFFECTS_SEND:
00345 break;
00346 case REVERB_EFFECTS_SEND:
00347 break;
00348 case PAN:
00349 pan = Gen.GenAmount.shAmount;
00350 pan * 64; pan /= 500;
00351 if (pan < -64) pan = -64;
00352 if (pan > 63) pan = 63;
00353 break;
00354 case DELAY_MOD_LFO:
00355 delayModLfo = Gen.GenAmount.shAmount;
00356 break;
00357 case FREQ_MOD_LFO:
00358 freqModLfo = Gen.GenAmount.shAmount;
00359 break;
00360 case DELAY_VIB_LFO:
00361 delayVibLfo = Gen.GenAmount.shAmount;
00362 break;
00363 case FREQ_VIB_LFO:
00364 freqVibLfo = Gen.GenAmount.shAmount;
00365 break;
00366 case DELAY_MOD_ENV:
00367 EG2PreAttackDelay = Gen.GenAmount.shAmount;
00368 break;
00369 case ATTACK_MOD_ENV:
00370 EG2Attack = Gen.GenAmount.shAmount;
00371 break;
00372 case HOLD_MOD_ENV:
00373 EG2Hold = Gen.GenAmount.shAmount;
00374 break;
00375 case DECAY_MOD_ENV:
00376 EG2Decay = Gen.GenAmount.shAmount;
00377 break;
00378 case SUSTAIN_MOD_ENV:
00379 EG2Sustain = Gen.GenAmount.shAmount;
00380 break;
00381 case RELEASEMODENV:
00382 EG2Release = Gen.GenAmount.shAmount;
00383 break;
00384 case KEYNUM_TO_MOD_ENV_HOLD:
00385 break;
00386 case KEYNUM_TO_MOD_ENV_DECAY:
00387 break;
00388 case DELAY_VOL_ENV:
00389 EG1PreAttackDelay = Gen.GenAmount.shAmount;
00390 break;
00391 case ATTACK_VOL_ENV:
00392 EG1Attack = Gen.GenAmount.shAmount;
00393 break;
00394 case HOLD_VOL_ENV:
00395 EG1Hold = Gen.GenAmount.shAmount;
00396 break;
00397 case DECAY_VOL_ENV:
00398 EG1Decay = Gen.GenAmount.shAmount;
00399 break;
00400 case SUSTAIN_VOL_ENV:
00401 EG1Sustain = Gen.GenAmount.shAmount;
00402 break;
00403 case RELEASE_VOL_ENV:
00404 EG1Release = Gen.GenAmount.shAmount;
00405 break;
00406 case KEYNUM_TO_VOL_ENV_HOLD:
00407 break;
00408 case KEYNUM_TO_VOL_ENV_DECAY:
00409 break;
00410 case INSTRUMENT: {
00411 uint16_t id = Gen.GenAmount.wAmount;
00412 if (id >= pFile->Instruments.size()) {
00413 throw Exception("Broken SF2 file (missing instruments)");
00414 }
00415 pInstrument = pFile->Instruments[id];
00416 break;
00417 }
00418 case KEY_RANGE:
00419 loKey = Gen.GenAmount.ranges.byLo;
00420 hiKey = Gen.GenAmount.ranges.byHi;
00421 break;
00422 case VEL_RANGE:
00423 minVel = Gen.GenAmount.ranges.byLo;
00424 maxVel = Gen.GenAmount.ranges.byHi;
00425 break;
00426 case STARTLOOP_ADDRS_COARSE_OFFSET:
00427 startloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
00428 LoopStart += startloopAddrsCoarseOffset * 32768;
00429 break;
00430 case KEYNUM:
00431 break;
00432 case VELOCITY:
00433 break;
00434 case INITIAL_ATTENUATION:
00435 break;
00436 case ENDLOOP_ADDRS_COARSE_OFFSET:
00437 endloopAddrsCoarseOffset = Gen.GenAmount.wAmount;
00438 LoopEnd += endloopAddrsCoarseOffset * 32768;
00439 break;
00440 case COARSE_TUNE:
00441 coarseTune = Gen.GenAmount.shAmount;
00442 if (coarseTune < -120) coarseTune = -120;
00443 if (coarseTune > 120) coarseTune = 120;
00444 break;
00445 case FINE_TUNE:
00446 fineTune = Gen.GenAmount.shAmount;
00447 break;
00448 case SAMPLE_ID: {
00449 uint16_t sid = Gen.GenAmount.wAmount;
00450 if (sid >= pFile->Samples.size()) {
00451 throw Exception("Broken SF2 file (missing samples)");
00452 }
00453 pSample = pFile->Samples[sid];
00454
00455 if (HasLoop) {
00456 LoopStart += pSample->StartLoop;
00457 LoopEnd += pSample->EndLoop;
00458 if ( LoopStart < pSample->Start || LoopStart > pSample->End ||
00459 LoopStart > LoopEnd || LoopEnd > pSample->End ) {
00460 throw Exception("Broken SF2 file (invalid loops)");
00461 }
00462 LoopStart -= pSample->Start;
00463 LoopEnd -= pSample->Start;
00464 }
00465 break;
00466 }
00467 case SAMPLE_MODES:
00468 HasLoop = Gen.GenAmount.wAmount & 1;
00469
00470
00471 break;
00472 case SCALE_TUNING:
00473 break;
00474 case EXCLUSIVE_CLASS:
00475 exclusiveClass = Gen.GenAmount.wAmount;
00476 break;
00477 case OVERRIDING_ROOT_KEY:
00478 overridingRootKey = Gen.GenAmount.shAmount;
00479 break;
00480 }
00481 }
00482
00483 void Region::SetModulator(sf2::File* pFile, ModList& Mod) {
00484 modulators.push_back(ModulatorItem(Mod));
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 }
00505
00506 int Region::GetPan(Region* pPresetRegion) {
00507 if (pPresetRegion == NULL) return pan;
00508 int p = pPresetRegion->pan + pan;
00509 if (p < -64) p = -64;
00510 if (p > 63) p = 63;
00511 return p;
00512 }
00513
00514 int Region::GetFineTune(Region* pPresetRegion) {
00515 if (pPresetRegion == NULL) return fineTune;
00516 int t = pPresetRegion->fineTune + fineTune;
00517 if (t < -99) t = -99;
00518 if (t > 99) t = 99;
00519 return t;
00520 }
00521
00522 int Region::GetCoarseTune(Region* pPresetRegion) {
00523 if (pPresetRegion == NULL) return coarseTune;
00524 int t = pPresetRegion->coarseTune + coarseTune;
00525 if (t < -120) t = -120;
00526 if (t > 120) t = 120;
00527 return t;
00528 }
00529
00530 double Region::GetEG1PreAttackDelay(Region* pPresetRegion) {
00531 if (pPresetRegion == NULL || pPresetRegion->EG1PreAttackDelay == NONE) return ToSeconds(EG1PreAttackDelay);
00532 return ToSeconds(pPresetRegion->EG1PreAttackDelay + EG1PreAttackDelay);
00533 }
00534
00535 double Region::GetEG1Attack(Region* pPresetRegion) {
00536 if (pPresetRegion == NULL || pPresetRegion->EG1Attack == NONE) return ToSeconds(EG1Attack);
00537 return ToSeconds(pPresetRegion->EG1Attack + EG1Attack);
00538 }
00539
00540 double Region::GetEG1Hold(Region* pPresetRegion) {
00541 if (pPresetRegion == NULL || pPresetRegion->EG1Hold == NONE) return ToSeconds(EG1Hold);
00542 return ToSeconds(pPresetRegion->EG1Hold + EG1Hold);
00543 }
00544
00545 double Region::GetEG1Decay(Region* pPresetRegion) {
00546 if (pPresetRegion == NULL || pPresetRegion->EG1Decay == NONE) return ToSeconds(EG1Decay);
00547 return ToSeconds(pPresetRegion->EG1Decay + EG1Decay);
00548 }
00549
00550 double Region::GetEG1Sustain(Region* pPresetRegion) {
00551 if (pPresetRegion == NULL || pPresetRegion->EG1Sustain == NONE) return ToPermilles(EG1Sustain);
00552 return ToPermilles(pPresetRegion->EG1Sustain + EG1Sustain);
00553 }
00554
00555 double Region::GetEG1Release(Region* pPresetRegion) {
00556 if (pPresetRegion == NULL || pPresetRegion->EG1Release == NONE) return ToSeconds(EG1Release);
00557 return ToSeconds(pPresetRegion->EG1Release + EG1Release);
00558 }
00559
00560 double Region::GetEG2PreAttackDelay(Region* pPresetRegion) {
00561 if (pPresetRegion == NULL || pPresetRegion->EG2PreAttackDelay == NONE) return ToSeconds(EG2PreAttackDelay);
00562 return ToSeconds(pPresetRegion->EG2PreAttackDelay + EG2PreAttackDelay);
00563 }
00564
00565 double Region::GetEG2Attack(Region* pPresetRegion) {
00566 if (pPresetRegion == NULL || pPresetRegion->EG2Attack == NONE) return ToSeconds(EG2Attack);
00567 return ToSeconds(pPresetRegion->EG2Attack + EG2Attack);
00568 }
00569
00570 double Region::GetEG2Hold(Region* pPresetRegion) {
00571 if (pPresetRegion == NULL || pPresetRegion->EG2Hold == NONE) return ToSeconds(EG2Hold);
00572 return ToSeconds(pPresetRegion->EG2Hold + EG2Hold);
00573 }
00574
00575 double Region::GetEG2Decay(Region* pPresetRegion) {
00576 if (pPresetRegion == NULL || pPresetRegion->EG2Decay == NONE) return ToSeconds(EG2Decay);
00577 return ToSeconds(pPresetRegion->EG2Decay + EG2Decay);
00578 }
00579
00580 double Region::GetEG2Sustain(Region* pPresetRegion) {
00581 if (pPresetRegion == NULL || pPresetRegion->EG2Sustain == NONE) {
00582 return EG2Sustain == NONE ? NONE : 1000 - EG2Sustain;
00583 }
00584 return 1000 - (pPresetRegion->EG2Sustain + EG2Sustain);
00585 }
00586
00587 double Region::GetEG2Release(Region* pPresetRegion) {
00588 if (pPresetRegion == NULL || pPresetRegion->EG2Release == NONE) return ToSeconds(EG2Release);
00589 return ToSeconds(pPresetRegion->EG2Release + EG2Release);
00590 }
00591
00592 int Region::GetModEnvToPitch(Region* pPresetRegion) {
00593 return modEnvToPitch + (pPresetRegion ? pPresetRegion->modEnvToPitch : 0);
00594 }
00595
00596 int Region::GetModLfoToPitch(Region* pPresetRegion) {
00597 return modLfoToPitch + (pPresetRegion ? pPresetRegion->modLfoToPitch : 0);
00598 }
00599
00600 int Region::GetModEnvToFilterFc(Region* pPresetRegion) {
00601 return modEnvToFilterFc + (pPresetRegion ? pPresetRegion->modEnvToFilterFc : 0);
00602 }
00603
00604 int Region::GetModLfoToFilterFc(Region* pPresetRegion) {
00605 return modLfoToFilterFc + (pPresetRegion ? pPresetRegion->modLfoToFilterFc : 0);
00606 }
00607
00608 double Region::GetModLfoToVolume(Region* pPresetRegion) {
00609 return ToPermilles(modLfoToVolume + (pPresetRegion ? pPresetRegion->modLfoToVolume : 0));
00610 }
00611
00612 double Region::GetFreqModLfo(Region* pPresetRegion) {
00613 if (pPresetRegion == NULL || pPresetRegion->freqModLfo == NONE) return ToHz(freqModLfo);
00614 return ToHz(pPresetRegion->freqModLfo + freqModLfo);
00615 }
00616
00617 double Region::GetDelayModLfo(Region* pPresetRegion) {
00618 if (pPresetRegion == NULL || pPresetRegion->delayModLfo == NONE) return ToSeconds(delayModLfo);
00619 return ToSeconds(pPresetRegion->delayModLfo + delayModLfo);
00620 }
00621
00622 int Region::GetVibLfoToPitch(Region* pPresetRegion) {
00623 return vibLfoToPitch + (pPresetRegion ? pPresetRegion->vibLfoToPitch : 0);
00624 }
00625
00626 double Region::GetFreqVibLfo(Region* pPresetRegion) {
00627 if (pPresetRegion == NULL || pPresetRegion->freqVibLfo == NONE) return ToHz(freqVibLfo);
00628 return ToHz(pPresetRegion->freqVibLfo + freqVibLfo);
00629 }
00630
00631 double Region::GetDelayVibLfo(Region* pPresetRegion) {
00632 if (pPresetRegion == NULL || pPresetRegion->delayVibLfo == NONE) return ToSeconds(delayVibLfo);
00633 return ToSeconds(pPresetRegion->delayVibLfo + delayVibLfo);
00634 }
00635
00636 InstrumentBase::InstrumentBase(sf2::File* pFile) {
00637 this->pFile = pFile;
00638 pGlobalRegion = NULL;
00639 }
00640
00641 InstrumentBase::~InstrumentBase() {
00642 if (pGlobalRegion) delete pGlobalRegion;
00643 for (int i = regions.size() - 1; i >= 0; i--) {
00644 if (regions[i]) delete (regions[i]);
00645 }
00646 }
00647
00648 int InstrumentBase::GetRegionCount() {
00649 return regions.size();
00650 }
00651
00652 Region* InstrumentBase::GetRegion(int idx) {
00653 if (idx < 0 || idx >= GetRegionCount()) {
00654 throw Exception("Region index out of bounds");
00655 }
00656
00657 return regions[idx];
00658 }
00659
00660 Query::Query(InstrumentBase& instrument) : instrument(instrument) {
00661 i = 0;
00662 }
00663
00664 Region* Query::next() {
00665 while (i < instrument.GetRegionCount()) {
00666 Region* r = instrument.GetRegion(i++);
00667 if (((r->loKey == NONE && r->hiKey == NONE) || (key >= r->loKey && key <= r->hiKey)) &&
00668 ((r->minVel == NONE && r->maxVel == NONE) || (vel >= r->minVel && vel <= r->maxVel))) {
00669 return r;
00670 }
00671 }
00672 return 0;
00673 }
00674
00675 Instrument::Instrument(sf2::File* pFile, RIFF::Chunk* ck) : InstrumentBase(pFile) {
00676 this->pFile = pFile;
00677 LoadString(ck, Name, 20);
00678 InstBagNdx = ck->ReadInt16();
00679 }
00680
00681 Instrument::~Instrument() {
00682 }
00683
00684 Region* Instrument::CreateRegion() {
00685 Region* r = new Region;
00686 r->pParentInstrument = this;
00687
00688 if (pGlobalRegion != NULL) {
00689 r->loKey = pGlobalRegion->loKey;
00690 r->hiKey = pGlobalRegion->hiKey;
00691 r->minVel = pGlobalRegion->minVel;
00692 r->maxVel = pGlobalRegion->maxVel;
00693 r->pan = pGlobalRegion->pan;
00694 r->fineTune = pGlobalRegion->fineTune;
00695 r->coarseTune = pGlobalRegion->coarseTune;
00696 r->overridingRootKey = pGlobalRegion->overridingRootKey;
00697 r->startAddrsOffset = pGlobalRegion->startAddrsOffset;
00698 r->startAddrsCoarseOffset = pGlobalRegion->startAddrsCoarseOffset;
00699 r->endAddrsOffset = pGlobalRegion->endAddrsOffset;
00700 r->endAddrsCoarseOffset = pGlobalRegion->endAddrsCoarseOffset;
00701 r->startloopAddrsOffset = pGlobalRegion->startloopAddrsOffset;
00702 r->startloopAddrsCoarseOffset = pGlobalRegion->startloopAddrsCoarseOffset;
00703 r->endloopAddrsOffset = pGlobalRegion->endloopAddrsOffset;
00704 r->endloopAddrsCoarseOffset = pGlobalRegion->endloopAddrsCoarseOffset;
00705
00706 r->EG1PreAttackDelay = pGlobalRegion->EG1PreAttackDelay;
00707 r->EG1Attack = pGlobalRegion->EG1Attack;
00708 r->EG1Hold = pGlobalRegion->EG1Hold;
00709 r->EG1Decay = pGlobalRegion->EG1Decay;
00710 r->EG1Sustain = pGlobalRegion->EG1Sustain;
00711 r->EG1Release = pGlobalRegion->EG1Release;
00712
00713 r->EG2PreAttackDelay = pGlobalRegion->EG2PreAttackDelay;
00714 r->EG2Attack = pGlobalRegion->EG2Attack;
00715 r->EG2Hold = pGlobalRegion->EG2Hold;
00716 r->EG2Decay = pGlobalRegion->EG2Decay;
00717 r->EG2Sustain = pGlobalRegion->EG2Sustain;
00718 r->EG2Release = pGlobalRegion->EG2Release;
00719
00720 r->modEnvToPitch = pGlobalRegion->modEnvToPitch;
00721 r->modLfoToPitch = pGlobalRegion->modLfoToPitch;
00722 r->modEnvToFilterFc = pGlobalRegion->modEnvToFilterFc;
00723 r->modLfoToFilterFc = pGlobalRegion->modLfoToFilterFc;
00724 r->modLfoToVolume = pGlobalRegion->modLfoToVolume;
00725 r->freqModLfo = pGlobalRegion->freqModLfo;
00726 r->delayModLfo = pGlobalRegion->delayModLfo;
00727 r->vibLfoToPitch = pGlobalRegion->vibLfoToPitch;
00728 r->freqVibLfo = pGlobalRegion->freqVibLfo;
00729 r->delayVibLfo = pGlobalRegion->delayVibLfo;
00730
00731 r->HasLoop = pGlobalRegion->HasLoop;
00732 r->LoopStart = pGlobalRegion->LoopStart;
00733 r->LoopEnd = pGlobalRegion->LoopEnd;
00734
00735 r->exclusiveClass = pGlobalRegion->exclusiveClass;
00736 }
00737
00738 return r;
00739 }
00740
00741 void Instrument::DeleteRegion(Region* pRegion) {
00742 for (int i = 0; i < regions.size(); i++) {
00743 if (regions[i] == pRegion) {
00744 delete pRegion;
00745 regions[i] = NULL;
00746 return;
00747 }
00748 }
00749
00750 std::cerr << "Can't remove unknown Region" << std::endl;
00751 }
00752
00753 void Instrument::LoadRegions(int idx1, int idx2) {
00754 for (int i = idx1; i < idx2; i++) {
00755 int gIdx1 = pFile->InstBags[i].InstGenNdx;
00756 int gIdx2 = pFile->InstBags[i + 1].InstGenNdx;
00757
00758 if (gIdx1 < 0 || gIdx2 < 0 || gIdx1 > gIdx2 || gIdx2 >= pFile->InstGenLists.size()) {
00759 throw Exception("Broken SF2 file (invalid InstGenNdx)");
00760 }
00761
00762 int mIdx1 = pFile->InstBags[i].InstModNdx;
00763 int mIdx2 = pFile->InstBags[i + 1].InstModNdx;
00764
00765 if (mIdx1 < 0 || mIdx2 < 0 || mIdx1 > mIdx2 || mIdx2 >= pFile->InstModLists.size()) {
00766 throw Exception("Broken SF2 file (invalid InstModNdx)");
00767 }
00768
00769 Region* reg = CreateRegion();
00770
00771 for (int j = gIdx1; j < gIdx2; j++) {
00772 reg->SetGenerator(pFile, pFile->InstGenLists[j]);
00773
00774 }
00775
00776 for (int j = mIdx1; j < mIdx2; j++) {
00777 reg->SetModulator(pFile, pFile->InstModLists[j]);
00778 }
00779
00780 if (reg->pSample == NULL) {
00781 if (i == idx1 && idx2 - idx1 > 1) {
00782 pGlobalRegion = reg;
00783 } else {
00784 std::cerr << "Ignoring instrument's region without sample" << std::endl;
00785 delete reg;
00786 }
00787 } else {
00788 regions.push_back(reg);
00789 }
00790 }
00791 }
00792
00793 Preset::Preset(sf2::File* pFile, RIFF::Chunk* ck): InstrumentBase(pFile) {
00794 this->pFile = pFile;
00795 LoadString(ck, Name, 20);
00796 PresetNum = ck->ReadInt16();
00797 Bank = ck->ReadInt16();
00798 PresetBagNdx = ck->ReadInt16();
00799 Library = ck->ReadInt32();
00800 Genre = ck->ReadInt32();
00801 Morphology = ck->ReadInt32();
00802 }
00803
00804 Preset::~Preset() {
00805 }
00806
00807 Region* Preset::CreateRegion() {
00808 Region* r = new Region;
00809
00810 r->EG1PreAttackDelay = r->EG1Attack = r->EG1Hold = r->EG1Decay = r->EG1Sustain = r->EG1Release = NONE;
00811 r->EG2PreAttackDelay = r->EG2Attack = r->EG2Hold = r->EG2Decay = r->EG2Sustain = r->EG2Release = NONE;
00812 r->freqModLfo = r->delayModLfo = r->freqVibLfo = r->delayVibLfo = NONE;
00813
00814 if (pGlobalRegion != NULL) {
00815 r->pan = pGlobalRegion->pan;
00816 r->fineTune = pGlobalRegion->fineTune;
00817 r->coarseTune = pGlobalRegion->coarseTune;
00818
00819 r->EG1PreAttackDelay = pGlobalRegion->EG1PreAttackDelay;
00820 r->EG1Attack = pGlobalRegion->EG1Attack;
00821 r->EG1Hold = pGlobalRegion->EG1Hold;
00822 r->EG1Decay = pGlobalRegion->EG1Decay;
00823 r->EG1Sustain = pGlobalRegion->EG1Sustain;
00824 r->EG1Release = pGlobalRegion->EG1Release;
00825
00826 r->EG2PreAttackDelay = pGlobalRegion->EG2PreAttackDelay;
00827 r->EG2Attack = pGlobalRegion->EG2Attack;
00828 r->EG2Hold = pGlobalRegion->EG2Hold;
00829 r->EG2Decay = pGlobalRegion->EG2Decay;
00830 r->EG2Sustain = pGlobalRegion->EG2Sustain;
00831 r->EG2Release = pGlobalRegion->EG2Release;
00832
00833 r->modEnvToPitch = pGlobalRegion->modEnvToPitch;
00834 r->modLfoToPitch = pGlobalRegion->modLfoToPitch;
00835 r->modEnvToFilterFc = pGlobalRegion->modEnvToFilterFc;
00836 r->modLfoToFilterFc = pGlobalRegion->modLfoToFilterFc;
00837 r->modLfoToVolume = pGlobalRegion->modLfoToVolume;
00838 r->freqModLfo = pGlobalRegion->freqModLfo;
00839 r->delayModLfo = pGlobalRegion->delayModLfo;
00840 r->vibLfoToPitch = pGlobalRegion->vibLfoToPitch;
00841 r->freqVibLfo = pGlobalRegion->freqVibLfo;
00842 r->delayVibLfo = pGlobalRegion->delayVibLfo;
00843 }
00844
00845 return r;
00846 }
00847
00848 void Preset::LoadRegions(int idx1, int idx2) {
00849 for (int i = idx1; i < idx2; i++) {
00850 int gIdx1 = pFile->PresetBags[i].GenNdx;
00851 int gIdx2 = pFile->PresetBags[i + 1].GenNdx;
00852
00853 if (gIdx1 < 0 || gIdx2 < 0 || gIdx1 > gIdx2 || gIdx2 >= pFile->PresetGenLists.size()) {
00854 throw Exception("Broken SF2 file (invalid PresetGenNdx)");
00855 }
00856
00857 Region* reg = CreateRegion();
00858
00859 for (int j = gIdx1; j < gIdx2; j++) {
00860 reg->SetGenerator(pFile, pFile->PresetGenLists[j]);
00861 }
00862 if (reg->pInstrument == NULL) {
00863 if (i == idx1 && idx2 - idx1 > 1) {
00864 pGlobalRegion = reg;
00865 } else {
00866 std::cerr << "Ignoring preset's region without instrument" << std::endl;
00867 delete reg;
00868 }
00869 } else {
00870 regions.push_back(reg);
00871 }
00872 }
00873 }
00874
00884 File::File(RIFF::File* pRIFF) {
00885 if (!pRIFF) throw Exception("NULL pointer reference to RIFF::File object.");
00886 this->pRIFF = pRIFF;
00887
00888 if (pRIFF->GetListType() != RIFF_TYPE_SF2) {
00889 throw Exception("Not a SF2 file");
00890 }
00891
00892 pInfo = new Info(pRIFF);
00893 if (pInfo->pVer->Major != 2) {
00894 throw Exception("Unsupported version: " + ToString(pInfo->pVer->Major));
00895 }
00896
00897 RIFF::List* lstSDTA = pRIFF->GetSubList(LIST_TYPE_SDTA);
00898 if (lstSDTA == NULL) {
00899 throw Exception("Broken SF2 file (missing sdta)");
00900 }
00901
00902 RIFF::Chunk* pCkSmpl = lstSDTA->GetSubChunk(CHUNK_ID_SMPL);
00903 RIFF::Chunk* pCkSm24 = lstSDTA->GetSubChunk(CHUNK_ID_SM24);
00904 if (pCkSmpl != NULL && pCkSm24 != NULL) {
00905 long l = pCkSmpl->GetSize() / 2;
00906 if (l%2) l++;
00907 if (pCkSm24->GetSize() != l) {
00908 pCkSm24 = NULL;
00909 }
00910 }
00911
00912 RIFF::List* lstPDTA = pRIFF->GetSubList(LIST_TYPE_PDTA);
00913 if (lstPDTA == NULL) {
00914 throw Exception("Broken SF2 file (missing pdta)");
00915 }
00916
00917 RIFF::Chunk* ck = lstPDTA->GetSubChunk(CHUNK_ID_PHDR);
00918 if (ck->GetSize() < 38) {
00919 throw Exception("Broken SF2 file (broken phdr)");
00920 }
00921
00922 int count = ck->GetSize() / 38;
00923 for (int i = 0; i < count; i++) {
00924 Presets.push_back(new Preset(this, ck));
00925 }
00926
00927 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_PBAG);
00928 if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
00929 throw Exception("Broken SF2 file (broken pbag)");
00930 }
00931
00932 count = ck->GetSize() / 4;
00933 for (int i = 0; i < count; i++) {
00934 PresetBag pb;
00935 pb.GenNdx = ck->ReadInt16();
00936 pb.ModNdx = ck->ReadInt16();
00937 PresetBags.push_back(pb);
00938 }
00939
00940
00941 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_PMOD);
00942 if (ck->GetSize() % 10) {
00943 throw Exception("Broken SF2 file (broken pmod)");
00944 }
00945
00946 count = ck->GetSize() / 10;
00947 for (int i = 0; i < count; i++) {
00948 ModList ml;
00949 ml.ModSrcOper = ck->ReadInt16();
00950 ml.ModDestOper = ck->ReadInt16();
00951 ml.ModAmount = ck->ReadInt16();
00952 ml.ModAmtSrcOper = ck->ReadInt16();
00953 ml.ModTransOper = ck->ReadInt16();
00954 PresetModLists.push_back(ml);
00955 }
00956
00957
00958 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_PGEN);
00959 if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
00960 throw Exception("Broken SF2 file (broken pgen)");
00961 }
00962
00963 count = ck->GetSize() / 4;
00964 for (int i = 0; i < count; i++) {
00965 GenList gl;
00966 gl.GenOper = ck->ReadInt16();
00967 gl.GenAmount.wAmount = ck->ReadInt16();
00968 PresetGenLists.push_back(gl);
00969 }
00970
00971
00972 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_INST);
00973 if (ck->GetSize() < (22 * 2) || (ck->GetSize() % 22)) {
00974 throw Exception("Broken SF2 file (broken inst)");
00975 }
00976 count = ck->GetSize() / 22;
00977 for (int i = 0; i < count; i++) {
00978 Instruments.push_back(new Instrument(this, ck));
00979 }
00980
00981 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_IBAG);
00982 if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
00983 throw Exception("Broken SF2 file (broken ibag)");
00984 }
00985
00986 count = ck->GetSize() / 4;
00987 for (int i = 0; i < count; i++) {
00988 InstBag ib;
00989 ib.InstGenNdx = ck->ReadInt16();
00990 ib.InstModNdx = ck->ReadInt16();
00991 InstBags.push_back(ib);
00992 }
00993
00994
00995 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_IMOD);
00996 if (ck->GetSize() % 10) {
00997 throw Exception("Broken SF2 file (broken imod)");
00998 }
00999
01000 count = ck->GetSize() / 10;
01001 for (int i = 0; i < count; i++) {
01002 ModList ml;
01003 ml.ModSrcOper = ck->ReadInt16();
01004 ml.ModDestOper = ck->ReadInt16();
01005 ml.ModAmount = ck->ReadInt16();
01006 ml.ModAmtSrcOper = ck->ReadInt16();
01007 ml.ModTransOper = ck->ReadInt16();
01008 InstModLists.push_back(ml);
01009 }
01010
01011
01012 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_IGEN);
01013 if (ck->GetSize() < 4 || (ck->GetSize() % 4)) {
01014 throw Exception("Broken SF2 file (broken igen)");
01015 }
01016
01017 count = ck->GetSize() / 4;
01018 for (int i = 0; i < count; i++) {
01019 GenList gl;
01020 gl.GenOper = ck->ReadInt16();
01021 gl.GenAmount.wAmount = ck->ReadInt16();
01022 InstGenLists.push_back(gl);
01023 }
01024
01025
01026 ck = GetMandatoryChunk(lstPDTA, CHUNK_ID_SHDR);
01027 if ((ck->GetSize() % 46)) {
01028 throw Exception("Broken SF2 file (broken shdr)");
01029 }
01030 count = ck->GetSize() / 46;
01031 for (int i = 0; i < count; i++) {
01032 Samples.push_back(new Sample(ck, pCkSmpl, pCkSm24));
01033 }
01034
01035
01036 for (int i = 0; i < Instruments.size() - 1; i++) {
01037 Instrument* instr = Instruments[i];
01038 int x1 = instr->InstBagNdx;
01039 int x2 = Instruments[i + 1]->InstBagNdx;
01040 if (x1 < 0 || x2 < 0 || x1 > x2 || x2 >= InstBags.size()) {
01041 throw Exception("Broken SF2 file (invalid InstBagNdx)");
01042 }
01043
01044 instr->LoadRegions(x1, x2);
01045 }
01046
01047
01048 for (int i = 0; i < Presets.size() - 1; i++) {
01049 Preset* preset = Presets[i];
01050 int x1 = preset->PresetBagNdx;
01051 int x2 = Presets[i + 1]->PresetBagNdx;
01052 if (x1 < 0 || x2 < 0 || x1 > x2 || x2 >= PresetBags.size()) {
01053 throw Exception("Broken SF2 file (invalid PresetBagNdx)");
01054 }
01055
01056 preset->LoadRegions(x1, x2);
01057 }
01058 }
01059
01060 File::~File() {
01061 delete pInfo;
01062 for (int i = Presets.size() - 1; i >= 0; i--) {
01063 if (Presets[i]) delete (Presets[i]);
01064 }
01065 for (int i = Instruments.size() - 1; i >= 0; i--) {
01066 if (Instruments[i]) delete (Instruments[i]);
01067 }
01068 for (int i = Samples.size() - 1; i >= 0; i--) {
01069 if (Samples[i]) delete (Samples[i]);
01070 }
01071 }
01072
01073 int File::GetPresetCount() {
01074 return Presets.size() - 1;
01075 }
01076
01077 Preset* File::GetPreset(int idx) {
01078 if (idx < 0 || idx >= GetPresetCount()) {
01079 throw Exception("Preset index out of bounds");
01080 }
01081
01082 return Presets[idx];
01083 }
01084
01085 int File::GetInstrumentCount() {
01086 return Instruments.size() - 1;
01087 }
01088
01089 Instrument* File::GetInstrument(int idx) {
01090 if (idx < 0 || idx >= GetInstrumentCount()) {
01091 throw Exception("Instrument index out of bounds");
01092 }
01093
01094 return Instruments[idx];
01095 }
01096
01097 void File::DeleteInstrument(Instrument* pInstrument) {
01098 for (int i = 0; i < GetPresetCount(); i++) {
01099 Preset* p = GetPreset(i);
01100 if (p == NULL) continue;
01101 for (int j = p->GetRegionCount() - 1; j >= 0 ; j--) {
01102 if (p->GetRegion(j) && p->GetRegion(j)->pInstrument == pInstrument) {
01103 p->GetRegion(j)->pInstrument = NULL;
01104 }
01105 }
01106 }
01107
01108 for (int i = 0; i < GetInstrumentCount(); i++) {
01109 if (GetInstrument(i) == pInstrument) {
01110 Instruments[i] = NULL;
01111 delete pInstrument;
01112 }
01113 }
01114 }
01115
01116 int File::GetSampleCount() {
01117 return Samples.size() - 1;
01118 }
01119
01120 Sample* File::GetSample(int idx) {
01121 if (idx < 0 || idx >= GetSampleCount()) {
01122 throw Exception("Sample index out of bounds");
01123 }
01124
01125 return Samples[idx];
01126 }
01127
01128 void File::DeleteSample(Sample* pSample) {
01129
01130 for (int i = GetInstrumentCount() - 1; i >= 0; i--) {
01131 Instrument* pInstr = GetInstrument(i);
01132 if (pInstr == NULL) continue;
01133
01134 for (int j = pInstr->GetRegionCount() - 1; j >= 0 ; j--) {
01135 if (pInstr->GetRegion(j) && pInstr->GetRegion(j)->GetSample() == pSample) {
01136 std::cerr << "Deleting sample which is still in use" << std::endl;
01137 }
01138 }
01139 }
01141
01142 for (int i = 0; i < GetSampleCount(); i++) {
01143 if (Samples[i] == pSample) {
01144 delete pSample;
01145 Samples[i] = NULL;
01146 return;
01147 }
01148 }
01149
01150 throw Exception("Unknown sample: " + pSample->Name);
01151 }
01152
01153 bool File::HasSamples() {
01154 for (int i = 0; i < GetSampleCount(); i++) {
01155 if (Samples[i] != NULL) return true;
01156 }
01157
01158 return false;
01159 }
01160
01170 Sample::buffer_t Sample::LoadSampleData() {
01171 return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), 0);
01172 }
01173
01192 Sample::buffer_t Sample::LoadSampleData(unsigned long SampleCount) {
01193 return LoadSampleDataWithNullSamplesExtension(SampleCount, 0);
01194 }
01195
01215 Sample::buffer_t Sample::LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount) {
01216 return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), NullSamplesCount);
01217 }
01218
01247 Sample::buffer_t Sample::LoadSampleDataWithNullSamplesExtension(unsigned long SampleCount, uint NullSamplesCount) {
01248 if (SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount();
01249 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
01250 unsigned long allocationsize = (SampleCount + NullSamplesCount) * GetFrameSize();
01251 SetPos(0);
01252 RAMCache.pStart = new int8_t[allocationsize];
01253 RAMCache.Size = Read(RAMCache.pStart, SampleCount) * GetFrameSize();
01254 RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
01255
01256 memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
01257 return GetCache();
01258 }
01259
01270 Sample::buffer_t Sample::GetCache() {
01271
01272 buffer_t result;
01273 result.Size = this->RAMCache.Size;
01274 result.pStart = this->RAMCache.pStart;
01275 result.NullExtensionSize = this->RAMCache.NullExtensionSize;
01276 return result;
01277 }
01278
01285 void Sample::ReleaseSampleData() {
01286 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
01287 RAMCache.pStart = NULL;
01288 RAMCache.Size = 0;
01289 RAMCache.NullExtensionSize = 0;
01290 }
01291
01301 unsigned long Sample::SetPos(unsigned long SampleCount) {
01302 pCkSmpl->SetPos((Start * 2) + (SampleCount * 2), RIFF::stream_start);
01303 if(pCkSm24) pCkSm24->SetPos(Start + SampleCount, RIFF::stream_start);
01304 return SampleCount;
01305 }
01306
01310 unsigned long Sample::GetPos() {
01311 return (pCkSmpl->GetPos() - (Start * 2)) / 2;
01312 }
01313
01330 unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
01331
01332 if (SampleCount == 0) return 0;
01333 long pos = GetPos();
01334 if (pos + SampleCount > GetTotalFrameCount()) SampleCount = GetTotalFrameCount() - pos;
01335
01336 if (GetFrameSize() / GetChannelCount() == 3 ) {
01337 uint8_t* pBuf = (uint8_t*)pBuffer;
01338 if (SampleType == MONO_SAMPLE || SampleType == ROM_MONO_SAMPLE) {
01339 pCkSmpl->Read(pBuf, SampleCount, 2);
01340 pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
01341 for (int i = SampleCount - 1; i >= 0; i--) {
01342 pBuf[i*3] = pBuf[(SampleCount * 2) + i];
01343 pBuf[i*3 + 2] = pBuf[i*2 + 1];
01344 pBuf[i*3 + 1] = pBuf[i*2];
01345 }
01346 } else if (SampleType == LEFT_SAMPLE || SampleType == ROM_LEFT_SAMPLE) {
01347 pCkSmpl->Read(pBuf, SampleCount, 2);
01348 pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
01349 for (int i = SampleCount - 1; i >= 0; i--) {
01350 pBuf[i*6] = pBuf[(SampleCount * 2) + i];
01351 pBuf[i*6 + 2] = pBuf[i*2 + 1];
01352 pBuf[i*6 + 1] = pBuf[i*2];
01353 pBuf[i*6 + 3] = pBuf[i*6 + 4] = pBuf[i*6 + 5] = 0;
01354 }
01355 } else if (SampleType == RIGHT_SAMPLE || SampleType == ROM_RIGHT_SAMPLE) {
01356 pCkSmpl->Read(pBuf, SampleCount, 2);
01357 pCkSm24->Read(pBuf + SampleCount * 2, SampleCount, 1);
01358 for (int i = SampleCount - 1; i >= 0; i--) {
01359 pBuf[i*6 + 3] = pBuf[(SampleCount * 2) + i];
01360 pBuf[i*6 + 5] = pBuf[i*2 + 1];
01361 pBuf[i*6 + 4] = pBuf[i*2];
01362 pBuf[i*6] = pBuf[i*6 + 1] = pBuf[i*6 + 2] = 0;
01363 }
01364 }
01365 } else {
01366 if (SampleType == MONO_SAMPLE || SampleType == ROM_MONO_SAMPLE) {
01367 return pCkSmpl->Read(pBuffer, SampleCount, 2);
01368 }
01369
01370 int16_t* pBuf = (int16_t*)pBuffer;
01371 if (SampleType == LEFT_SAMPLE || SampleType == ROM_LEFT_SAMPLE) {
01372 pCkSmpl->Read(pBuf, SampleCount, 2);
01373 for (int i = SampleCount - 1; i >= 0; i--) {
01374 pBuf[i*2] = pBuf[i];
01375 pBuf[i*2 + 1] = 0;
01376 }
01377 } else if (SampleType == RIGHT_SAMPLE || SampleType == ROM_RIGHT_SAMPLE) {
01378 pCkSmpl->Read(pBuf, SampleCount, 2);
01379 for (int i = SampleCount - 1; i >= 0; i--) {
01380 pBuf[i*2] = 0;
01381 pBuf[i*2 + 1] = pBuf[i];
01382 }
01383 }
01384 }
01385
01386 if (pCkSmpl->GetPos() > (End * 2)) {
01387 std::cerr << "Read after the sample end. This is a BUG!" << std::endl;
01388 std::cerr << "Current position: " << GetPos() << std::endl;
01389 std::cerr << "Total number of frames: " << GetTotalFrameCount() << std::endl << std::endl;
01390 }
01391 return SampleCount;
01392 }
01393
01394
01395
01396
01397
01401 String libraryName() {
01402 return PACKAGE;
01403 }
01404
01408 String libraryVersion() {
01409 return VERSION;
01410 }
01411
01412 }