--- libgig/trunk/src/gig.cpp 2004/09/05 00:46:28 231 +++ libgig/trunk/src/gig.cpp 2004/11/21 18:02:21 308 @@ -680,7 +680,7 @@ if (!pVelocityTables) pVelocityTables = new VelocityTableMap; RIFF::Chunk* _3ewa = _3ewl->GetSubChunk(CHUNK_ID_3EWA); - _3ewa->ReadInt32(); // unknown, allways 0x0000008C ? + _3ewa->ReadInt32(); // unknown, always 0x0000008C ? LFO3Frequency = (double) GIG_EXP_DECODE(_3ewa->ReadInt32()); EG3Attack = (double) GIG_EXP_DECODE(_3ewa->ReadInt32()); _3ewa->ReadInt16(); // unknown @@ -774,7 +774,7 @@ else if (pitchTrackDimensionBypass & 0x20) DimensionBypass = dim_bypass_ctrl_95; else DimensionBypass = dim_bypass_ctrl_none; uint8_t pan = _3ewa->ReadUint8(); - Pan = (pan < 64) ? pan : (-1) * (int8_t)pan - 63; + Pan = (pan < 64) ? pan : -((int)pan - 63); // signed 7 bit -> signed 8 bit SelfMask = _3ewa->ReadInt8() & 0x01; _3ewa->ReadInt8(); // unknown uint8_t lfo3ctrl = _3ewa->ReadUint8(); @@ -836,36 +836,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 +992,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 *************** @@ -1029,6 +1065,7 @@ for (int i = 0; i < 32; i++) { pDimensionRegions[i] = NULL; } + Layers = 1; // Actual Loading @@ -1053,13 +1090,17 @@ pDimensionDefinitions[i].bits = bits; pDimensionDefinitions[i].zones = 0x01 << bits; // = pow(2,bits) pDimensionDefinitions[i].split_type = (dimension == dimension_layer || - dimension == dimension_samplechannel) ? split_type_bit - : split_type_normal; + dimension == dimension_samplechannel || + dimension == dimension_releasetrigger) ? split_type_bit + : split_type_normal; pDimensionDefinitions[i].ranges = NULL; // it's not possible to check velocity dimensions for custom defined ranges at this point pDimensionDefinitions[i].zone_size = (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 } @@ -1152,7 +1193,7 @@ * @see Dimensions */ DimensionRegion* Region::GetDimensionRegionByValue(uint Dim4Val, uint Dim3Val, uint Dim2Val, uint Dim1Val, uint Dim0Val) { - unsigned int bits[5] = {Dim0Val,Dim1Val,Dim2Val,Dim3Val,Dim4Val}; + uint8_t bits[5] = {Dim0Val,Dim1Val,Dim2Val,Dim3Val,Dim4Val}; for (uint i = 0; i < Dimensions; i++) { switch (pDimensionDefinitions[i].split_type) { case split_type_normal: @@ -1161,7 +1202,10 @@ case split_type_customvelocity: bits[i] = VelocityTable[bits[i]]; break; - // else the value is already the sought dimension bit number + case split_type_bit: // the value is already the sought dimension bit number + const uint8_t limiter_mask = (0xff << pDimensionDefinitions[i].bits) ^ 0xff; + bits[i] = bits[i] & limiter_mask; // just make sure the value don't uses more bits than allowed + break; } } return GetDimensionRegionByBit(bits[4],bits[3],bits[2],bits[1],bits[0]);