45 |
Product = smpl->ReadInt32(); |
Product = smpl->ReadInt32(); |
46 |
SamplePeriod = smpl->ReadInt32(); |
SamplePeriod = smpl->ReadInt32(); |
47 |
MIDIUnityNote = smpl->ReadInt32(); |
MIDIUnityNote = smpl->ReadInt32(); |
48 |
MIDIPitchFraction = smpl->ReadInt32(); |
FineTune = smpl->ReadInt32(); |
49 |
smpl->Read(&SMPTEFormat, 1, 4); |
smpl->Read(&SMPTEFormat, 1, 4); |
50 |
SMPTEOffset = smpl->ReadInt32(); |
SMPTEOffset = smpl->ReadInt32(); |
51 |
Loops = smpl->ReadInt32(); |
Loops = smpl->ReadInt32(); |
52 |
|
uint32_t manufByt = smpl->ReadInt32(); |
53 |
LoopID = smpl->ReadInt32(); |
LoopID = smpl->ReadInt32(); |
54 |
smpl->Read(&LoopType, 1, 4); |
smpl->Read(&LoopType, 1, 4); |
55 |
LoopStart = smpl->ReadInt32(); |
LoopStart = smpl->ReadInt32(); |
72 |
} |
} |
73 |
} |
} |
74 |
FrameOffset = 0; // just for streaming compressed samples |
FrameOffset = 0; // just for streaming compressed samples |
75 |
|
|
76 |
|
LoopStart /= FrameSize; // convert to sample points |
77 |
|
LoopEnd /= FrameSize; // convert to sample points |
78 |
|
LoopSize = LoopEnd - LoopStart; |
79 |
} |
} |
80 |
|
|
81 |
/// Scans compressed samples for mandatory informations (e.g. actual number of total sample points). |
/// Scans compressed samples for mandatory informations (e.g. actual number of total sample points). |
328 |
* @see SetPos() |
* @see SetPos() |
329 |
*/ |
*/ |
330 |
unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) { |
unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) { |
331 |
|
if (SampleCount == 0) return 0; |
332 |
if (!Compressed) return pCkData->Read(pBuffer, SampleCount, FrameSize); //FIXME: channel inversion due to endian correction? |
if (!Compressed) return pCkData->Read(pBuffer, SampleCount, FrameSize); //FIXME: channel inversion due to endian correction? |
333 |
else { //FIXME: no support for mono compressed samples yet, are there any? |
else { //FIXME: no support for mono compressed samples yet, are there any? |
334 |
if (this->SamplePos >= this->SamplesTotal) return 0; |
if (this->SamplePos >= this->SamplesTotal) return 0; |
497 |
// *************** DimensionRegion *************** |
// *************** DimensionRegion *************** |
498 |
// * |
// * |
499 |
|
|
500 |
|
uint DimensionRegion::Instances = 0; |
501 |
|
DimensionRegion::VelocityTableMap* DimensionRegion::pVelocityTables = NULL; |
502 |
|
|
503 |
DimensionRegion::DimensionRegion(RIFF::List* _3ewl) : DLS::Sampler(_3ewl) { |
DimensionRegion::DimensionRegion(RIFF::List* _3ewl) : DLS::Sampler(_3ewl) { |
504 |
|
Instances++; |
505 |
|
|
506 |
memcpy(&Crossfade, &SamplerOptions, 4); |
memcpy(&Crossfade, &SamplerOptions, 4); |
507 |
|
if (!pVelocityTables) pVelocityTables = new VelocityTableMap; |
508 |
|
|
509 |
RIFF::Chunk* _3ewa = _3ewl->GetSubChunk(CHUNK_ID_3EWA); |
RIFF::Chunk* _3ewa = _3ewl->GetSubChunk(CHUNK_ID_3EWA); |
510 |
_3ewa->ReadInt32(); // unknown, allways 0x0000008C ? |
_3ewa->ReadInt32(); // unknown, allways 0x0000008C ? |
656 |
VCFVelocityDynamicRange = vcfvelocity % 5; |
VCFVelocityDynamicRange = vcfvelocity % 5; |
657 |
VCFVelocityCurve = static_cast<curve_type_t>(vcfvelocity / 5); |
VCFVelocityCurve = static_cast<curve_type_t>(vcfvelocity / 5); |
658 |
VCFType = static_cast<vcf_type_t>(_3ewa->ReadUint8()); |
VCFType = static_cast<vcf_type_t>(_3ewa->ReadUint8()); |
659 |
|
|
660 |
|
// get the corresponding velocity->volume table from the table map or create & calculate that table if it doesn't exist yet |
661 |
|
uint32_t tableKey = (VelocityResponseCurve<<16) | (VelocityResponseDepth<<8) | VelocityResponseCurveScaling; |
662 |
|
if (pVelocityTables->count(tableKey)) { // if key exists |
663 |
|
pVelocityAttenuationTable = (*pVelocityTables)[tableKey]; |
664 |
|
} |
665 |
|
else { |
666 |
|
pVelocityAttenuationTable = new double[128]; |
667 |
|
switch (VelocityResponseCurve) { // calculate the new table |
668 |
|
case curve_type_nonlinear: |
669 |
|
for (int velocity = 0; velocity < 128; velocity++) { |
670 |
|
pVelocityAttenuationTable[velocity] = |
671 |
|
GIG_VELOCITY_TRANSFORM_NONLINEAR((double)(velocity+1),(double)(VelocityResponseDepth+1),(double)VelocityResponseCurveScaling); |
672 |
|
if (pVelocityAttenuationTable[velocity] > 1.0) pVelocityAttenuationTable[velocity] = 1.0; |
673 |
|
else if (pVelocityAttenuationTable[velocity] < 0.0) pVelocityAttenuationTable[velocity] = 0.0; |
674 |
|
} |
675 |
|
break; |
676 |
|
case curve_type_linear: |
677 |
|
for (int velocity = 0; velocity < 128; velocity++) { |
678 |
|
pVelocityAttenuationTable[velocity] = |
679 |
|
GIG_VELOCITY_TRANSFORM_LINEAR((double)velocity,(double)(VelocityResponseDepth+1),(double)VelocityResponseCurveScaling); |
680 |
|
if (pVelocityAttenuationTable[velocity] > 1.0) pVelocityAttenuationTable[velocity] = 1.0; |
681 |
|
else if (pVelocityAttenuationTable[velocity] < 0.0) pVelocityAttenuationTable[velocity] = 0.0; |
682 |
|
} |
683 |
|
break; |
684 |
|
case curve_type_special: |
685 |
|
for (int velocity = 0; velocity < 128; velocity++) { |
686 |
|
pVelocityAttenuationTable[velocity] = |
687 |
|
GIG_VELOCITY_TRANSFORM_SPECIAL((double)(velocity+1),(double)(VelocityResponseDepth+1),(double)VelocityResponseCurveScaling); |
688 |
|
if (pVelocityAttenuationTable[velocity] > 1.0) pVelocityAttenuationTable[velocity] = 1.0; |
689 |
|
else if (pVelocityAttenuationTable[velocity] < 0.0) pVelocityAttenuationTable[velocity] = 0.0; |
690 |
|
} |
691 |
|
break; |
692 |
|
case curve_type_unknown: |
693 |
|
default: |
694 |
|
throw gig::Exception("Unknown transform curve type."); |
695 |
|
} |
696 |
|
(*pVelocityTables)[tableKey] = pVelocityAttenuationTable; // put the new table into the tables map |
697 |
|
} |
698 |
|
} |
699 |
|
|
700 |
|
DimensionRegion::~DimensionRegion() { |
701 |
|
Instances--; |
702 |
|
if (!Instances) { |
703 |
|
// delete the velocity->volume tables |
704 |
|
VelocityTableMap::iterator iter; |
705 |
|
for (iter = pVelocityTables->begin(); iter != pVelocityTables->end(); iter++) { |
706 |
|
double* pTable = iter->second; |
707 |
|
if (pTable) delete[] pTable; |
708 |
|
} |
709 |
|
pVelocityTables->clear(); |
710 |
|
delete pVelocityTables; |
711 |
|
pVelocityTables = NULL; |
712 |
|
} |
713 |
|
} |
714 |
|
|
715 |
|
/** |
716 |
|
* Returns the correct amplitude factor for the given \a MIDIKeyVelocity. |
717 |
|
* All involved parameters (VelocityResponseCurve, VelocityResponseDepth |
718 |
|
* and VelocityResponseCurveScaling) involved are taken into account to |
719 |
|
* calculate the amplitude factor. Use this method when a key was |
720 |
|
* triggered to get the volume with which the sample should be played |
721 |
|
* back. |
722 |
|
* |
723 |
|
* @param MIDI velocity value of the triggered key (between 0 and 127) |
724 |
|
* @returns amplitude factor (between 0.0 and 1.0) |
725 |
|
*/ |
726 |
|
double DimensionRegion::GetVelocityAttenuation(uint8_t MIDIKeyVelocity) { |
727 |
|
return pVelocityAttenuationTable[MIDIKeyVelocity]; |
728 |
} |
} |
729 |
|
|
730 |
|
|
1076 |
return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL; |
return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL; |
1077 |
} |
} |
1078 |
|
|
1079 |
|
/** |
1080 |
|
* Returns the instrument with the given index. |
1081 |
|
* |
1082 |
|
* @returns sought instrument or NULL if there's no such instrument |
1083 |
|
*/ |
1084 |
|
Instrument* File::GetInstrument(uint index) { |
1085 |
|
if (!pInstruments) LoadInstruments(); |
1086 |
|
if (!pInstruments) return NULL; |
1087 |
|
InstrumentsIterator = pInstruments->begin(); |
1088 |
|
for (uint i = 0; InstrumentsIterator != pInstruments->end(); i++) { |
1089 |
|
if (i == index) return *InstrumentsIterator; |
1090 |
|
InstrumentsIterator++; |
1091 |
|
} |
1092 |
|
return NULL; |
1093 |
|
} |
1094 |
|
|
1095 |
void File::LoadInstruments() { |
void File::LoadInstruments() { |
1096 |
RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS); |
RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS); |
1097 |
if (lstInstruments) { |
if (lstInstruments) { |