--- libgig/trunk/src/gig.cpp 2017/07/21 13:05:39 3324 +++ libgig/trunk/src/gig.cpp 2017/10/03 17:35:02 3350 @@ -1736,12 +1736,15 @@ // Gigasampler/GigaStudio ! RIFF::Chunk* lsde = _3ewl->GetSubChunk(CHUNK_ID_LSDE); if (lsde) { - unsigned char byte = lsde->ReadUint8(); - EGOptions.AttackCancel = byte & 1; - EGOptions.AttackHoldCancel = byte & (1 << 1); - EGOptions.Decay1Cancel = byte & (1 << 2); - EGOptions.Decay2Cancel = byte & (1 << 3); - EGOptions.ReleaseCancel = byte & (1 << 4); + eg_opt_t* pEGOpts[2] = { &EG1Options, &EG2Options }; + for (int i = 0; i < 2; ++i) { + unsigned char byte = lsde->ReadUint8(); + pEGOpts[i]->AttackCancel = byte & 1; + pEGOpts[i]->AttackHoldCancel = byte & (1 << 1); + pEGOpts[i]->Decay1Cancel = byte & (1 << 2); + pEGOpts[i]->Decay2Cancel = byte & (1 << 3); + pEGOpts[i]->ReleaseCancel = byte & (1 << 4); + } } pVelocityAttenuationTable = GetVelocityTable(VelocityResponseCurve, @@ -1931,7 +1934,8 @@ SRLZ(MSDecode); //SRLZ(SampleStartOffset); SRLZ(SampleAttenuation); - SRLZ(EGOptions); + SRLZ(EG1Options); + SRLZ(EG2Options); // derived attributes from DLS::Sampler SRLZ(FineTune); @@ -2246,20 +2250,25 @@ // only add this "LSDE" chunk if the EG options do not match the // default EG behavior eg_opt_t defaultOpt; - if (memcmp(&EGOptions, &defaultOpt, sizeof(eg_opt_t))) { - lsde = pParentList->AddSubChunk(CHUNK_ID_LSDE, 1); + if (memcmp(&EG1Options, &defaultOpt, sizeof(eg_opt_t)) || + memcmp(&EG2Options, &defaultOpt, sizeof(eg_opt_t))) + { + lsde = pParentList->AddSubChunk(CHUNK_ID_LSDE, 2); // move LSDE chunk to the end of parent list pParentList->MoveSubChunk(lsde, (RIFF::Chunk*)NULL); } } if (lsde) { - unsigned char* pByte = (unsigned char*) lsde->LoadChunkData(); - *pByte = - (EGOptions.AttackCancel ? 1 : 0) | - (EGOptions.AttackHoldCancel ? (1<<1) : 0) | - (EGOptions.Decay1Cancel ? (1<<2) : 0) | - (EGOptions.Decay2Cancel ? (1<<3) : 0) | - (EGOptions.ReleaseCancel ? (1<<4) : 0); + unsigned char* pData = (unsigned char*) lsde->LoadChunkData(); + eg_opt_t* pEGOpts[2] = { &EG1Options, &EG2Options }; + for (int i = 0; i < 2; ++i) { + pData[i] = + (pEGOpts[i]->AttackCancel ? 1 : 0) | + (pEGOpts[i]->AttackHoldCancel ? (1<<1) : 0) | + (pEGOpts[i]->Decay1Cancel ? (1<<2) : 0) | + (pEGOpts[i]->Decay2Cancel ? (1<<3) : 0) | + (pEGOpts[i]->ReleaseCancel ? (1<<4) : 0); + } } } @@ -2300,6 +2309,33 @@ // get the corresponding velocity table from the table map or create & calculate that table if it doesn't exist yet double* DimensionRegion::GetVelocityTable(curve_type_t curveType, uint8_t depth, uint8_t scaling) { + // sanity check input parameters + // (fallback to some default parameters on ill input) + switch (curveType) { + case curve_type_nonlinear: + case curve_type_linear: + if (depth > 4) { + printf("Warning: Invalid depth (0x%x) for velocity curve type (0x%x).\n", depth, curveType); + depth = 0; + scaling = 0; + } + break; + case curve_type_special: + if (depth > 5) { + printf("Warning: Invalid depth (0x%x) for velocity curve type 'special'.\n", depth); + depth = 0; + scaling = 0; + } + break; + case curve_type_unknown: + default: + printf("Warning: Unknown velocity curve type (0x%x).\n", curveType); + curveType = curve_type_linear; + depth = 0; + scaling = 0; + break; + } + double* table; uint32_t tableKey = (curveType<<16) | (depth<<8) | scaling; if (pVelocityTables->count(tableKey)) { // if key exists @@ -3225,7 +3261,8 @@ if (file->GetAutoLoad()) { for (uint i = 0; i < DimensionRegions; i++) { uint32_t wavepoolindex = _3lnk->ReadUint32(); - if (file->pWavePoolTable) pDimensionRegions[i]->pSample = GetSampleFromWavePool(wavepoolindex); + if (file->pWavePoolTable && pDimensionRegions[i]) + pDimensionRegions[i]->pSample = GetSampleFromWavePool(wavepoolindex); } GetSample(); // load global region sample reference } @@ -4106,6 +4143,7 @@ if ((int32_t)WavePoolTableIndex == -1) return NULL; File* file = (File*) GetParent()->GetParent(); if (!file->pWavePoolTable) return NULL; + if (WavePoolTableIndex + 1 > file->WavePoolCount) return NULL; // for new files or files >= 2 GB use 64 bit wave pool offsets if (file->pRIFF->IsNew() || (file->pRIFF->GetCurrentFileSize() >> 31)) { // use 64 bit wave pool offsets (treating this as large file) @@ -4732,7 +4770,9 @@ RegionList::iterator end = pRegions->end(); for (; iter != end; ++iter) { gig::Region* pRegion = static_cast(*iter); - for (int iKey = pRegion->KeyRange.low; iKey <= pRegion->KeyRange.high; iKey++) { + const int low = std::max(int(pRegion->KeyRange.low), 0); + const int high = std::min(int(pRegion->KeyRange.high), 127); + for (int iKey = low; iKey <= high; iKey++) { RegionKeyTable[iKey] = pRegion; } }