--- libgig/trunk/src/gig.cpp 2004/10/08 17:25:28 269 +++ libgig/trunk/src/gig.cpp 2005/01/23 20:47:18 347 @@ -66,10 +66,16 @@ Compressed = (waveList->GetSubChunk(CHUNK_ID_EWAV)); if (Compressed) { ScanCompressedSample(); - if (!pDecompressionBuffer) { - pDecompressionBuffer = new int8_t[INITIAL_SAMPLE_BUFFER_SIZE]; - DecompressionBufferSize = INITIAL_SAMPLE_BUFFER_SIZE; - } + } + + if (BitDepth > 24) throw gig::Exception("Only samples up to 24 bit supported"); + if (Compressed && Channels == 1) throw gig::Exception("Mono compressed samples not yet supported"); + if (Compressed && BitDepth == 24) throw gig::Exception("24 bit compressed samples not yet supported"); + + // we use a buffer for decompression and for truncating 24 bit samples to 16 bit + if ((Compressed || BitDepth == 24) && !pDecompressionBuffer) { + pDecompressionBuffer = new int8_t[INITIAL_SAMPLE_BUFFER_SIZE]; + DecompressionBufferSize = INITIAL_SAMPLE_BUFFER_SIZE; } FrameOffset = 0; // just for streaming compressed samples @@ -502,7 +508,22 @@ */ unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) { if (SampleCount == 0) return 0; - if (!Compressed) return pCkData->Read(pBuffer, SampleCount, FrameSize); //FIXME: channel inversion due to endian correction? + if (!Compressed) { + if (BitDepth == 24) { + // 24 bit sample. For now just truncate to 16 bit. + int8_t* pSrc = (int8_t*)this->pDecompressionBuffer; + int8_t* pDst = (int8_t*)pBuffer; + unsigned long n = pCkData->Read(pSrc, SampleCount, FrameSize); + for (int i = SampleCount * (FrameSize / 3) ; i > 0 ; i--) { + pSrc++; + *pDst++ = *pSrc++; + *pDst++ = *pSrc++; + } + return SampleCount; + } else { + return pCkData->Read(pBuffer, SampleCount, FrameSize); //FIXME: channel inversion due to endian correction? + } + } else { //FIXME: no support for mono compressed samples yet, are there any? if (this->SamplePos >= this->SamplesTotal) return 0; //TODO: efficiency: we simply assume here that all frames are compressed, maybe we should test for an average compression rate @@ -781,10 +802,6 @@ LFO3Controller = static_cast(lfo3ctrl & 0x07); // lower 3 bits LFO3Sync = lfo3ctrl & 0x20; // bit 5 InvertAttenuationController = lfo3ctrl & 0x80; // bit 7 - if (VCFType == vcf_type_lowpass) { - if (lfo3ctrl & 0x40) // bit 6 - VCFType = vcf_type_lowpassturbo; - } AttenuationController = DecodeLeverageController(static_cast<_lev_ctrl_t>(_3ewa->ReadUint8())); uint8_t lfo2ctrl = _3ewa->ReadUint8(); LFO2Controller = static_cast(lfo2ctrl & 0x07); // lower 3 bits @@ -829,6 +846,10 @@ VCFVelocityDynamicRange = vcfvelocity % 5; VCFVelocityCurve = static_cast(vcfvelocity / 5); VCFType = static_cast(_3ewa->ReadUint8()); + if (VCFType == vcf_type_lowpass) { + if (lfo3ctrl & 0x40) // bit 6 + VCFType = vcf_type_lowpassturbo; + } // get the corresponding velocity->volume table from the table map or create & calculate that table if it doesn't exist yet uint32_t tableKey = (VelocityResponseCurve<<16) | (VelocityResponseDepth<<8) | VelocityResponseCurveScaling; @@ -836,36 +857,10 @@ pVelocityAttenuationTable = (*pVelocityTables)[tableKey]; } else { - pVelocityAttenuationTable = new double[128]; - switch (VelocityResponseCurve) { // calculate the new table - case curve_type_nonlinear: - for (int velocity = 0; velocity < 128; velocity++) { - pVelocityAttenuationTable[velocity] = - GIG_VELOCITY_TRANSFORM_NONLINEAR(((double)velocity),((double)VelocityResponseDepth),((double)VelocityResponseCurveScaling)); - if (pVelocityAttenuationTable[velocity] > 1.0) pVelocityAttenuationTable[velocity] = 1.0; - else if (pVelocityAttenuationTable[velocity] < 1e-15) pVelocityAttenuationTable[velocity] = 0.0; - } - break; - case curve_type_linear: - for (int velocity = 0; velocity < 128; velocity++) { - pVelocityAttenuationTable[velocity] = - GIG_VELOCITY_TRANSFORM_LINEAR(((double)velocity),((double)VelocityResponseDepth),((double)VelocityResponseCurveScaling)); - if (pVelocityAttenuationTable[velocity] > 1.0) pVelocityAttenuationTable[velocity] = 1.0; - else if (pVelocityAttenuationTable[velocity] < 1e-15) pVelocityAttenuationTable[velocity] = 0.0; - } - break; - case curve_type_special: - for (int velocity = 0; velocity < 128; velocity++) { - pVelocityAttenuationTable[velocity] = - GIG_VELOCITY_TRANSFORM_SPECIAL(((double)velocity),((double)VelocityResponseDepth),((double)VelocityResponseCurveScaling)); - if (pVelocityAttenuationTable[velocity] > 1.0) pVelocityAttenuationTable[velocity] = 1.0; - else if (pVelocityAttenuationTable[velocity] < 1e-15) pVelocityAttenuationTable[velocity] = 0.0; - } - break; - case curve_type_unknown: - default: - throw gig::Exception("Unknown transform curve type."); - } + pVelocityAttenuationTable = + CreateVelocityTable(VelocityResponseCurve, + VelocityResponseDepth, + VelocityResponseCurveScaling); (*pVelocityTables)[tableKey] = pVelocityAttenuationTable; // put the new table into the tables map } } @@ -1018,6 +1013,68 @@ return pVelocityAttenuationTable[MIDIKeyVelocity]; } + double* DimensionRegion::CreateVelocityTable(curve_type_t curveType, uint8_t depth, uint8_t scaling) { + + // line-segment approximations of the 15 velocity curves + + // linear + const int lin0[] = { 1, 1, 127, 127 }; + const int lin1[] = { 1, 21, 127, 127 }; + const int lin2[] = { 1, 45, 127, 127 }; + const int lin3[] = { 1, 74, 127, 127 }; + const int lin4[] = { 1, 127, 127, 127 }; + + // non-linear + const int non0[] = { 1, 4, 24, 5, 57, 17, 92, 57, 122, 127, 127, 127 }; + const int non1[] = { 1, 4, 46, 9, 93, 56, 118, 106, 123, 127, + 127, 127 }; + const int non2[] = { 1, 4, 46, 9, 57, 20, 102, 107, 107, 127, + 127, 127 }; + const int non3[] = { 1, 15, 10, 19, 67, 73, 80, 80, 90, 98, 98, 127, + 127, 127 }; + const int non4[] = { 1, 25, 33, 57, 82, 81, 92, 127, 127, 127 }; + + // special + const int spe0[] = { 1, 2, 76, 10, 90, 15, 95, 20, 99, 28, 103, 44, + 113, 127, 127, 127 }; + const int spe1[] = { 1, 2, 27, 5, 67, 18, 89, 29, 95, 35, 107, 67, + 118, 127, 127, 127 }; + const int spe2[] = { 1, 1, 33, 1, 53, 5, 61, 13, 69, 32, 79, 74, + 85, 90, 91, 127, 127, 127 }; + const int spe3[] = { 1, 32, 28, 35, 66, 48, 89, 59, 95, 65, 99, 73, + 117, 127, 127, 127 }; + const int spe4[] = { 1, 4, 23, 5, 49, 13, 57, 17, 92, 57, 122, 127, + 127, 127 }; + + const int* const curves[] = { non0, non1, non2, non3, non4, + lin0, lin1, lin2, lin3, lin4, + spe0, spe1, spe2, spe3, spe4 }; + + double* const table = new double[128]; + + const int* curve = curves[curveType * 5 + depth]; + const int s = scaling == 0 ? 20 : scaling; // 0 or 20 means no scaling + + table[0] = 0; + for (int x = 1 ; x < 128 ; x++) { + + if (x > curve[2]) curve += 2; + double y = curve[1] + (x - curve[0]) * + (double(curve[3] - curve[1]) / (curve[2] - curve[0])); + y = y / 127; + + // Scale up for s > 20, down for s < 20. When + // down-scaling, the curve still ends at 1.0. + if (s < 20 && y >= 0.5) + y = y / ((2 - 40.0 / s) * y + 40.0 / s - 1); + else + y = y * (s / 20.0); + if (y > 1) y = 1; + + table[x] = y; + } + return table; + } // *************** Region *************** @@ -1026,9 +1083,12 @@ Region::Region(Instrument* pInstrument, RIFF::List* rgnList) : DLS::Region((DLS::Instrument*) pInstrument, rgnList) { // Initialization Dimensions = 0; - for (int i = 0; i < 32; i++) { + for (int i = 0; i < 256; i++) { pDimensionRegions[i] = NULL; } + Layers = 1; + File* file = (File*) GetParent()->GetParent(); + int dimensionBits = (file->pVersion && file->pVersion->major == 3) ? 8 : 5; // Actual Loading @@ -1037,7 +1097,7 @@ RIFF::Chunk* _3lnk = rgnList->GetSubChunk(CHUNK_ID_3LNK); if (_3lnk) { DimensionRegions = _3lnk->ReadUint32(); - for (int i = 0; i < 5; i++) { + for (int i = 0; i < dimensionBits; i++) { dimension_t dimension = static_cast(_3lnk->ReadUint8()); uint8_t bits = _3lnk->ReadUint8(); if (dimension == dimension_none) { // inactive dimension @@ -1061,6 +1121,9 @@ (pDimensionDefinitions[i].split_type == split_type_normal) ? 128 / pDimensionDefinitions[i].zones : 0; Dimensions++; + + // if this is a layer dimension, remember the amount of layers + if (dimension == dimension_layer) Layers = pDimensionDefinitions[i].zones; } _3lnk->SetPos(6, RIFF::stream_curpos); // jump forward to next dimension definition } @@ -1077,11 +1140,11 @@ else { // custom defined ranges pDimDef->split_type = split_type_customvelocity; pDimDef->ranges = new range_t[pDimDef->zones]; - unsigned int bits[5] = {0,0,0,0,0}; + uint8_t bits[8] = { 0 }; int previousUpperLimit = -1; for (int velocityZone = 0; velocityZone < pDimDef->zones; velocityZone++) { bits[i] = velocityZone; - DimensionRegion* pDimRegion = GetDimensionRegionByBit(bits[4],bits[3],bits[2],bits[1],bits[0]); + DimensionRegion* pDimRegion = GetDimensionRegionByBit(bits); pDimDef->ranges[velocityZone].low = previousUpperLimit + 1; pDimDef->ranges[velocityZone].high = pDimRegion->VelocityUpperLimit; @@ -1095,8 +1158,14 @@ } } + // jump to start of the wave pool indices (if not already there) + File* file = (File*) GetParent()->GetParent(); + if (file->pVersion && file->pVersion->major == 3) + _3lnk->SetPos(68); // version 3 has a different 3lnk structure + else + _3lnk->SetPos(44); + // load sample references - _3lnk->SetPos(44); // jump to start of the wave pool indices (if not already there) for (uint i = 0; i < DimensionRegions; i++) { uint32_t wavepoolindex = _3lnk->ReadUint32(); pDimensionRegions[i]->pSample = GetSampleFromWavePool(wavepoolindex); @@ -1143,18 +1212,15 @@ * left channel, 1 for right channel or 0 for layer 0, 1 for layer 1, * etc.). * - * @param Dim4Val MIDI controller value (0-127) for dimension 4 - * @param Dim3Val MIDI controller value (0-127) for dimension 3 - * @param Dim2Val MIDI controller value (0-127) for dimension 2 - * @param Dim1Val MIDI controller value (0-127) for dimension 1 - * @param Dim0Val MIDI controller value (0-127) for dimension 0 + * @param DimValues MIDI controller values (0-127) for dimension 0 to 7 * @returns adress to the DimensionRegion for the given situation * @see pDimensionDefinitions * @see Dimensions */ - DimensionRegion* Region::GetDimensionRegionByValue(uint Dim4Val, uint Dim3Val, uint Dim2Val, uint Dim1Val, uint Dim0Val) { - uint8_t bits[5] = {Dim0Val,Dim1Val,Dim2Val,Dim3Val,Dim4Val}; + DimensionRegion* Region::GetDimensionRegionByValue(const uint DimValues[8]) { + uint8_t bits[8] = { 0 }; for (uint i = 0; i < Dimensions; i++) { + bits[i] = DimValues[i]; switch (pDimensionDefinitions[i].split_type) { case split_type_normal: bits[i] /= pDimensionDefinitions[i].zone_size; @@ -1168,7 +1234,7 @@ break; } } - return GetDimensionRegionByBit(bits[4],bits[3],bits[2],bits[1],bits[0]); + return GetDimensionRegionByBit(bits); } /** @@ -1176,20 +1242,19 @@ * numbers (zone index). You usually use GetDimensionRegionByValue * instead of calling this method directly! * - * @param Dim4Bit Bit number for dimension 4 - * @param Dim3Bit Bit number for dimension 3 - * @param Dim2Bit Bit number for dimension 2 - * @param Dim1Bit Bit number for dimension 1 - * @param Dim0Bit Bit number for dimension 0 + * @param DimBits Bit numbers for dimension 0 to 7 * @returns adress to the DimensionRegion for the given dimension * bit numbers * @see GetDimensionRegionByValue() */ - DimensionRegion* Region::GetDimensionRegionByBit(uint8_t Dim4Bit, uint8_t Dim3Bit, uint8_t Dim2Bit, uint8_t Dim1Bit, uint8_t Dim0Bit) { - return *(pDimensionRegions + ((((((((Dim4Bit << pDimensionDefinitions[3].bits) | Dim3Bit) - << pDimensionDefinitions[2].bits) | Dim2Bit) - << pDimensionDefinitions[1].bits) | Dim1Bit) - << pDimensionDefinitions[0].bits) | Dim0Bit) ); + DimensionRegion* Region::GetDimensionRegionByBit(const uint8_t DimBits[8]) { + return pDimensionRegions[((((((DimBits[7] << pDimensionDefinitions[6].bits | DimBits[6]) + << pDimensionDefinitions[5].bits | DimBits[5]) + << pDimensionDefinitions[4].bits | DimBits[4]) + << pDimensionDefinitions[3].bits | DimBits[3]) + << pDimensionDefinitions[2].bits | DimBits[2]) + << pDimensionDefinitions[1].bits | DimBits[1]) + << pDimensionDefinitions[0].bits | DimBits[0]]; } /**