27 #include "Serialization.h" 36 #define GIG_FILE_EXT_VERSION 2 43 #define INITIAL_SAMPLE_BUFFER_SIZE 512000 // 512 kB 46 #define GIG_EXP_DECODE(x) (pow(1.000000008813822, x)) 47 #define GIG_EXP_ENCODE(x) (log(x) / log(1.000000008813822)) 48 #define GIG_PITCH_TRACK_EXTRACT(x) (!(x & 0x01)) 49 #define GIG_PITCH_TRACK_ENCODE(x) ((x) ? 0x00 : 0x01) 50 #define GIG_VCF_RESONANCE_CTRL_EXTRACT(x) ((x >> 4) & 0x03) 51 #define GIG_VCF_RESONANCE_CTRL_ENCODE(x) ((x & 0x03) << 4) 52 #define GIG_EG_CTR_ATTACK_INFLUENCE_EXTRACT(x) ((x >> 1) & 0x03) 53 #define GIG_EG_CTR_DECAY_INFLUENCE_EXTRACT(x) ((x >> 3) & 0x03) 54 #define GIG_EG_CTR_RELEASE_INFLUENCE_EXTRACT(x) ((x >> 5) & 0x03) 55 #define GIG_EG_CTR_ATTACK_INFLUENCE_ENCODE(x) ((x & 0x03) << 1) 56 #define GIG_EG_CTR_DECAY_INFLUENCE_ENCODE(x) ((x & 0x03) << 3) 57 #define GIG_EG_CTR_RELEASE_INFLUENCE_ENCODE(x) ((x & 0x03) << 5) 59 #define SRLZ(member) \ 60 archive->serializeMember(*this, member, #member); 69 inline int get12lo(
const unsigned char* pSrc)
71 const int x = pSrc[0] | (pSrc[1] & 0x0f) << 8;
72 return x & 0x800 ? x - 0x1000 : x;
75 inline int get12hi(
const unsigned char* pSrc)
77 const int x = pSrc[1] >> 4 | pSrc[2] << 4;
78 return x & 0x800 ? x - 0x1000 : x;
81 inline int16_t get16(
const unsigned char* pSrc)
83 return int16_t(pSrc[0] | pSrc[1] << 8);
86 inline int get24(
const unsigned char* pSrc)
88 const int x = pSrc[0] | pSrc[1] << 8 | pSrc[2] << 16;
89 return x & 0x800000 ? x - 0x1000000 : x;
92 inline void store24(
unsigned char* pDst,
int x)
99 void Decompress16(
int compressionmode,
const unsigned char* params,
100 int srcStep,
int dstStep,
101 const unsigned char* pSrc, int16_t* pDst,
102 file_offset_t currentframeoffset,
103 file_offset_t copysamples)
105 switch (compressionmode) {
107 pSrc += currentframeoffset * srcStep;
108 while (copysamples) {
117 int y = get16(params);
118 int dy = get16(params + 2);
119 while (currentframeoffset) {
123 currentframeoffset--;
125 while (copysamples) {
137 void Decompress24(
int compressionmode,
const unsigned char* params,
138 int dstStep,
const unsigned char* pSrc, uint8_t* pDst,
139 file_offset_t currentframeoffset,
140 file_offset_t copysamples,
int truncatedBits)
142 int y, dy, ddy, dddy;
144 #define GET_PARAMS(params) \ 146 dy = y - get24((params) + 3); \ 147 ddy = get24((params) + 6); \ 148 dddy = get24((params) + 9) 150 #define SKIP_ONE(x) \ 156 #define COPY_ONE(x) \ 158 store24(pDst, y << truncatedBits); \ 161 switch (compressionmode) {
163 pSrc += currentframeoffset * 3;
164 while (copysamples) {
165 store24(pDst, get24(pSrc) << truncatedBits);
174 while (currentframeoffset) {
175 SKIP_ONE(get16(pSrc));
177 currentframeoffset--;
179 while (copysamples) {
180 COPY_ONE(get16(pSrc));
188 while (currentframeoffset > 1) {
189 SKIP_ONE(get12lo(pSrc));
190 SKIP_ONE(get12hi(pSrc));
192 currentframeoffset -= 2;
194 if (currentframeoffset) {
195 SKIP_ONE(get12lo(pSrc));
196 currentframeoffset--;
198 COPY_ONE(get12hi(pSrc));
203 while (copysamples > 1) {
204 COPY_ONE(get12lo(pSrc));
205 COPY_ONE(get12hi(pSrc));
210 COPY_ONE(get12lo(pSrc));
216 while (currentframeoffset) {
217 SKIP_ONE(int8_t(*pSrc++));
218 currentframeoffset--;
220 while (copysamples) {
221 COPY_ONE(int8_t(*pSrc++));
228 const int bytesPerFrame[] = { 4096, 2052, 768, 524, 396, 268 };
229 const int bytesPerFrameNoHdr[] = { 4096, 2048, 768, 512, 384, 256 };
230 const int headerSize[] = { 0, 4, 0, 12, 12, 12 };
231 const int bitsPerSample[] = { 16, 8, 24, 16, 12, 8 };
239 static uint32_t* __initCRCTable() {
240 static uint32_t res[256];
242 for (
int i = 0 ; i < 256 ; i++) {
244 for (
int j = 0 ; j < 8 ; j++) {
245 c = (c & 1) ? 0xedb88320 ^ (c >> 1) : c >> 1;
252 static const uint32_t* __CRCTable = __initCRCTable();
259 inline static void __resetCRC(uint32_t& crc) {
282 static void __calculateCRC(
unsigned char* buf,
size_t bufSize, uint32_t& crc) {
283 for (
size_t i = 0 ; i < bufSize ; i++) {
284 crc = __CRCTable[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
293 inline static void __finalizeCRC(uint32_t& crc) {
315 static int __resolveZoneSize(dimension_def_t& dimension_definition) {
317 ? int(128.0 / dimension_definition.zones) : 0;
347 eg_opt_t::eg_opt_t() {
349 AttackHoldCancel =
true;
352 ReleaseCancel =
true;
357 SRLZ(AttackHoldCancel);
393 static const DLS::Info::string_length_t fixedStringLengths[] = {
394 { CHUNK_ID_INAM, 64 },
408 uint32_t crc = pFile->GetSampleChecksumByIndex(index);
417 uint16_t iSampleGroup = pCk3gix->
ReadInt16();
477 if (version > 2 &&
BitDepth == 24) {
482 ScanCompressedSample();
547 const int iReadAtOnce = 32*1024;
548 char* buf =
new char[iReadAtOnce * orig->
FrameSize];
550 file_offset_t restorePos = pOrig->
GetPos();
553 for (file_offset_t n = pOrig->
Read(buf, iReadAtOnce); n;
554 n = pOrig->
Read(buf, iReadAtOnce))
558 pOrig->
SetPos(restorePos);
581 pCkSmpl = pWaveList->
AddSubChunk(CHUNK_ID_SMPL, 60);
594 store32(&pData[28],
Loops);
598 store32(&pData[36],
LoopID);
607 if (!pCk3gix) pCk3gix = pWaveList->
AddSubChunk(CHUNK_ID_3GIX, 4);
609 uint16_t iSampleGroup = 0;
610 File* pFile =
static_cast<File*
>(pParent);
611 if (pFile->pGroups) {
612 std::vector<Group*>::iterator iter = pFile->pGroups->begin();
613 std::vector<Group*>::iterator end = pFile->pGroups->end();
614 for (
int i = 0; iter != end; i++, iter++) {
623 store16(&pData[0], iSampleGroup);
635 void Sample::ScanCompressedSample() {
638 std::list<file_offset_t> frameOffsets;
646 for (
int i = 0 ; ; i++) {
649 if (
BitDepth != 24 || (i & 7) == 0) frameOffsets.push_back(pCkData->
GetPos());
653 if (mode_l > 5 || mode_r > 5)
throw gig::Exception(
"Unknown compression mode");
654 const file_offset_t frameSize = bytesPerFrame[mode_l] + bytesPerFrame[mode_r];
658 ((pCkData->
RemainingBytes() - headerSize[mode_l] - headerSize[mode_r]) << 3) /
659 (bitsPerSample[mode_l] + bitsPerSample[mode_r]);
664 pCkData->
SetPos(frameSize, RIFF::stream_curpos);
668 for (
int i = 0 ; ; i++) {
669 if (
BitDepth != 24 || (i & 7) == 0) frameOffsets.push_back(pCkData->
GetPos());
673 const file_offset_t frameSize = bytesPerFrame[mode];
677 ((pCkData->
RemainingBytes() - headerSize[mode]) << 3) / bitsPerSample[mode];
682 pCkData->
SetPos(frameSize, RIFF::stream_curpos);
689 FrameTable =
new file_offset_t[frameOffsets.size()];
690 std::list<file_offset_t>::iterator end = frameOffsets.end();
691 std::list<file_offset_t>::iterator iter = frameOffsets.begin();
692 for (
int i = 0; iter != end; i++, iter++) {
794 file_offset_t allocationsize = (SampleCount + NullSamplesCount) * this->
FrameSize;
895 case RIFF::stream_curpos:
898 case RIFF::stream_end:
901 case RIFF::stream_backward:
904 case RIFF::stream_start:
default:
910 file_offset_t frame = this->
SamplePos / 2048;
916 file_offset_t orderedBytes = SampleCount * this->
FrameSize;
917 file_offset_t result = pCkData->
SetPos(orderedBytes, Whence);
918 return (result == orderedBytes) ? SampleCount
967 file_offset_t samplestoread = SampleCount, totalreadsamples = 0, readsamples, samplestoloopend;
968 uint8_t* pDst = (uint8_t*) pBuffer;
977 if (
GetPos() <= loopEnd) {
985 if (!pPlaybackState->
reverse) {
987 samplestoloopend = loopEnd -
GetPos();
988 readsamples =
Read(&pDst[totalreadsamples * this->
FrameSize], Min(samplestoread, samplestoloopend), pExternalDecompressionBuffer);
989 samplestoread -= readsamples;
990 totalreadsamples += readsamples;
991 if (readsamples == samplestoloopend) {
992 pPlaybackState->
reverse =
true;
995 }
while (samplestoread && readsamples);
1005 file_offset_t swapareastart = totalreadsamples;
1007 file_offset_t samplestoreadinloop = Min(samplestoread, loopoffset);
1008 file_offset_t reverseplaybackend =
GetPos() - samplestoreadinloop;
1010 SetPos(reverseplaybackend);
1014 readsamples =
Read(&pDst[totalreadsamples * this->
FrameSize], samplestoreadinloop, pExternalDecompressionBuffer);
1015 samplestoreadinloop -= readsamples;
1016 samplestoread -= readsamples;
1017 totalreadsamples += readsamples;
1018 }
while (samplestoreadinloop && readsamples);
1020 SetPos(reverseplaybackend);
1022 if (reverseplaybackend == loop.
LoopStart) {
1024 pPlaybackState->
reverse =
false;
1028 if (totalreadsamples > swapareastart)
1029 SwapMemoryArea(&pDst[swapareastart * this->
FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize);
1031 }
while (samplestoread && readsamples);
1037 if (!pPlaybackState->
reverse)
do {
1038 samplestoloopend = loopEnd -
GetPos();
1039 readsamples =
Read(&pDst[totalreadsamples * this->
FrameSize], Min(samplestoread, samplestoloopend), pExternalDecompressionBuffer);
1040 samplestoread -= readsamples;
1041 totalreadsamples += readsamples;
1042 if (readsamples == samplestoloopend) {
1043 pPlaybackState->
reverse =
true;
1046 }
while (samplestoread && readsamples);
1048 if (!samplestoread)
break;
1056 file_offset_t swapareastart = totalreadsamples;
1060 file_offset_t reverseplaybackend = loop.
LoopStart + Abs((loopoffset - samplestoreadinloop) % loop.
LoopLength);
1062 SetPos(reverseplaybackend);
1068 samplestoloopend = loopEnd -
GetPos();
1069 readsamples =
Read(&pDst[totalreadsamples * this->
FrameSize], Min(samplestoreadinloop, samplestoloopend), pExternalDecompressionBuffer);
1070 samplestoreadinloop -= readsamples;
1071 samplestoread -= readsamples;
1072 totalreadsamples += readsamples;
1073 if (readsamples == samplestoloopend) {
1077 }
while (samplestoreadinloop && readsamples);
1079 SetPos(reverseplaybackend);
1082 SwapMemoryArea(&pDst[swapareastart * this->
FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize);
1090 samplestoloopend = loopEnd -
GetPos();
1091 readsamples =
Read(&pDst[totalreadsamples * this->
FrameSize], Min(samplestoread, samplestoloopend), pExternalDecompressionBuffer);
1092 samplestoread -= readsamples;
1093 totalreadsamples += readsamples;
1094 if (readsamples == samplestoloopend) {
1098 }
while (samplestoread && readsamples);
1106 if (samplestoread)
do {
1107 readsamples =
Read(&pDst[totalreadsamples * this->
FrameSize], samplestoread, pExternalDecompressionBuffer);
1108 samplestoread -= readsamples;
1109 totalreadsamples += readsamples;
1110 }
while (readsamples && samplestoread);
1115 return totalreadsamples;
1141 if (SampleCount == 0)
return 0;
1148 return Channels == 2 ? pCkData->
Read(pBuffer, SampleCount << 1, 2) >> 1
1149 : pCkData->
Read(pBuffer, SampleCount, 2);
1155 file_offset_t assumedsize = GuessSize(SampleCount),
1157 remainingsamples = SampleCount,
1158 copysamples, skipsamples,
1165 if (pDecompressionBuffer->
Size < assumedsize) {
1166 std::cerr <<
"gig::Read(): WARNING - decompression buffer size too small!" << std::endl;
1167 SampleCount = WorstCaseMaxSamples(pDecompressionBuffer);
1168 remainingsamples = SampleCount;
1169 assumedsize = GuessSize(SampleCount);
1172 unsigned char* pSrc = (
unsigned char*) pDecompressionBuffer->
pStart;
1173 int16_t* pDst = static_cast<int16_t*>(pBuffer);
1174 uint8_t* pDst24 =
static_cast<uint8_t*
>(pBuffer);
1175 remainingbytes = pCkData->
Read(pSrc, assumedsize, 1);
1177 while (remainingsamples && remainingbytes) {
1179 file_offset_t framebytes, rightChannelOffset = 0, nextFrameOffset;
1181 int mode_l = *pSrc++, mode_r = 0;
1185 framebytes = bytesPerFrame[mode_l] + bytesPerFrame[mode_r] + 2;
1186 rightChannelOffset = bytesPerFrameNoHdr[mode_l];
1187 nextFrameOffset = rightChannelOffset + bytesPerFrameNoHdr[mode_r];
1188 if (remainingbytes < framebytes) {
1190 if (mode_l == 4 && (framesamples & 1)) {
1191 rightChannelOffset = ((framesamples + 1) * bitsPerSample[mode_l]) >> 3;
1194 rightChannelOffset = (framesamples * bitsPerSample[mode_l]) >> 3;
1199 framebytes = bytesPerFrame[mode_l] + 1;
1200 nextFrameOffset = bytesPerFrameNoHdr[mode_l];
1201 if (remainingbytes < framebytes) {
1207 if (currentframeoffset + remainingsamples >= framesamples) {
1208 if (currentframeoffset <= framesamples) {
1209 copysamples = framesamples - currentframeoffset;
1210 skipsamples = currentframeoffset;
1214 skipsamples = framesamples;
1221 copysamples = remainingsamples;
1222 skipsamples = currentframeoffset;
1223 pCkData->
SetPos(remainingbytes, RIFF::stream_backward);
1224 this->
FrameOffset = currentframeoffset + copysamples;
1226 remainingsamples -= copysamples;
1228 if (remainingbytes > framebytes) {
1229 remainingbytes -= framebytes;
1230 if (remainingsamples == 0 &&
1231 currentframeoffset + copysamples == framesamples) {
1236 pCkData->
SetPos(remainingbytes, RIFF::stream_backward);
1239 else remainingbytes = 0;
1241 currentframeoffset -= skipsamples;
1243 if (copysamples == 0) {
1248 const unsigned char*
const param_l = pSrc;
1250 if (mode_l != 2) pSrc += 12;
1253 const unsigned char*
const param_r = pSrc;
1254 if (mode_r != 2) pSrc += 12;
1256 Decompress24(mode_l, param_l, 6, pSrc, pDst24,
1258 Decompress24(mode_r, param_r, 6, pSrc + rightChannelOffset, pDst24 + 3,
1260 pDst24 += copysamples * 6;
1263 Decompress24(mode_l, param_l, 3, pSrc, pDst24,
1265 pDst24 += copysamples * 3;
1269 if (mode_l) pSrc += 4;
1273 const unsigned char*
const param_r = pSrc;
1274 if (mode_r) pSrc += 4;
1276 step = (2 - mode_l) + (2 - mode_r);
1277 Decompress16(mode_l, param_l, step, 2, pSrc, pDst, skipsamples, copysamples);
1278 Decompress16(mode_r, param_r, step, 2, pSrc + (2 - mode_l), pDst + 1,
1279 skipsamples, copysamples);
1280 pDst += copysamples << 1;
1284 Decompress16(mode_l, param_l, step, 1, pSrc, pDst, skipsamples, copysamples);
1285 pDst += copysamples;
1288 pSrc += nextFrameOffset;
1292 if (remainingsamples && remainingbytes < WorstCaseFrameSize && pCkData->GetState() == RIFF::stream_ready) {
1293 assumedsize = GuessSize(remainingsamples);
1294 pCkData->
SetPos(remainingbytes, RIFF::stream_backward);
1296 remainingbytes = pCkData->
Read(pDecompressionBuffer->
pStart, assumedsize, 1);
1297 pSrc = (
unsigned char*) pDecompressionBuffer->
pStart;
1301 this->
SamplePos += (SampleCount - remainingsamples);
1303 return (SampleCount - remainingsamples);
1334 if (pCkData->
GetPos() == 0) {
1337 if (
GetSize() < SampleCount)
throw Exception(
"Could not write sample data, current sample size to small");
1342 res =
Channels == 2 ? pCkData->
Write(pBuffer, SampleCount << 1, 2) >> 1
1343 : pCkData->
Write(pBuffer, SampleCount, 2);
1345 __calculateCRC((
unsigned char *)pBuffer, SampleCount *
FrameSize, crc);
1351 File* pFile =
static_cast<File*
>(GetParent());
1375 const double worstCaseHeaderOverhead =
1376 (256.0 + 12.0 + 2.0 ) / 256.0;
1377 result.
Size = (file_offset_t) (
double(MaxReadSize) * 3.0 * 2.0 * worstCaseHeaderOverhead);
1391 if (DecompressionBuffer.
Size && DecompressionBuffer.
pStart) {
1392 delete[] (int8_t*) DecompressionBuffer.
pStart;
1393 DecompressionBuffer.
pStart = NULL;
1394 DecompressionBuffer.
Size = 0;
1454 uint32_t crc = CalculateWaveDataChecksum();
1455 if (pActually) *pActually =
crc;
1456 return crc == this->
crc;
1459 uint32_t Sample::CalculateWaveDataChecksum() {
1460 const size_t sz = 20*1024;
1461 std::vector<uint8_t> buffer(sz);
1469 file_offset_t nRead =
Read(&buffer[0], n);
1470 if (nRead <= 0)
break;
1471 __calculateCRC(&buffer[0], nRead *
FrameSize, crc);
1493 size_t DimensionRegion::Instances = 0;
1494 DimensionRegion::VelocityTableMap* DimensionRegion::pVelocityTables = NULL;
1496 DimensionRegion::DimensionRegion(
Region* pParent,
RIFF::List* _3ewl) :
DLS::Sampler(_3ewl) {
1502 if (_3ewl->
GetSubChunk(CHUNK_ID_WSMP)) memcpy(&Crossfade, &SamplerOptions, 4);
1503 else memset(&Crossfade, 0, 4);
1505 if (!pVelocityTables) pVelocityTables =
new VelocityTableMap;
1512 LFO3Frequency = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1513 EG3Attack = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1522 EG1Attack = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1523 EG1Decay1 = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1526 EG1Release = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1527 EG1Controller = DecodeLeverageController(static_cast<_lev_ctrl_t>(_3ewa->
ReadUint8()));
1528 uint8_t eg1ctrloptions = _3ewa->
ReadUint8();
1529 EG1ControllerInvert = eg1ctrloptions & 0x01;
1530 EG1ControllerAttackInfluence = GIG_EG_CTR_ATTACK_INFLUENCE_EXTRACT(eg1ctrloptions);
1531 EG1ControllerDecayInfluence = GIG_EG_CTR_DECAY_INFLUENCE_EXTRACT(eg1ctrloptions);
1532 EG1ControllerReleaseInfluence = GIG_EG_CTR_RELEASE_INFLUENCE_EXTRACT(eg1ctrloptions);
1533 EG2Controller = DecodeLeverageController(static_cast<_lev_ctrl_t>(_3ewa->
ReadUint8()));
1534 uint8_t eg2ctrloptions = _3ewa->
ReadUint8();
1535 EG2ControllerInvert = eg2ctrloptions & 0x01;
1536 EG2ControllerAttackInfluence = GIG_EG_CTR_ATTACK_INFLUENCE_EXTRACT(eg2ctrloptions);
1537 EG2ControllerDecayInfluence = GIG_EG_CTR_DECAY_INFLUENCE_EXTRACT(eg2ctrloptions);
1538 EG2ControllerReleaseInfluence = GIG_EG_CTR_RELEASE_INFLUENCE_EXTRACT(eg2ctrloptions);
1539 LFO1Frequency = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1540 EG2Attack = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1541 EG2Decay1 = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1544 EG2Release = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1547 LFO2Frequency = (double) GIG_EXP_DECODE(_3ewa->
ReadInt32());
1551 EG1Decay2 = (double) GIG_EXP_DECODE(eg1decay2);
1552 EG1InfiniteSustain = (eg1decay2 == 0x7fffffff);
1556 EG2Decay2 = (double) GIG_EXP_DECODE(eg2decay2);
1557 EG2InfiniteSustain = (eg2decay2 == 0x7fffffff);
1560 uint8_t velocityresponse = _3ewa->
ReadUint8();
1561 if (velocityresponse < 5) {
1563 VelocityResponseDepth = velocityresponse;
1564 }
else if (velocityresponse < 10) {
1566 VelocityResponseDepth = velocityresponse - 5;
1567 }
else if (velocityresponse < 15) {
1569 VelocityResponseDepth = velocityresponse - 10;
1572 VelocityResponseDepth = 0;
1574 uint8_t releasevelocityresponse = _3ewa->
ReadUint8();
1575 if (releasevelocityresponse < 5) {
1577 ReleaseVelocityResponseDepth = releasevelocityresponse;
1578 }
else if (releasevelocityresponse < 10) {
1580 ReleaseVelocityResponseDepth = releasevelocityresponse - 5;
1581 }
else if (releasevelocityresponse < 15) {
1583 ReleaseVelocityResponseDepth = releasevelocityresponse - 10;
1586 ReleaseVelocityResponseDepth = 0;
1588 VelocityResponseCurveScaling = _3ewa->
ReadUint8();
1589 AttenuationControllerThreshold = _3ewa->
ReadInt8();
1591 SampleStartOffset = (uint16_t) _3ewa->
ReadInt16();
1593 uint8_t pitchTrackDimensionBypass = _3ewa->
ReadInt8();
1594 PitchTrack = GIG_PITCH_TRACK_EXTRACT(pitchTrackDimensionBypass);
1599 Pan = (pan < 64) ? pan : -((
int)pan - 63);
1600 SelfMask = _3ewa->
ReadInt8() & 0x01;
1603 LFO3Controller =
static_cast<lfo3_ctrl_t>(lfo3ctrl & 0x07);
1604 LFO3Sync = lfo3ctrl & 0x20;
1605 InvertAttenuationController = lfo3ctrl & 0x80;
1606 AttenuationController = DecodeLeverageController(static_cast<_lev_ctrl_t>(_3ewa->
ReadUint8()));
1608 LFO2Controller =
static_cast<lfo2_ctrl_t>(lfo2ctrl & 0x07);
1609 LFO2FlipPhase = lfo2ctrl & 0x80;
1610 LFO2Sync = lfo2ctrl & 0x20;
1611 bool extResonanceCtrl = lfo2ctrl & 0x40;
1613 LFO1Controller =
static_cast<lfo1_ctrl_t>(lfo1ctrl & 0x07);
1614 LFO1FlipPhase = lfo1ctrl & 0x80;
1615 LFO1Sync = lfo1ctrl & 0x40;
1616 VCFResonanceController = (extResonanceCtrl) ? static_cast<vcf_res_ctrl_t>(GIG_VCF_RESONANCE_CTRL_EXTRACT(lfo1ctrl))
1619 EG3Depth = (eg3depth <= 1200) ? eg3depth
1620 : (-1) * (int16_t) ((eg3depth ^ 0xfff) + 1);
1623 uint8_t regoptions = _3ewa->
ReadUint8();
1624 MSDecode = regoptions & 0x01;
1625 SustainDefeat = regoptions & 0x02;
1627 VelocityUpperLimit = _3ewa->
ReadInt8();
1630 ReleaseTriggerDecay = _3ewa->
ReadUint8();
1635 VCFEnabled = vcfcutoff & 0x80;
1636 VCFCutoff = vcfcutoff & 0x7f;
1638 uint8_t vcfvelscale = _3ewa->
ReadUint8();
1639 VCFCutoffControllerInvert = vcfvelscale & 0x80;
1640 VCFVelocityScale = vcfvelscale & 0x7f;
1642 uint8_t vcfresonance = _3ewa->
ReadUint8();
1643 VCFResonance = vcfresonance & 0x7f;
1644 VCFResonanceDynamic = !(vcfresonance & 0x80);
1645 uint8_t vcfbreakpoint = _3ewa->
ReadUint8();
1646 VCFKeyboardTracking = vcfbreakpoint & 0x80;
1647 VCFKeyboardTrackingBreakpoint = vcfbreakpoint & 0x7f;
1648 uint8_t vcfvelocity = _3ewa->
ReadUint8();
1649 VCFVelocityDynamicRange = vcfvelocity % 5;
1650 VCFVelocityCurve =
static_cast<curve_type_t>(vcfvelocity / 5);
1653 if (lfo3ctrl & 0x40)
1657 _3ewa->
Read(DimensionUpperLimits, 1, 8);
1659 memset(DimensionUpperLimits, 0, 8);
1663 LFO3Frequency = 1.0;
1665 LFO1InternalDepth = 0;
1666 LFO3InternalDepth = 0;
1667 LFO1ControlDepth = 0;
1668 LFO3ControlDepth = 0;
1674 EG1Controller.controller_number = 0;
1675 EG1ControllerInvert =
false;
1676 EG1ControllerAttackInfluence = 0;
1677 EG1ControllerDecayInfluence = 0;
1678 EG1ControllerReleaseInfluence = 0;
1680 EG2Controller.controller_number = 0;
1681 EG2ControllerInvert =
false;
1682 EG2ControllerAttackInfluence = 0;
1683 EG2ControllerDecayInfluence = 0;
1684 EG2ControllerReleaseInfluence = 0;
1685 LFO1Frequency = 1.0;
1690 LFO2ControlDepth = 0;
1691 LFO2Frequency = 1.0;
1692 LFO2InternalDepth = 0;
1694 EG1InfiniteSustain =
true;
1697 EG2InfiniteSustain =
true;
1700 VelocityResponseDepth = 3;
1702 ReleaseVelocityResponseDepth = 3;
1703 VelocityResponseCurveScaling = 32;
1704 AttenuationControllerThreshold = 0;
1705 SampleStartOffset = 0;
1712 InvertAttenuationController =
false;
1714 AttenuationController.controller_number = 0;
1716 LFO2FlipPhase =
false;
1719 LFO1FlipPhase =
false;
1725 SustainDefeat =
false;
1726 VelocityUpperLimit = 0;
1727 ReleaseTriggerDecay = 0;
1732 VCFCutoffControllerInvert =
false;
1733 VCFVelocityScale = 0;
1735 VCFResonanceDynamic =
false;
1736 VCFKeyboardTracking =
false;
1737 VCFKeyboardTrackingBreakpoint = 0;
1738 VCFVelocityDynamicRange = 0x04;
1741 memset(DimensionUpperLimits, 127, 8);
1749 eg_opt_t* pEGOpts[2] = { &EG1Options, &EG2Options };
1750 for (
int i = 0; i < 2; ++i) {
1760 if (lsde && lsde->
GetSize() > 3) {
1763 SustainReleaseTrigger =
static_cast<sust_rel_trg_t>(byte & 0x03);
1764 NoNoteOffReleaseTrigger = byte >> 7;
1767 NoNoteOffReleaseTrigger =
false;
1771 if (lsde && lsde->
GetSize() > 4) {
1777 LFO1Phase = (double) GIG_EXP_DECODE( lsde->
ReadInt32() );
1778 LFO2Phase = (double) GIG_EXP_DECODE( lsde->
ReadInt32() );
1779 LFO3Phase = (double) GIG_EXP_DECODE( lsde->
ReadInt32() );
1780 const uint32_t flags = lsde->
ReadInt32();
1781 LFO3FlipPhase = flags & 1;
1789 LFO3FlipPhase =
false;
1792 pVelocityAttenuationTable = GetVelocityTable(VelocityResponseCurve,
1793 VelocityResponseDepth,
1794 VelocityResponseCurveScaling);
1796 pVelocityReleaseTable = GetReleaseVelocityTable(
1797 ReleaseVelocityResponseCurve,
1798 ReleaseVelocityResponseDepth
1801 pVelocityCutoffTable = GetCutoffVelocityTable(VCFVelocityCurve,
1802 VCFVelocityDynamicRange,
1804 VCFCutoffController);
1806 SampleAttenuation = pow(10.0, -Gain / (20.0 * 655360));
1818 pParentList = _3ewl;
1822 VelocityTable =
new uint8_t[128];
1823 for (
int k = 0 ; k < 128 ; k++)
1856 if (VelocityTable)
delete [] VelocityTable;
1857 if (pSampleLoops)
delete [] pSampleLoops;
1871 pRegion = pOriginalRegion;
1875 if (pOriginalRegion->GetParent()->GetParent() != orig->pRegion->GetParent()->GetParent()) {
1876 pSample = pOriginalSample;
1879 if (mSamples && mSamples->count(orig->
pSample)) {
1880 pSample = mSamples->find(orig->
pSample)->second;
1885 VelocityTable =
new uint8_t[128];
1886 for (
int k = 0 ; k < 128 ; k++)
1902 SRLZ(VelocityUpperLimit);
1907 SRLZ(EG1InfiniteSustain);
1911 SRLZ(EG1Controller);
1912 SRLZ(EG1ControllerInvert);
1913 SRLZ(EG1ControllerAttackInfluence);
1914 SRLZ(EG1ControllerDecayInfluence);
1915 SRLZ(EG1ControllerReleaseInfluence);
1917 SRLZ(LFO1Frequency);
1919 SRLZ(LFO1InternalDepth);
1920 SRLZ(LFO1ControlDepth);
1921 SRLZ(LFO1Controller);
1922 SRLZ(LFO1FlipPhase);
1928 SRLZ(EG2InfiniteSustain);
1931 SRLZ(EG2Controller);
1932 SRLZ(EG2ControllerInvert);
1933 SRLZ(EG2ControllerAttackInfluence);
1934 SRLZ(EG2ControllerDecayInfluence);
1935 SRLZ(EG2ControllerReleaseInfluence);
1937 SRLZ(LFO2Frequency);
1939 SRLZ(LFO2InternalDepth);
1940 SRLZ(LFO2ControlDepth);
1941 SRLZ(LFO2Controller);
1942 SRLZ(LFO2FlipPhase);
1947 SRLZ(LFO3Frequency);
1949 SRLZ(LFO3InternalDepth);
1950 SRLZ(LFO3ControlDepth);
1951 SRLZ(LFO3Controller);
1952 SRLZ(LFO3FlipPhase);
1956 SRLZ(VCFCutoffController);
1957 SRLZ(VCFCutoffControllerInvert);
1959 SRLZ(VCFVelocityCurve);
1960 SRLZ(VCFVelocityScale);
1961 SRLZ(VCFVelocityDynamicRange);
1963 SRLZ(VCFResonanceDynamic);
1964 SRLZ(VCFResonanceController);
1965 SRLZ(VCFKeyboardTracking);
1966 SRLZ(VCFKeyboardTrackingBreakpoint);
1967 SRLZ(VelocityResponseCurve);
1968 SRLZ(VelocityResponseDepth);
1969 SRLZ(VelocityResponseCurveScaling);
1970 SRLZ(ReleaseVelocityResponseCurve);
1971 SRLZ(ReleaseVelocityResponseDepth);
1972 SRLZ(ReleaseTriggerDecay);
1975 SRLZ(DimensionBypass);
1978 SRLZ(AttenuationController);
1979 SRLZ(InvertAttenuationController);
1980 SRLZ(AttenuationControllerThreshold);
1981 SRLZ(ChannelOffset);
1982 SRLZ(SustainDefeat);
1985 SRLZ(SampleAttenuation);
1988 SRLZ(SustainReleaseTrigger);
1989 SRLZ(NoNoteOffReleaseTrigger);
2001 DLS::Sampler::SetGain(gain);
2002 SampleAttenuation = pow(10.0, -Gain / (20.0 * 655360));
2018 RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);
2020 pData[12] = Crossfade.in_start;
2021 pData[13] = Crossfade.in_end;
2022 pData[14] = Crossfade.out_start;
2023 pData[15] = Crossfade.out_end;
2026 RIFF::Chunk* _3ewa = pParentList->GetSubChunk(CHUNK_ID_3EWA);
2028 File* pFile = (
File*) GetParent()->GetParent()->GetParent();
2030 _3ewa = pParentList->AddSubChunk(CHUNK_ID_3EWA, versiongt2 ? 148 : 140);
2036 const uint32_t chunksize = (uint32_t) _3ewa->
GetNewSize();
2037 store32(&pData[0], chunksize);
2039 const int32_t lfo3freq = (int32_t) GIG_EXP_ENCODE(LFO3Frequency);
2040 store32(&pData[4], lfo3freq);
2042 const int32_t eg3attack = (int32_t) GIG_EXP_ENCODE(EG3Attack);
2043 store32(&pData[8], eg3attack);
2047 store16(&pData[14], LFO1InternalDepth);
2051 store16(&pData[18], LFO3InternalDepth);
2055 store16(&pData[22], LFO1ControlDepth);
2059 store16(&pData[26], LFO3ControlDepth);
2061 const int32_t eg1attack = (int32_t) GIG_EXP_ENCODE(EG1Attack);
2062 store32(&pData[28], eg1attack);
2064 const int32_t eg1decay1 = (int32_t) GIG_EXP_ENCODE(EG1Decay1);
2065 store32(&pData[32], eg1decay1);
2069 store16(&pData[38], EG1Sustain);
2071 const int32_t eg1release = (int32_t) GIG_EXP_ENCODE(EG1Release);
2072 store32(&pData[40], eg1release);
2074 const uint8_t eg1ctl = (uint8_t) EncodeLeverageController(EG1Controller);
2077 const uint8_t eg1ctrloptions =
2078 (EG1ControllerInvert ? 0x01 : 0x00) |
2079 GIG_EG_CTR_ATTACK_INFLUENCE_ENCODE(EG1ControllerAttackInfluence) |
2080 GIG_EG_CTR_DECAY_INFLUENCE_ENCODE(EG1ControllerDecayInfluence) |
2081 GIG_EG_CTR_RELEASE_INFLUENCE_ENCODE(EG1ControllerReleaseInfluence);
2082 pData[45] = eg1ctrloptions;
2084 const uint8_t eg2ctl = (uint8_t) EncodeLeverageController(EG2Controller);
2087 const uint8_t eg2ctrloptions =
2088 (EG2ControllerInvert ? 0x01 : 0x00) |
2089 GIG_EG_CTR_ATTACK_INFLUENCE_ENCODE(EG2ControllerAttackInfluence) |
2090 GIG_EG_CTR_DECAY_INFLUENCE_ENCODE(EG2ControllerDecayInfluence) |
2091 GIG_EG_CTR_RELEASE_INFLUENCE_ENCODE(EG2ControllerReleaseInfluence);
2092 pData[47] = eg2ctrloptions;
2094 const int32_t lfo1freq = (int32_t) GIG_EXP_ENCODE(LFO1Frequency);
2095 store32(&pData[48], lfo1freq);
2097 const int32_t eg2attack = (int32_t) GIG_EXP_ENCODE(EG2Attack);
2098 store32(&pData[52], eg2attack);
2100 const int32_t eg2decay1 = (int32_t) GIG_EXP_ENCODE(EG2Decay1);
2101 store32(&pData[56], eg2decay1);
2105 store16(&pData[62], EG2Sustain);
2107 const int32_t eg2release = (int32_t) GIG_EXP_ENCODE(EG2Release);
2108 store32(&pData[64], eg2release);
2112 store16(&pData[70], LFO2ControlDepth);
2114 const int32_t lfo2freq = (int32_t) GIG_EXP_ENCODE(LFO2Frequency);
2115 store32(&pData[72], lfo2freq);
2119 store16(&pData[78], LFO2InternalDepth);
2121 const int32_t eg1decay2 = (int32_t) (EG1InfiniteSustain) ? 0x7fffffff : (int32_t) GIG_EXP_ENCODE(EG1Decay2);
2122 store32(&pData[80], eg1decay2);
2126 store16(&pData[86], EG1PreAttack);
2128 const int32_t eg2decay2 = (int32_t) (EG2InfiniteSustain) ? 0x7fffffff : (int32_t) GIG_EXP_ENCODE(EG2Decay2);
2129 store32(&pData[88], eg2decay2);
2133 store16(&pData[94], EG2PreAttack);
2136 if (VelocityResponseDepth > 4)
throw Exception(
"VelocityResponseDepth must be between 0 and 4");
2137 uint8_t velocityresponse = VelocityResponseDepth;
2138 switch (VelocityResponseCurve) {
2142 velocityresponse += 5;
2145 velocityresponse += 10;
2149 throw Exception(
"Could not update DimensionRegion's chunk, unknown VelocityResponseCurve selected");
2151 pData[96] = velocityresponse;
2155 if (ReleaseVelocityResponseDepth > 4)
throw Exception(
"ReleaseVelocityResponseDepth must be between 0 and 4");
2156 uint8_t releasevelocityresponse = ReleaseVelocityResponseDepth;
2157 switch (ReleaseVelocityResponseCurve) {
2161 releasevelocityresponse += 5;
2164 releasevelocityresponse += 10;
2168 throw Exception(
"Could not update DimensionRegion's chunk, unknown ReleaseVelocityResponseCurve selected");
2170 pData[97] = releasevelocityresponse;
2173 pData[98] = VelocityResponseCurveScaling;
2175 pData[99] = AttenuationControllerThreshold;
2179 store16(&pData[104], SampleStartOffset);
2184 uint8_t pitchTrackDimensionBypass = GIG_PITCH_TRACK_ENCODE(PitchTrack);
2185 switch (DimensionBypass) {
2187 pitchTrackDimensionBypass |= 0x10;
2190 pitchTrackDimensionBypass |= 0x20;
2196 throw Exception(
"Could not update DimensionRegion's chunk, unknown DimensionBypass selected");
2198 pData[108] = pitchTrackDimensionBypass;
2201 const uint8_t pan = (Pan >= 0) ? Pan : ((-Pan) + 63);
2204 const uint8_t selfmask = (SelfMask) ? 0x01 : 0x00;
2205 pData[110] = selfmask;
2210 uint8_t lfo3ctrl = LFO3Controller & 0x07;
2211 if (LFO3Sync) lfo3ctrl |= 0x20;
2212 if (InvertAttenuationController) lfo3ctrl |= 0x80;
2214 pData[112] = lfo3ctrl;
2217 const uint8_t attenctl = EncodeLeverageController(AttenuationController);
2218 pData[113] = attenctl;
2221 uint8_t lfo2ctrl = LFO2Controller & 0x07;
2222 if (LFO2FlipPhase) lfo2ctrl |= 0x80;
2223 if (LFO2Sync) lfo2ctrl |= 0x20;
2225 pData[114] = lfo2ctrl;
2229 uint8_t lfo1ctrl = LFO1Controller & 0x07;
2230 if (LFO1FlipPhase) lfo1ctrl |= 0x80;
2231 if (LFO1Sync) lfo1ctrl |= 0x40;
2233 lfo1ctrl |= GIG_VCF_RESONANCE_CTRL_ENCODE(VCFResonanceController);
2234 pData[115] = lfo1ctrl;
2237 const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth
2238 : uint16_t(((-EG3Depth) - 1) ^ 0xfff);
2239 store16(&pData[116], eg3depth);
2243 const uint8_t channeloffset = ChannelOffset * 4;
2244 pData[120] = channeloffset;
2247 uint8_t regoptions = 0;
2248 if (MSDecode) regoptions |= 0x01;
2249 if (SustainDefeat) regoptions |= 0x02;
2250 pData[121] = regoptions;
2255 pData[124] = VelocityUpperLimit;
2259 pData[128] = ReleaseTriggerDecay;
2263 const uint8_t eg1hold = (EG1Hold) ? 0x80 : 0x00;
2264 pData[131] = eg1hold;
2266 const uint8_t vcfcutoff = (VCFEnabled ? 0x80 : 0x00) |
2268 pData[132] = vcfcutoff;
2270 pData[133] = VCFCutoffController;
2272 const uint8_t vcfvelscale = (VCFCutoffControllerInvert ? 0x80 : 0x00) |
2273 (VCFVelocityScale & 0x7f);
2274 pData[134] = vcfvelscale;
2278 const uint8_t vcfresonance = (VCFResonanceDynamic ? 0x00 : 0x80) |
2279 (VCFResonance & 0x7f);
2280 pData[136] = vcfresonance;
2282 const uint8_t vcfbreakpoint = (VCFKeyboardTracking ? 0x80 : 0x00) |
2283 (VCFKeyboardTrackingBreakpoint & 0x7f);
2284 pData[137] = vcfbreakpoint;
2286 const uint8_t vcfvelocity = VCFVelocityDynamicRange % 5 +
2287 VCFVelocityCurve * 5;
2288 pData[138] = vcfvelocity;
2291 pData[139] = vcftype;
2293 if (chunksize >= 148) {
2294 memcpy(&pData[140], DimensionUpperLimits, 8);
2299 RIFF::Chunk* lsde = pParentList->GetSubChunk(CHUNK_ID_LSDE);
2300 const int lsdeSize =
2304 if (!lsde && UsesAnyGigFormatExtension()) {
2308 lsde = pParentList->AddSubChunk(CHUNK_ID_LSDE, lsdeSize);
2310 pParentList->MoveSubChunk(lsde, (
RIFF::Chunk*)NULL);
2316 unsigned char* pData = (
unsigned char*) lsde->
LoadChunkData();
2317 eg_opt_t* pEGOpts[2] = { &EG1Options, &EG2Options };
2318 for (
int i = 0; i < 2; ++i) {
2321 (pEGOpts[i]->AttackHoldCancel ? (1<<1) : 0) |
2322 (pEGOpts[i]->Decay1Cancel ? (1<<2) : 0) |
2323 (pEGOpts[i]->Decay2Cancel ? (1<<3) : 0) |
2324 (pEGOpts[i]->ReleaseCancel ? (1<<4) : 0);
2327 pData[3] =
static_cast<uint8_t
>(SustainReleaseTrigger) | (NoNoteOffReleaseTrigger ? (1<<7) : 0);
2330 store16(&pData[4], LFO1WaveForm);
2331 store16(&pData[6], LFO2WaveForm);
2332 store16(&pData[8], LFO3WaveForm);
2334 const int32_t lfo1Phase = (int32_t) GIG_EXP_ENCODE(LFO1Phase);
2335 const int32_t lfo2Phase = (int32_t) GIG_EXP_ENCODE(LFO2Phase);
2336 const int32_t lfo3Phase = (int32_t) GIG_EXP_ENCODE(LFO3Phase);
2337 store32(&pData[12], lfo1Phase);
2338 store32(&pData[16], lfo2Phase);
2339 store32(&pData[20], lfo3Phase);
2340 const int32_t flags = LFO3FlipPhase ? 1 : 0;
2341 store32(&pData[24], flags);
2345 static_assert(lsdeSize == 28,
"Inconsistency in assumed 'LSDE' RIFF chunk size");
2364 bool DimensionRegion::UsesAnyGigFormatExtension()
const {
2366 return memcmp(&EG1Options, &defaultOpt,
sizeof(
eg_opt_t)) ||
2367 memcmp(&EG2Options, &defaultOpt,
sizeof(
eg_opt_t)) ||
2368 SustainReleaseTrigger || NoNoteOffReleaseTrigger ||
2369 LFO1WaveForm || LFO2WaveForm || LFO3WaveForm ||
2370 LFO1Phase || LFO2Phase || LFO3Phase ||
2374 double* DimensionRegion::GetReleaseVelocityTable(
curve_type_t releaseVelocityResponseCurve, uint8_t releaseVelocityResponseDepth) {
2376 uint8_t depth = releaseVelocityResponseDepth;
2385 return GetVelocityTable(curveType, depth, 0);
2388 double* DimensionRegion::GetCutoffVelocityTable(
curve_type_t vcfVelocityCurve,
2389 uint8_t vcfVelocityDynamicRange,
2390 uint8_t vcfVelocityScale,
2394 uint8_t depth = vcfVelocityDynamicRange;
2403 return GetVelocityTable(curveType, depth,
2405 ? vcfVelocityScale : 0);
2409 double* DimensionRegion::GetVelocityTable(
curve_type_t curveType, uint8_t depth, uint8_t scaling)
2413 switch (curveType) {
2417 printf(
"Warning: Invalid depth (0x%x) for velocity curve type (0x%x).\n", depth, curveType);
2424 printf(
"Warning: Invalid depth (0x%x) for velocity curve type 'special'.\n", depth);
2431 printf(
"Warning: Unknown velocity curve type (0x%x).\n", curveType);
2439 uint32_t tableKey = (curveType<<16) | (depth<<8) | scaling;
2440 if (pVelocityTables->count(tableKey)) {
2441 table = (*pVelocityTables)[tableKey];
2444 table = CreateVelocityTable(curveType, depth, scaling);
2445 (*pVelocityTables)[tableKey] = table;
2450 Region* DimensionRegion::GetParent()
const {
2460 leverage_ctrl_t DimensionRegion::DecodeLeverageController(_lev_ctrl_t EncodedController) {
2462 switch (EncodedController) {
2464 case _lev_ctrl_none:
2468 case _lev_ctrl_velocity:
2472 case _lev_ctrl_channelaftertouch:
2478 case _lev_ctrl_modwheel:
2482 case _lev_ctrl_breath:
2486 case _lev_ctrl_foot:
2490 case _lev_ctrl_effect1:
2494 case _lev_ctrl_effect2:
2498 case _lev_ctrl_genpurpose1:
2502 case _lev_ctrl_genpurpose2:
2506 case _lev_ctrl_genpurpose3:
2510 case _lev_ctrl_genpurpose4:
2514 case _lev_ctrl_portamentotime:
2518 case _lev_ctrl_sustainpedal:
2522 case _lev_ctrl_portamento:
2526 case _lev_ctrl_sostenutopedal:
2530 case _lev_ctrl_softpedal:
2534 case _lev_ctrl_genpurpose5:
2538 case _lev_ctrl_genpurpose6:
2542 case _lev_ctrl_genpurpose7:
2546 case _lev_ctrl_genpurpose8:
2550 case _lev_ctrl_effect1depth:
2554 case _lev_ctrl_effect2depth:
2558 case _lev_ctrl_effect3depth:
2562 case _lev_ctrl_effect4depth:
2566 case _lev_ctrl_effect5depth:
2574 case _lev_ctrl_CC3_EXT:
2578 case _lev_ctrl_CC6_EXT:
2582 case _lev_ctrl_CC7_EXT:
2586 case _lev_ctrl_CC8_EXT:
2590 case _lev_ctrl_CC9_EXT:
2594 case _lev_ctrl_CC10_EXT:
2598 case _lev_ctrl_CC11_EXT:
2602 case _lev_ctrl_CC14_EXT:
2606 case _lev_ctrl_CC15_EXT:
2610 case _lev_ctrl_CC20_EXT:
2614 case _lev_ctrl_CC21_EXT:
2618 case _lev_ctrl_CC22_EXT:
2622 case _lev_ctrl_CC23_EXT:
2626 case _lev_ctrl_CC24_EXT:
2630 case _lev_ctrl_CC25_EXT:
2634 case _lev_ctrl_CC26_EXT:
2638 case _lev_ctrl_CC27_EXT:
2642 case _lev_ctrl_CC28_EXT:
2646 case _lev_ctrl_CC29_EXT:
2650 case _lev_ctrl_CC30_EXT:
2654 case _lev_ctrl_CC31_EXT:
2658 case _lev_ctrl_CC68_EXT:
2662 case _lev_ctrl_CC69_EXT:
2666 case _lev_ctrl_CC70_EXT:
2670 case _lev_ctrl_CC71_EXT:
2674 case _lev_ctrl_CC72_EXT:
2678 case _lev_ctrl_CC73_EXT:
2682 case _lev_ctrl_CC74_EXT:
2686 case _lev_ctrl_CC75_EXT:
2690 case _lev_ctrl_CC76_EXT:
2694 case _lev_ctrl_CC77_EXT:
2698 case _lev_ctrl_CC78_EXT:
2702 case _lev_ctrl_CC79_EXT:
2706 case _lev_ctrl_CC84_EXT:
2710 case _lev_ctrl_CC85_EXT:
2714 case _lev_ctrl_CC86_EXT:
2718 case _lev_ctrl_CC87_EXT:
2722 case _lev_ctrl_CC89_EXT:
2726 case _lev_ctrl_CC90_EXT:
2730 case _lev_ctrl_CC96_EXT:
2734 case _lev_ctrl_CC97_EXT:
2738 case _lev_ctrl_CC102_EXT:
2742 case _lev_ctrl_CC103_EXT:
2746 case _lev_ctrl_CC104_EXT:
2750 case _lev_ctrl_CC105_EXT:
2754 case _lev_ctrl_CC106_EXT:
2758 case _lev_ctrl_CC107_EXT:
2762 case _lev_ctrl_CC108_EXT:
2766 case _lev_ctrl_CC109_EXT:
2770 case _lev_ctrl_CC110_EXT:
2774 case _lev_ctrl_CC111_EXT:
2778 case _lev_ctrl_CC112_EXT:
2782 case _lev_ctrl_CC113_EXT:
2786 case _lev_ctrl_CC114_EXT:
2790 case _lev_ctrl_CC115_EXT:
2794 case _lev_ctrl_CC116_EXT:
2798 case _lev_ctrl_CC117_EXT:
2802 case _lev_ctrl_CC118_EXT:
2806 case _lev_ctrl_CC119_EXT:
2815 printf(
"Warning: Unknown leverage controller type (0x%x).\n", EncodedController);
2818 return decodedcontroller;
2824 DimensionRegion::_lev_ctrl_t DimensionRegion::EncodeLeverageController(
leverage_ctrl_t DecodedController) {
2825 _lev_ctrl_t encodedcontroller;
2826 switch (DecodedController.
type) {
2829 encodedcontroller = _lev_ctrl_none;
2832 encodedcontroller = _lev_ctrl_velocity;
2835 encodedcontroller = _lev_ctrl_channelaftertouch;
2842 encodedcontroller = _lev_ctrl_modwheel;
2845 encodedcontroller = _lev_ctrl_breath;
2848 encodedcontroller = _lev_ctrl_foot;
2851 encodedcontroller = _lev_ctrl_effect1;
2854 encodedcontroller = _lev_ctrl_effect2;
2857 encodedcontroller = _lev_ctrl_genpurpose1;
2860 encodedcontroller = _lev_ctrl_genpurpose2;
2863 encodedcontroller = _lev_ctrl_genpurpose3;
2866 encodedcontroller = _lev_ctrl_genpurpose4;
2869 encodedcontroller = _lev_ctrl_portamentotime;
2872 encodedcontroller = _lev_ctrl_sustainpedal;
2875 encodedcontroller = _lev_ctrl_portamento;
2878 encodedcontroller = _lev_ctrl_sostenutopedal;
2881 encodedcontroller = _lev_ctrl_softpedal;
2884 encodedcontroller = _lev_ctrl_genpurpose5;
2887 encodedcontroller = _lev_ctrl_genpurpose6;
2890 encodedcontroller = _lev_ctrl_genpurpose7;
2893 encodedcontroller = _lev_ctrl_genpurpose8;
2896 encodedcontroller = _lev_ctrl_effect1depth;
2899 encodedcontroller = _lev_ctrl_effect2depth;
2902 encodedcontroller = _lev_ctrl_effect3depth;
2905 encodedcontroller = _lev_ctrl_effect4depth;
2908 encodedcontroller = _lev_ctrl_effect5depth;
2915 encodedcontroller = _lev_ctrl_CC3_EXT;
2918 encodedcontroller = _lev_ctrl_CC6_EXT;
2921 encodedcontroller = _lev_ctrl_CC7_EXT;
2924 encodedcontroller = _lev_ctrl_CC8_EXT;
2927 encodedcontroller = _lev_ctrl_CC9_EXT;
2930 encodedcontroller = _lev_ctrl_CC10_EXT;
2933 encodedcontroller = _lev_ctrl_CC11_EXT;
2936 encodedcontroller = _lev_ctrl_CC14_EXT;
2939 encodedcontroller = _lev_ctrl_CC15_EXT;
2942 encodedcontroller = _lev_ctrl_CC20_EXT;
2945 encodedcontroller = _lev_ctrl_CC21_EXT;
2948 encodedcontroller = _lev_ctrl_CC22_EXT;
2951 encodedcontroller = _lev_ctrl_CC23_EXT;
2954 encodedcontroller = _lev_ctrl_CC24_EXT;
2957 encodedcontroller = _lev_ctrl_CC25_EXT;
2960 encodedcontroller = _lev_ctrl_CC26_EXT;
2963 encodedcontroller = _lev_ctrl_CC27_EXT;
2966 encodedcontroller = _lev_ctrl_CC28_EXT;
2969 encodedcontroller = _lev_ctrl_CC29_EXT;
2972 encodedcontroller = _lev_ctrl_CC30_EXT;
2975 encodedcontroller = _lev_ctrl_CC31_EXT;
2978 encodedcontroller = _lev_ctrl_CC68_EXT;
2981 encodedcontroller = _lev_ctrl_CC69_EXT;
2984 encodedcontroller = _lev_ctrl_CC70_EXT;
2987 encodedcontroller = _lev_ctrl_CC71_EXT;
2990 encodedcontroller = _lev_ctrl_CC72_EXT;
2993 encodedcontroller = _lev_ctrl_CC73_EXT;
2996 encodedcontroller = _lev_ctrl_CC74_EXT;
2999 encodedcontroller = _lev_ctrl_CC75_EXT;
3002 encodedcontroller = _lev_ctrl_CC76_EXT;
3005 encodedcontroller = _lev_ctrl_CC77_EXT;
3008 encodedcontroller = _lev_ctrl_CC78_EXT;
3011 encodedcontroller = _lev_ctrl_CC79_EXT;
3014 encodedcontroller = _lev_ctrl_CC84_EXT;
3017 encodedcontroller = _lev_ctrl_CC85_EXT;
3020 encodedcontroller = _lev_ctrl_CC86_EXT;
3023 encodedcontroller = _lev_ctrl_CC87_EXT;
3026 encodedcontroller = _lev_ctrl_CC89_EXT;
3029 encodedcontroller = _lev_ctrl_CC90_EXT;
3032 encodedcontroller = _lev_ctrl_CC96_EXT;
3035 encodedcontroller = _lev_ctrl_CC97_EXT;
3038 encodedcontroller = _lev_ctrl_CC102_EXT;
3041 encodedcontroller = _lev_ctrl_CC103_EXT;
3044 encodedcontroller = _lev_ctrl_CC104_EXT;
3047 encodedcontroller = _lev_ctrl_CC105_EXT;
3050 encodedcontroller = _lev_ctrl_CC106_EXT;
3053 encodedcontroller = _lev_ctrl_CC107_EXT;
3056 encodedcontroller = _lev_ctrl_CC108_EXT;
3059 encodedcontroller = _lev_ctrl_CC109_EXT;
3062 encodedcontroller = _lev_ctrl_CC110_EXT;
3065 encodedcontroller = _lev_ctrl_CC111_EXT;
3068 encodedcontroller = _lev_ctrl_CC112_EXT;
3071 encodedcontroller = _lev_ctrl_CC113_EXT;
3074 encodedcontroller = _lev_ctrl_CC114_EXT;
3077 encodedcontroller = _lev_ctrl_CC115_EXT;
3080 encodedcontroller = _lev_ctrl_CC116_EXT;
3083 encodedcontroller = _lev_ctrl_CC117_EXT;
3086 encodedcontroller = _lev_ctrl_CC118_EXT;
3089 encodedcontroller = _lev_ctrl_CC119_EXT;
3093 throw gig::Exception(
"leverage controller number is not supported by the gig format");
3099 return encodedcontroller;
3102 DimensionRegion::~DimensionRegion() {
3106 VelocityTableMap::iterator iter;
3107 for (iter = pVelocityTables->begin(); iter != pVelocityTables->end(); iter++) {
3108 double* pTable = iter->second;
3109 if (pTable)
delete[] pTable;
3111 pVelocityTables->clear();
3112 delete pVelocityTables;
3113 pVelocityTables = NULL;
3115 if (VelocityTable)
delete[] VelocityTable;
3130 return pVelocityAttenuationTable[MIDIKeyVelocity];
3133 double DimensionRegion::GetVelocityRelease(uint8_t MIDIKeyVelocity) {
3134 return pVelocityReleaseTable[MIDIKeyVelocity];
3137 double DimensionRegion::GetVelocityCutoff(uint8_t MIDIKeyVelocity) {
3138 return pVelocityCutoffTable[MIDIKeyVelocity];
3146 pVelocityAttenuationTable =
3148 curve, VelocityResponseDepth, VelocityResponseCurveScaling
3150 VelocityResponseCurve = curve;
3158 pVelocityAttenuationTable =
3160 VelocityResponseCurve, depth, VelocityResponseCurveScaling
3162 VelocityResponseDepth = depth;
3170 pVelocityAttenuationTable =
3172 VelocityResponseCurve, VelocityResponseDepth, scaling
3174 VelocityResponseCurveScaling = scaling;
3182 pVelocityReleaseTable = GetReleaseVelocityTable(curve, ReleaseVelocityResponseDepth);
3183 ReleaseVelocityResponseCurve = curve;
3191 pVelocityReleaseTable = GetReleaseVelocityTable(ReleaseVelocityResponseCurve, depth);
3192 ReleaseVelocityResponseDepth = depth;
3200 pVelocityCutoffTable = GetCutoffVelocityTable(VCFVelocityCurve, VCFVelocityDynamicRange, VCFVelocityScale, controller);
3201 VCFCutoffController = controller;
3209 pVelocityCutoffTable = GetCutoffVelocityTable(curve, VCFVelocityDynamicRange, VCFVelocityScale, VCFCutoffController);
3210 VCFVelocityCurve = curve;
3218 pVelocityCutoffTable = GetCutoffVelocityTable(VCFVelocityCurve, range, VCFVelocityScale, VCFCutoffController);
3219 VCFVelocityDynamicRange = range;
3227 pVelocityCutoffTable = GetCutoffVelocityTable(VCFVelocityCurve, VCFVelocityDynamicRange, scaling, VCFCutoffController);
3228 VCFVelocityScale = scaling;
3231 double* DimensionRegion::CreateVelocityTable(
curve_type_t curveType, uint8_t depth, uint8_t scaling) {
3236 const int lin0[] = { 1, 1, 127, 127 };
3237 const int lin1[] = { 1, 21, 127, 127 };
3238 const int lin2[] = { 1, 45, 127, 127 };
3239 const int lin3[] = { 1, 74, 127, 127 };
3240 const int lin4[] = { 1, 127, 127, 127 };
3243 const int non0[] = { 1, 4, 24, 5, 57, 17, 92, 57, 122, 127, 127, 127 };
3244 const int non1[] = { 1, 4, 46, 9, 93, 56, 118, 106, 123, 127,
3246 const int non2[] = { 1, 4, 46, 9, 57, 20, 102, 107, 107, 127,
3248 const int non3[] = { 1, 15, 10, 19, 67, 73, 80, 80, 90, 98, 98, 127,
3250 const int non4[] = { 1, 25, 33, 57, 82, 81, 92, 127, 127, 127 };
3253 const int spe0[] = { 1, 2, 76, 10, 90, 15, 95, 20, 99, 28, 103, 44,
3254 113, 127, 127, 127 };
3255 const int spe1[] = { 1, 2, 27, 5, 67, 18, 89, 29, 95, 35, 107, 67,
3256 118, 127, 127, 127 };
3257 const int spe2[] = { 1, 1, 33, 1, 53, 5, 61, 13, 69, 32, 79, 74,
3258 85, 90, 91, 127, 127, 127 };
3259 const int spe3[] = { 1, 32, 28, 35, 66, 48, 89, 59, 95, 65, 99, 73,
3260 117, 127, 127, 127 };
3261 const int spe4[] = { 1, 4, 23, 5, 49, 13, 57, 17, 92, 57, 122, 127,
3265 const int spe5[] = { 1, 2, 30, 5, 60, 19, 77, 70, 83, 85, 88, 106,
3266 91, 127, 127, 127 };
3268 const int*
const curves[] = { non0, non1, non2, non3, non4,
3269 lin0, lin1, lin2, lin3, lin4,
3270 spe0, spe1, spe2, spe3, spe4, spe5 };
3272 double*
const table =
new double[128];
3274 const int* curve = curves[curveType * 5 + depth];
3275 const int s = scaling == 0 ? 20 : scaling;
3278 for (
int x = 1 ; x < 128 ; x++) {
3280 if (x > curve[2]) curve += 2;
3281 double y = curve[1] + (x - curve[0]) *
3282 (
double(curve[3] - curve[1]) / (curve[2] - curve[0]));
3287 if (s < 20 && y >= 0.5)
3288 y = y / ((2 - 40.0 / s) * y + 40.0 / s - 1);
3305 for (
int i = 0; i < 256; i++) {
3306 pDimensionRegions[i] = NULL;
3309 File* file = (
File*) GetParent()->GetParent();
3316 LoadDimensionRegions(rgnList);
3323 for (
int i = 0; i < dimensionBits; i++) {
3331 pDimensionDefinitions[i].bits = 0;
3332 pDimensionDefinitions[i].zones = 0;
3334 pDimensionDefinitions[i].zone_size = 0;
3337 pDimensionDefinitions[i].dimension = dimension;
3338 pDimensionDefinitions[i].bits = bits;
3339 pDimensionDefinitions[i].zones = zones ? zones : 0x01 << bits;
3340 pDimensionDefinitions[i].split_type = __resolveSplitType(dimension);
3341 pDimensionDefinitions[i].zone_size = __resolveZoneSize(pDimensionDefinitions[i]);
3345 if (dimension ==
dimension_layer) Layers = pDimensionDefinitions[i].zones;
3347 _3lnk->
SetPos(3, RIFF::stream_curpos);
3349 for (
int i = dimensionBits ; i < 8 ; i++) pDimensionDefinitions[i].bits = 0;
3353 UpdateVelocityTable();
3363 for (uint i = 0; i < DimensionRegions; i++) {
3364 uint32_t wavepoolindex = _3lnk->
ReadUint32();
3365 if (file->pWavePoolTable && pDimensionRegions[i])
3366 pDimensionRegions[i]->pSample = GetSampleFromWavePool(wavepoolindex);
3371 DimensionRegions = 0;
3372 for (
int i = 0 ; i < 8 ; i++) {
3374 pDimensionDefinitions[i].bits = 0;
3375 pDimensionDefinitions[i].zones = 0;
3380 if (!DimensionRegions) {
3382 if (!_3prg) _3prg = rgnList->
AddSubList(LIST_TYPE_3PRG);
3385 DimensionRegions = 1;
3404 pSample = pDimensionRegions[0]->pSample;
3410 for (
int i = 0; i < DimensionRegions; i++) {
3411 pDimensionRegions[i]->UpdateChunks(pProgress);
3414 File* pFile = (
File*) GetParent()->GetParent();
3416 const int iMaxDimensions = versiongt2 ? 8 : 5;
3417 const int iMaxDimensionRegions = versiongt2 ? 256 : 32;
3420 RIFF::Chunk* _3lnk = pCkRegion->GetSubChunk(CHUNK_ID_3LNK);
3422 const int _3lnkChunkSize = versiongt2 ? 1092 : 172;
3423 _3lnk = pCkRegion->AddSubChunk(CHUNK_ID_3LNK, _3lnkChunkSize);
3427 pCkRegion->MoveSubChunk(pCkRegion->GetSubList(LIST_TYPE_3PRG), (
RIFF::Chunk*)NULL);
3432 store32(&pData[0], DimensionRegions);
3434 for (
int i = 0; i < iMaxDimensions; i++) {
3435 pData[4 + i * 8] = (uint8_t) pDimensionDefinitions[i].dimension;
3436 pData[5 + i * 8] = pDimensionDefinitions[i].bits;
3437 pData[6 + i * 8] = pDimensionDefinitions[i].dimension ==
dimension_none ? 0 : shift;
3438 pData[7 + i * 8] = (1 << (shift + pDimensionDefinitions[i].bits)) - (1 << shift);
3439 pData[8 + i * 8] = pDimensionDefinitions[i].zones;
3442 shift += pDimensionDefinitions[i].bits;
3446 const int iWavePoolOffset = versiongt2 ? 68 : 44;
3447 for (uint i = 0; i < iMaxDimensionRegions; i++) {
3448 int iWaveIndex = -1;
3449 if (i < DimensionRegions) {
3450 if (!pFile->pSamples || !pFile->pSamples->size())
throw gig::Exception(
"Could not update gig::Region, there are no samples");
3451 File::SampleList::iterator iter = pFile->pSamples->begin();
3452 File::SampleList::iterator end = pFile->pSamples->end();
3453 for (
int index = 0; iter != end; ++iter, ++index) {
3454 if (*iter == pDimensionRegions[i]->pSample) {
3460 store32(&pData[iWavePoolOffset + i * 4], iWaveIndex);
3470 if (versiongt2 && !UsesAnyGigFormatExtension()) {
3473 if (!_3dnm) _3dnm = pCkRegion->
AddSubList(LIST_TYPE_3DNM);
3476 RIFF::Chunk* _3ddp = pCkRegion->GetSubChunk(CHUNK_ID_3DDP);
3477 if (!_3ddp) _3ddp = pCkRegion->AddSubChunk(CHUNK_ID_3DDP, 16);
3479 for (
int i = 0; i < 16; i += 4) {
3480 store32(&pData[i], 0xFFFFFFFF);
3484 pCkRegion->MoveSubChunk(pCkRegion->GetSubList(LIST_TYPE_3DNM), (
RIFF::Chunk*)NULL);
3485 pCkRegion->MoveSubChunk(pCkRegion->GetSubChunk(CHUNK_ID_3DDP), (
RIFF::Chunk*)NULL);
3492 RIFF::Chunk* _3ddp = pCkRegion->GetSubChunk(CHUNK_ID_3DDP);
3493 if (_3ddp) pCkRegion->DeleteSubChunk(_3ddp);
3497 void Region::LoadDimensionRegions(
RIFF::List* rgn) {
3500 int dimensionRegionNr = 0;
3506 pDimensionRegions[dimensionRegionNr] =
new DimensionRegion(
this, _3ewl);
3507 dimensionRegionNr++;
3510 if (dimensionRegionNr == 0)
throw gig::Exception(
"No dimension region found.");
3521 void Region::UpdateVelocityTable() {
3524 for (
int i = 0 ; i < Dimensions ; i++) {
3530 if (veldim == -1)
return;
3533 for (
int i = 0 ; i < veldim ; i++) step <<= pDimensionDefinitions[i].bits;
3534 int skipveldim = (step << pDimensionDefinitions[veldim].bits) - step;
3538 for (
int i = 0 ; i < DimensionRegions ; i++) {
3539 const int end = i + step * pDimensionDefinitions[veldim].zones;
3542 if (pDimensionRegions[i]->DimensionUpperLimits[veldim] ||
3543 pDimensionRegions[i]->VelocityUpperLimit) {
3545 uint8_t* table = pDimensionRegions[i]->VelocityTable;
3547 table =
new uint8_t[128];
3548 pDimensionRegions[i]->VelocityTable = table;
3551 int velocityZone = 0;
3552 if (pDimensionRegions[i]->DimensionUpperLimits[veldim]) {
3553 for (
int k = i ; k < end ; k += step) {
3555 for (; tableidx <= d->
DimensionUpperLimits[veldim] ; tableidx++) table[tableidx] = velocityZone;
3559 for (
int k = i ; k < end ; k += step) {
3561 for (; tableidx <= d->
VelocityUpperLimit ; tableidx++) table[tableidx] = velocityZone;
3566 if (pDimensionRegions[i]->VelocityTable) {
3568 pDimensionRegions[i]->VelocityTable = 0;
3575 for (j = 0 ; j < Dimensions ; j++) {
3576 if (j == veldim) i += skipveldim;
3579 if (dim[j] < pDimensionDefinitions[j].zones)
break;
3583 i += ((1 << pDimensionDefinitions[j].bits) -
3584 pDimensionDefinitions[j].zones) << shift;
3587 shift += pDimensionDefinitions[j].bits;
3589 if (j == Dimensions)
break;
3610 if (pDimDef->
zones < 2)
3611 throw gig::Exception(
"Could not add new dimension, amount of requested zones must always be at least two");
3612 if (pDimDef->
bits < 1)
3613 throw gig::Exception(
"Could not add new dimension, amount of requested requested zone bits must always be at least one");
3615 if (pDimDef->
zones != 2)
3616 throw gig::Exception(
"Could not add new 'sample channel' dimensions, the requested amount of zones must always be 2 for this dimension type");
3617 if (pDimDef->
bits != 1)
3618 throw gig::Exception(
"Could not add new 'sample channel' dimensions, the requested amount of zone bits must always be 1 for this dimension type");
3622 File* file = (
File*) GetParent()->GetParent();
3623 const int iMaxDimensions = (file->
pVersion && file->
pVersion->major > 2) ? 8 : 5;
3624 if (Dimensions >= iMaxDimensions)
3625 throw gig::Exception(
"Could not add new dimension, max. amount of " + ToString(iMaxDimensions) +
" dimensions already reached");
3627 int iCurrentBits = 0;
3628 for (
int i = 0; i < Dimensions; i++)
3629 iCurrentBits += pDimensionDefinitions[i].bits;
3630 if (iCurrentBits >= iMaxDimensions)
3631 throw gig::Exception(
"Could not add new dimension, max. amount of " + ToString(iMaxDimensions) +
" dimension bits already reached");
3632 const int iNewBits = iCurrentBits + pDimDef->
bits;
3633 if (iNewBits > iMaxDimensions)
3634 throw gig::Exception(
"Could not add new dimension, new dimension would exceed max. amount of " + ToString(iMaxDimensions) +
" dimension bits");
3636 for (
int i = 0; i < Dimensions; i++)
3637 if (pDimensionDefinitions[i].dimension == pDimDef->
dimension)
3638 throw gig::Exception(
"Could not add new dimension, there is already a dimension of the same type");
3645 for (
int i = 0 ; i < pos ; i++)
3646 bitpos += pDimensionDefinitions[i].bits;
3649 for (
int i = Dimensions ; i > pos ; i--) pDimensionDefinitions[i] = pDimensionDefinitions[i - 1];
3650 for (
int i = 0 ; i < (1 << iCurrentBits) ; i++) {
3651 for (
int j = Dimensions ; j > pos ; j--) {
3652 pDimensionRegions[i]->DimensionUpperLimits[j] =
3653 pDimensionRegions[i]->DimensionUpperLimits[j - 1];
3658 pDimensionDefinitions[pos] = *pDimDef;
3662 __resolveSplitType(pDimensionDefinitions[pos].dimension);
3663 pDimensionDefinitions[pos].zone_size =
3664 __resolveZoneSize(pDimensionDefinitions[pos]);
3671 for (
int i = (1 << iCurrentBits) - (1 << bitpos) ; i >= 0 ; i -= (1 << bitpos)) {
3672 for (
int k = 0 ; k < (1 << bitpos) ; k++) {
3673 pDimensionRegions[(i << pDimDef->
bits) + k] = pDimensionRegions[i + k];
3675 for (
int j = 1 ; j < (1 << pDimDef->
bits) ; j++) {
3676 for (
int k = 0 ; k < (1 << bitpos) ; k++) {
3678 if (moveTo) _3prg->
MoveSubChunk(pNewDimRgnListChunk, moveTo);
3681 pDimensionRegions[(i << pDimDef->
bits) + (j << bitpos) + k] =
3687 moveTo = pDimensionRegions[i]->pParentList;
3691 int mask = (1 << bitpos) - 1;
3692 for (
int z = 0 ; z < pDimDef->
zones ; z++) {
3693 uint8_t upperLimit = uint8_t((z + 1) * 128.0 / pDimDef->
zones - 1);
3694 for (
int i = 0 ; i < 1 << iCurrentBits ; i++) {
3695 pDimensionRegions[((i & ~mask) << pDimDef->
bits) |
3697 (i & mask)]->DimensionUpperLimits[pos] = upperLimit;
3706 UpdateVelocityTable();
3722 int iDimensionNr = -1;
3723 for (
int i = 0; i < Dimensions; i++) {
3724 if (&pDimensionDefinitions[i] == pDimDef) {
3729 if (iDimensionNr < 0)
throw gig::Exception(
"Invalid dimension_def_t pointer");
3733 for (
int i = 0; i < iDimensionNr; i++)
3734 iLowerBits += pDimensionDefinitions[i].bits;
3738 for (
int i = iDimensionNr + 1; i < Dimensions; i++)
3739 iUpperBits += pDimensionDefinitions[i].bits;
3745 for (
int iUpperBit = 0; iUpperBit < 1 << iUpperBits; iUpperBit++) {
3746 for (
int iObsoleteBit = 1; iObsoleteBit < 1 << pDimensionDefinitions[iDimensionNr].bits; iObsoleteBit++) {
3747 for (
int iLowerBit = 0; iLowerBit < 1 << iLowerBits; iLowerBit++) {
3748 int iToDelete = iUpperBit << (pDimensionDefinitions[iDimensionNr].bits + iLowerBits) |
3749 iObsoleteBit << iLowerBits |
3752 _3prg->
DeleteSubChunk(pDimensionRegions[iToDelete]->pParentList);
3753 delete pDimensionRegions[iToDelete];
3754 pDimensionRegions[iToDelete] = NULL;
3762 for (
int iFrom = 2, iTo = 1; iFrom < 256 && iTo < 256 - 1; iTo++) {
3763 if (!pDimensionRegions[iTo]) {
3764 if (iFrom <= iTo) iFrom = iTo + 1;
3765 while (!pDimensionRegions[iFrom] && iFrom < 256) iFrom++;
3766 if (iFrom < 256 && pDimensionRegions[iFrom]) {
3767 pDimensionRegions[iTo] = pDimensionRegions[iFrom];
3768 pDimensionRegions[iFrom] = NULL;
3774 for (
int j = 0 ; j < 256 && pDimensionRegions[j] ; j++) {
3776 for (
int i = iDimensionNr + 1; i < Dimensions; i++) {
3783 for (
int i = iDimensionNr + 1; i < Dimensions; i++) {
3784 pDimensionDefinitions[i - 1] = pDimensionDefinitions[i];
3786 pDimensionDefinitions[Dimensions - 1].dimension =
dimension_none;
3787 pDimensionDefinitions[Dimensions - 1].bits = 0;
3788 pDimensionDefinitions[Dimensions - 1].zones = 0;
3812 throw gig::Exception(
"Could not delete dimension zone, because there is no dimension at all.");
3815 throw gig::Exception(
"Could not delete dimension zone, no such dimension of given type");
3816 if (oldDef->
zones <= 2)
3817 throw gig::Exception(
"Could not delete dimension zone, because it would end up with only one zone.");
3818 if (zone < 0 || zone >= oldDef->
zones)
3819 throw gig::Exception(
"Could not delete dimension zone, requested zone index out of bounds.");
3821 const int newZoneSize = oldDef->
zones - 1;
3830 RIFF::List* pCkInstrument = instr->pCkInstrument;
3832 if (!lrgn) lrgn = pCkInstrument->
AddSubList(LIST_TYPE_LRGN);
3834 tempRgn =
new Region(instr, rgn);
3842 for (
int i = 0; i < Dimensions; ++i) {
3846 def.
zones = newZoneSize;
3854 throw gig::Exception(
"Unexpected internal failure resolving dimension in DeleteDimensionZone() [this is a bug].");
3858 int tempReducedDimensionIndex = -1;
3859 for (
int d = 0; d < tempRgn->
Dimensions; ++d) {
3861 tempReducedDimensionIndex = d;
3867 for (
int iDst = 0; iDst < 256; ++iDst) {
3869 if (!dstDimRgn)
continue;
3870 std::map<dimension_t,int> dimCase;
3871 bool isValidZone =
true;
3872 for (
int d = 0, baseBits = 0; d < tempRgn->
Dimensions; ++d) {
3875 (iDst >> baseBits) & ((1 << dstBits) - 1);
3876 baseBits += dstBits;
3879 isValidZone =
false;
3883 if (!isValidZone)
continue;
3886 const bool isLastZone = (dimCase[type] == newZoneSize - 1);
3887 if (dimCase[type] >= zone) dimCase[type]++;
3904 std::vector<dimension_def_t> oldDefs;
3905 for (
int i = 0; i < Dimensions; ++i)
3906 oldDefs.push_back(pDimensionDefinitions[i]);
3907 for (
int i = Dimensions - 1; i >= 0; --i)
3908 DeleteDimension(&pDimensionDefinitions[i]);
3909 for (
int i = 0; i < oldDefs.size(); ++i) {
3916 for (
int iSrc = 0; iSrc < 256; ++iSrc) {
3918 if (!srcDimRgn)
continue;
3919 std::map<dimension_t,int> dimCase;
3920 for (
int d = 0, baseBits = 0; d < tempRgn->
Dimensions; ++d) {
3923 (iSrc >> baseBits) & ((1 << srcBits) - 1);
3924 baseBits += srcBits;
3929 if (!dstDimRgn)
continue;
3937 UpdateVelocityTable();
3956 throw gig::Exception(
"Could not split dimension zone, because there is no dimension at all.");
3959 throw gig::Exception(
"Could not split dimension zone, no such dimension of given type");
3960 if (zone < 0 || zone >= oldDef->
zones)
3961 throw gig::Exception(
"Could not split dimension zone, requested zone index out of bounds.");
3963 const int newZoneSize = oldDef->
zones + 1;
3972 RIFF::List* pCkInstrument = instr->pCkInstrument;
3974 if (!lrgn) lrgn = pCkInstrument->
AddSubList(LIST_TYPE_LRGN);
3976 tempRgn =
new Region(instr, rgn);
3984 for (
int i = 0; i < Dimensions; ++i) {
3988 def.
zones = newZoneSize;
3989 if ((1 << oldDef->
bits) < newZoneSize) def.
bits++;
3996 throw gig::Exception(
"Unexpected internal failure resolving dimension in SplitDimensionZone() [this is a bug].");
4000 int tempIncreasedDimensionIndex = -1;
4001 for (
int d = 0; d < tempRgn->
Dimensions; ++d) {
4003 tempIncreasedDimensionIndex = d;
4009 for (
int iSrc = 0; iSrc < 256; ++iSrc) {
4011 if (!srcDimRgn)
continue;
4012 std::map<dimension_t,int> dimCase;
4013 bool isValidZone =
true;
4014 for (
int d = 0, baseBits = 0; d < Dimensions; ++d) {
4015 const int srcBits = pDimensionDefinitions[d].bits;
4016 dimCase[pDimensionDefinitions[d].dimension] =
4017 (iSrc >> baseBits) & ((1 << srcBits) - 1);
4019 if (dimCase[pDimensionDefinitions[d].dimension] >= pDimensionDefinitions[d].zones) {
4020 isValidZone =
false;
4023 baseBits += srcBits;
4025 if (!isValidZone)
continue;
4028 if (dimCase[type] > zone) dimCase[type]++;
4034 if (dimCase[type] == zone) {
4041 std::map<dimension_t,int> lowerCase = dimCase;
4063 std::vector<dimension_def_t> oldDefs;
4064 for (
int i = 0; i < Dimensions; ++i)
4065 oldDefs.push_back(pDimensionDefinitions[i]);
4066 for (
int i = Dimensions - 1; i >= 0; --i)
4067 DeleteDimension(&pDimensionDefinitions[i]);
4068 for (
int i = 0; i < oldDefs.size(); ++i) {
4075 for (
int iSrc = 0; iSrc < 256; ++iSrc) {
4077 if (!srcDimRgn)
continue;
4078 std::map<dimension_t,int> dimCase;
4079 for (
int d = 0, baseBits = 0; d < tempRgn->
Dimensions; ++d) {
4082 (iSrc >> baseBits) & ((1 << srcBits) - 1);
4083 baseBits += srcBits;
4088 if (!dstDimRgn)
continue;
4096 UpdateVelocityTable();
4114 if (oldType == newType)
return;
4117 throw gig::Exception(
"No dimension with provided old dimension type exists on this region");
4119 throw gig::Exception(
"Cannot change to dimension type 'sample channel', because existing dimension does not have 2 zones");
4120 if (GetDimensionDefinition(newType))
4121 throw gig::Exception(
"There is already a dimension with requested new dimension type on this region");
4123 def->
split_type = __resolveSplitType(newType);
4127 uint8_t bits[8] = {};
4128 for (std::map<dimension_t,int>::const_iterator it = DimCase.begin();
4129 it != DimCase.end(); ++it)
4131 for (
int d = 0; d < Dimensions; ++d) {
4132 if (pDimensionDefinitions[d].dimension == it->first) {
4133 bits[d] = it->second;
4134 goto nextDimCaseSlice;
4141 return GetDimensionRegionByBit(bits);
4154 for (
int i = 0; i < Dimensions; ++i)
4155 if (pDimensionDefinitions[i].dimension == type)
4156 return &pDimensionDefinitions[i];
4161 for (
int i = 0; i < 256; i++) {
4162 if (pDimensionRegions[i])
delete pDimensionRegions[i];
4190 for (uint i = 0; i < Dimensions; i++) {
4196 switch (pDimensionDefinitions[i].split_type) {
4198 if (pDimensionRegions[0]->DimensionUpperLimits[i]) {
4200 for (bits = 0 ; bits < pDimensionDefinitions[i].zones ; bits++) {
4201 if (DimValues[i] <= pDimensionRegions[bits << bitpos]->DimensionUpperLimits[i])
break;
4205 bits = uint8_t(DimValues[i] / pDimensionDefinitions[i].zone_size);
4209 const uint8_t limiter_mask = (0xff << pDimensionDefinitions[i].bits) ^ 0xff;
4210 bits = DimValues[i] & limiter_mask;
4213 dimregidx |= bits << bitpos;
4215 bitpos += pDimensionDefinitions[i].bits;
4218 if (!dimreg)
return NULL;
4224 bits = uint8_t((DimValues[veldim] & 127) / pDimensionDefinitions[veldim].zone_size);
4226 const uint8_t limiter_mask = (1 << pDimensionDefinitions[veldim].bits) - 1;
4227 dimregidx |= (bits & limiter_mask) << velbitpos;
4228 dimreg = pDimensionRegions[dimregidx & 255];
4233 int Region::GetDimensionRegionIndexByValue(
const uint DimValues[8]) {
4239 for (uint i = 0; i < Dimensions; i++) {
4245 switch (pDimensionDefinitions[i].split_type) {
4247 if (pDimensionRegions[0]->DimensionUpperLimits[i]) {
4249 for (bits = 0 ; bits < pDimensionDefinitions[i].zones ; bits++) {
4250 if (DimValues[i] <= pDimensionRegions[bits << bitpos]->DimensionUpperLimits[i])
break;
4254 bits = uint8_t(DimValues[i] / pDimensionDefinitions[i].zone_size);
4258 const uint8_t limiter_mask = (0xff << pDimensionDefinitions[i].bits) ^ 0xff;
4259 bits = DimValues[i] & limiter_mask;
4262 dimregidx |= bits << bitpos;
4264 bitpos += pDimensionDefinitions[i].bits;
4268 if (!dimreg)
return -1;
4274 bits = uint8_t((DimValues[veldim] & 127) / pDimensionDefinitions[veldim].zone_size);
4276 const uint8_t limiter_mask = (1 << pDimensionDefinitions[veldim].bits) - 1;
4277 dimregidx |= (bits & limiter_mask) << velbitpos;
4294 return pDimensionRegions[((((((DimBits[7] << pDimensionDefinitions[6].bits | DimBits[6])
4295 << pDimensionDefinitions[5].bits | DimBits[5])
4296 << pDimensionDefinitions[4].bits | DimBits[4])
4297 << pDimensionDefinitions[3].bits | DimBits[3])
4298 << pDimensionDefinitions[2].bits | DimBits[2])
4299 << pDimensionDefinitions[1].bits | DimBits[1])
4300 << pDimensionDefinitions[0].bits | DimBits[0]];
4313 if (pSample)
return static_cast<gig::Sample*
>(pSample);
4314 else return static_cast<gig::Sample*
>(pSample = GetSampleFromWavePool(WavePoolTableIndex));
4317 Sample* Region::GetSampleFromWavePool(
unsigned int WavePoolTableIndex,
progress_t* pProgress) {
4318 if ((int32_t)WavePoolTableIndex == -1)
return NULL;
4319 File* file = (
File*) GetParent()->GetParent();
4320 if (!file->pWavePoolTable)
return NULL;
4321 if (WavePoolTableIndex + 1 > file->WavePoolCount)
return NULL;
4325 uint64_t soughtoffset =
4326 uint64_t(file->pWavePoolTable[WavePoolTableIndex]) |
4327 uint64_t(file->pWavePoolTableHi[WavePoolTableIndex]) << 32;
4332 if (sample->ullWavePoolOffset == soughtoffset)
4337 file_offset_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
4338 file_offset_t soughtfileno = file->pWavePoolTableHi[WavePoolTableIndex];
4343 if (sample->ullWavePoolOffset == soughtoffset &&
4344 sample->FileNo == soughtfileno)
return sample;
4374 if (mSamples && mSamples->count((
gig::Sample*)orig->pSample)) {
4375 pSample = mSamples->find((
gig::Sample*)orig->pSample)->second;
4379 for (
int i = Dimensions - 1; i >= 0; --i) {
4380 DeleteDimension(&pDimensionDefinitions[i]);
4389 for (
int i = 0; i < 256; i++) {
4391 pDimensionRegions[i]->CopyAssign(
4413 bool Region::UsesAnyGigFormatExtension()
const {
4414 for (
int i = 0; i < 256; i++) {
4415 if (pDimensionRegions[i]) {
4416 if (pDimensionRegions[i]->UsesAnyGigFormatExtension())
4427 MidiRuleCtrlTrigger::MidiRuleCtrlTrigger(
RIFF::Chunk* _3ewg) {
4433 for (
int i = 0 ; i < Triggers ; i++) {
4434 pTriggers[i].TriggerPoint = _3ewg->
ReadUint8();
4435 pTriggers[i].Descending = _3ewg->
ReadUint8();
4436 pTriggers[i].VelSensitivity = _3ewg->
ReadUint8();
4438 pTriggers[i].NoteOff = _3ewg->
ReadUint8();
4439 pTriggers[i].Velocity = _3ewg->
ReadUint8();
4440 pTriggers[i].OverridePedal = _3ewg->
ReadUint8();
4445 MidiRuleCtrlTrigger::MidiRuleCtrlTrigger() :
4446 ControllerNumber(0),
4450 void MidiRuleCtrlTrigger::UpdateChunks(uint8_t* pData)
const {
4453 pData[36] = Triggers;
4454 pData[40] = ControllerNumber;
4455 for (
int i = 0 ; i < Triggers ; i++) {
4456 pData[46 + i * 8] = pTriggers[i].TriggerPoint;
4457 pData[47 + i * 8] = pTriggers[i].Descending;
4458 pData[48 + i * 8] = pTriggers[i].VelSensitivity;
4459 pData[49 + i * 8] = pTriggers[i].Key;
4460 pData[50 + i * 8] = pTriggers[i].NoteOff;
4461 pData[51 + i * 8] = pTriggers[i].Velocity;
4462 pData[52 + i * 8] = pTriggers[i].OverridePedal;
4466 MidiRuleLegato::MidiRuleLegato(
RIFF::Chunk* _3ewg) {
4470 BypassUseController = _3ewg->
ReadUint8();
4485 MidiRuleLegato::MidiRuleLegato() :
4487 BypassUseController(
false),
4489 BypassController(1),
4492 ReleaseTriggerKey(0),
4496 KeyRange.low = KeyRange.high = 0;
4499 void MidiRuleLegato::UpdateChunks(uint8_t* pData)
const {
4502 pData[36] = LegatoSamples;
4503 pData[40] = BypassUseController;
4504 pData[41] = BypassKey;
4505 pData[42] = BypassController;
4506 store16(&pData[43], ThresholdTime);
4507 store16(&pData[47], ReleaseTime);
4508 pData[51] = KeyRange.low;
4509 pData[52] = KeyRange.high;
4510 pData[64] = ReleaseTriggerKey;
4511 pData[65] = AltSustain1Key;
4512 pData[66] = AltSustain2Key;
4515 MidiRuleAlternator::MidiRuleAlternator(
RIFF::Chunk* _3ewg) {
4519 Polyphonic = flags & 8;
4520 Chained = flags & 4;
4521 Selector = (flags & 2) ? selector_controller :
4522 (flags & 1) ? selector_key_switch : selector_none;
4528 KeySwitchRange.low = _3ewg->
ReadUint8();
4529 KeySwitchRange.high = _3ewg->
ReadUint8();
4534 int n = std::min(
int(Articulations), 32);
4535 for (
int i = 0 ; i < n ; i++) {
4539 n = std::min(
int(Patterns), 32);
4540 for (
int i = 0 ; i < n ; i++) {
4543 _3ewg->
Read(&pPatterns[i][0], 1, 32);
4547 MidiRuleAlternator::MidiRuleAlternator() :
4550 Selector(selector_none),
4555 PlayRange.low = PlayRange.high = 0;
4556 KeySwitchRange.low = KeySwitchRange.high = 0;
4559 void MidiRuleAlternator::UpdateChunks(uint8_t* pData)
const {
4562 pData[36] = Articulations;
4563 pData[37] = (Polyphonic ? 8 : 0) | (Chained ? 4 : 0) |
4564 (Selector == selector_controller ? 2 :
4565 (Selector == selector_key_switch ? 1 : 0));
4566 pData[38] = Patterns;
4568 pData[43] = KeySwitchRange.low;
4569 pData[44] = KeySwitchRange.high;
4570 pData[45] = Controller;
4571 pData[46] = PlayRange.low;
4572 pData[47] = PlayRange.high;
4574 char* str =
reinterpret_cast<char*
>(pData);
4576 int n = std::min(
int(Articulations), 32);
4577 for (
int i = 0 ; i < n ; i++, pos += 32) {
4578 strncpy(&str[pos], pArticulations[i].c_str(), 32);
4582 n = std::min(
int(Patterns), 32);
4583 for (
int i = 0 ; i < n ; i++, pos += 49) {
4584 strncpy(&str[pos], pPatterns[i].Name.c_str(), 16);
4585 pData[pos + 16] = pPatterns[i].Size;
4586 memcpy(&pData[pos + 16], &(pPatterns[i][0]), 32);
4601 Compression = (Compression_t) ckScri->
ReadUint32();
4602 Encoding = (Encoding_t) ckScri->
ReadUint32();
4603 Language = (Language_t) ckScri->
ReadUint32();
4607 Name.resize(nameSize,
' ');
4608 for (
int i = 0; i < nameSize; ++i)
4611 if (headerSize >= 6*
sizeof(int32_t) + nameSize + 16) {
4612 for (uint i = 0; i < 16; ++i) {
4619 ckScri->
SetPos(
sizeof(int32_t) + headerSize);
4621 uint32_t scriptSize = uint32_t(ckScri->
GetSize() - ckScri->
GetPos());
4622 data.resize(scriptSize);
4623 for (
int i = 0; i < scriptSize; ++i)
4626 Compression = COMPRESSION_NONE;
4627 Encoding = ENCODING_ASCII;
4628 Language = LANGUAGE_NKSP;
4631 Name =
"Unnamed Script";
4644 s.resize(data.size(),
' ');
4645 memcpy(&s[0], &data[0], data.size());
4656 data.resize(text.size());
4657 memcpy(&data[0], &text[0], text.size());
4684 __calculateCRC(&data[0], data.size(),
crc);
4687 const file_offset_t chunkSize =
4688 (file_offset_t) 7*
sizeof(int32_t) + Name.size() + 16 + data.size();
4689 if (!pChunk) pChunk =
pGroup->pList->AddSubChunk(CHUNK_ID_SCRI, chunkSize);
4690 else pChunk->Resize(chunkSize);
4692 uint8_t* pData = (uint8_t*) pChunk->LoadChunkData();
4694 store32(&pData[pos], uint32_t(6*
sizeof(int32_t) + Name.size() + 16));
4695 pos +=
sizeof(int32_t);
4696 store32(&pData[pos], Compression);
4697 pos +=
sizeof(int32_t);
4698 store32(&pData[pos], Encoding);
4699 pos +=
sizeof(int32_t);
4700 store32(&pData[pos], Language);
4701 pos +=
sizeof(int32_t);
4702 store32(&pData[pos], Bypass ? 1 : 0);
4703 pos +=
sizeof(int32_t);
4704 store32(&pData[pos], crc);
4705 pos +=
sizeof(int32_t);
4706 store32(&pData[pos], (uint32_t) Name.size());
4707 pos +=
sizeof(int32_t);
4708 for (
int i = 0; i < Name.size(); ++i, ++pos)
4709 pData[pos] = Name[i];
4710 for (
int i = 0; i < 16; ++i, ++pos)
4711 pData[pos] = Uuid[i];
4712 for (
int i = 0; i < data.size(); ++i, ++pos)
4713 pData[pos] = data[i];
4722 Uuid[0] = dlsid.ulData1 & 0xff;
4723 Uuid[1] = dlsid.ulData1 >> 8 & 0xff;
4724 Uuid[2] = dlsid.ulData1 >> 16 & 0xff;
4725 Uuid[3] = dlsid.ulData1 >> 24 & 0xff;
4726 Uuid[4] = dlsid.usData2 & 0xff;
4727 Uuid[5] = dlsid.usData2 >> 8 & 0xff;
4728 Uuid[6] = dlsid.usData3 & 0xff;
4729 Uuid[7] = dlsid.usData3 >> 8 & 0xff;
4730 Uuid[8] = dlsid.abData[0];
4731 Uuid[9] = dlsid.abData[1];
4732 Uuid[10] = dlsid.abData[2];
4733 Uuid[11] = dlsid.abData[3];
4734 Uuid[12] = dlsid.abData[4];
4735 Uuid[13] = dlsid.abData[5];
4736 Uuid[14] = dlsid.abData[6];
4737 Uuid[15] = dlsid.abData[7];
4747 if (this->pGroup == pGroup)
return;
4749 pChunk->GetParent()->MoveSubChunk(pChunk, pGroup->pList);
4779 void Script::RemoveAllScriptReferences() {
4796 ::LoadString(ckName, Name);
4798 Name =
"Default Group";
4802 ScriptGroup::~ScriptGroup() {
4804 std::vector<Script*>::iterator iter = pScripts->begin();
4805 std::vector<Script*>::iterator end = pScripts->end();
4806 while (iter != end) {
4838 pList = pFile->pRIFF->GetSubList(LIST_TYPE_3LS)->AddSubList(LIST_TYPE_RTIS);
4841 ::SaveString(CHUNK_ID_LSNM, NULL, pList, Name, String(
"Unnamed Group"),
true, 64);
4843 for (std::vector<Script*>::iterator it = pScripts->begin();
4844 it != pScripts->end(); ++it)
4846 (*it)->UpdateChunks(pProgress);
4859 if (!pScripts) LoadScripts();
4860 if (index >= pScripts->size())
return NULL;
4861 return (*pScripts)[index];
4876 if (!pScripts) LoadScripts();
4878 pScripts->push_back(pScript);
4893 if (!pScripts) LoadScripts();
4894 std::vector<Script*>::iterator iter =
4895 find(pScripts->begin(), pScripts->end(), pScript);
4896 if (iter == pScripts->end())
4897 throw gig::Exception(
"Could not delete script, could not find given script");
4898 pScripts->erase(iter);
4899 pScript->RemoveAllScriptReferences();
4900 if (pScript->pChunk)
4905 void ScriptGroup::LoadScripts() {
4906 if (pScripts)
return;
4907 pScripts =
new std::vector<Script*>;
4911 for (
RIFF::Chunk* ck = pList->GetSubChunkAt(i); ck;
4912 ck = pList->GetSubChunkAt(++i))
4914 if (ck->GetChunkID() == CHUNK_ID_SCRI) {
4915 pScripts->push_back(
new Script(
this, ck));
4924 static const DLS::Info::string_length_t fixedStringLengths[] = {
4925 { CHUNK_ID_INAM, 64 },
4926 { CHUNK_ID_ISFT, 12 },
4932 for (
int i = 0; i < 128; i++) RegionKeyTable[i] = NULL;
4937 PianoReleaseMode =
false;
4938 DimensionKeyRange.low = 0;
4939 DimensionKeyRange.high = 0;
4941 pMidiRules[0] = NULL;
4955 uint8_t dimkeystart = _3ewg->
ReadUint8();
4956 PianoReleaseMode = dimkeystart & 0x01;
4957 DimensionKeyRange.low = dimkeystart >> 1;
4958 DimensionKeyRange.high = _3ewg->
ReadUint8();
4970 }
else if (id1 == 0) {
4972 }
else if (id1 == 3) {
4978 else if (id1 != 0 || id2 != 0) {
4983 pMidiRules[i] = NULL;
4988 if (pFile->GetAutoLoad()) {
4989 if (!pRegions) pRegions =
new RegionList;
4998 __notify_progress(pProgress, (
float) pRegions->size() / (float) Regions);
4999 pRegions->push_back(
new Region(
this, rgn));
5003 UpdateRegionKeyTable();
5019 ckSCSL->
SetPos(headerSize);
5020 int unknownSpace = slotSize - 2*
sizeof(uint32_t);
5021 for (
int i = 0; i < slotCount; ++i) {
5022 _ScriptPooolEntry e;
5025 if (unknownSpace) ckSCSL->
SetPos(unknownSpace, RIFF::stream_curpos);
5026 scriptPoolFileOffsets.push_back(e);
5037 for (
int iScript = 0; iScript < nScripts; ++iScript) {
5039 for (
int i = 0; i < 16; ++i)
5044 for (
int iVar = 0; iVar < nVars; ++iVar) {
5054 for (
int i = 0; i < len; ++i)
5057 for (
int i = 0; i < len; ++i)
5060 scriptVars[uuid][slot][name] = value;
5064 ckSCPV->
SetPos(pos + blobSize);
5071 __notify_progress(pProgress, 1.0f);
5074 void Instrument::UpdateRegionKeyTable() {
5075 for (
int i = 0; i < 128; i++) RegionKeyTable[i] = NULL;
5076 RegionList::iterator iter = pRegions->begin();
5077 RegionList::iterator end = pRegions->end();
5078 for (; iter != end; ++iter) {
5080 const int low = std::max(
int(pRegion->
KeyRange.
low), 0);
5081 const int high = std::min(
int(pRegion->
KeyRange.
high), 127);
5082 for (
int iKey = low; iKey <= high; iKey++) {
5083 RegionKeyTable[iKey] = pRegion;
5089 for (
int i = 0 ; pMidiRules[i] ; i++) {
5090 delete pMidiRules[i];
5092 delete[] pMidiRules;
5093 if (pScriptRefs)
delete pScriptRefs;
5112 RegionList::iterator iter = pRegions->begin();
5113 RegionList::iterator end = pRegions->end();
5114 for (; iter != end; ++iter)
5115 (*iter)->UpdateChunks(pProgress);
5120 if (!lart) lart = pCkInstrument->
AddSubList(LIST_TYPE_LART);
5133 store16(&pData[0], EffectSend);
5134 store32(&pData[2], Attenuation);
5136 store16(&pData[8], PitchbendRange);
5137 const uint8_t dimkeystart = (PianoReleaseMode ? 0x01 : 0x00) |
5138 DimensionKeyRange.low << 1;
5139 pData[10] = dimkeystart;
5140 pData[11] = DimensionKeyRange.high;
5142 if (pMidiRules[0] == 0 && _3ewg->
GetSize() >= 34) {
5146 for (
int i = 0 ; pMidiRules[i] ; i++) {
5147 pMidiRules[i]->UpdateChunks(pData);
5152 if (ScriptSlotCount()) {
5158 if (!lst3LS) lst3LS = pCkInstrument->
AddSubList(LIST_TYPE_3LS);
5161 const int slotCount = (int) pScriptRefs->size();
5162 const int headerSize = 3 *
sizeof(uint32_t);
5163 const int slotSize = 2 *
sizeof(uint32_t);
5164 const int totalChunkSize = headerSize + slotCount * slotSize;
5166 if (!ckSCSL) ckSCSL = lst3LS->
AddSubChunk(CHUNK_ID_SCSL, totalChunkSize);
5167 else ckSCSL->
Resize(totalChunkSize);
5170 store32(&pData[pos], headerSize);
5171 pos +=
sizeof(uint32_t);
5172 store32(&pData[pos], slotCount);
5173 pos +=
sizeof(uint32_t);
5174 store32(&pData[pos], slotSize);
5175 pos +=
sizeof(uint32_t);
5176 for (
int i = 0; i < slotCount; ++i) {
5179 int bogusFileOffset = 0;
5180 store32(&pData[pos], bogusFileOffset);
5181 pos +=
sizeof(uint32_t);
5182 store32(&pData[pos], (*pScriptRefs)[i].bypass ? 1 : 0);
5183 pos +=
sizeof(uint32_t);
5195 _VarsByScript vars = stripScriptVars();
5196 if (!vars.empty()) {
5201 size_t totalChunkSize = 4;
5202 size_t totalScriptsOverridden = 0;
5203 for (
const auto& script : vars) {
5204 for (
const auto& slot : script.second) {
5205 totalScriptsOverridden++;
5206 totalChunkSize += 16 + 4 + 4 + 4;
5207 for (
const auto& var : slot.second) {
5208 totalChunkSize += 4 + 2 + var.first.length() +
5209 2 + var.second.length();
5216 if (!ckSCPV) ckSCPV = lst3LS->
AddSubChunk(CHUNK_ID_SCPV, totalChunkSize);
5217 else ckSCPV->
Resize(totalChunkSize);
5222 store32(&pData[pos], (uint32_t) totalScriptsOverridden);
5224 for (
const auto& script : vars) {
5225 for (
const auto& slot : script.second) {
5226 for (
int i = 0; i < 16; ++i)
5227 pData[pos+i] = script.first[i];
5229 store32(&pData[pos], (uint32_t) slot.first);
5231 store32(&pData[pos], (uint32_t) 0);
5233 store32(&pData[pos], (uint32_t) slot.second.size());
5235 for (
const auto& var : slot.second) {
5238 store16(&pData[pos], 2 + var.first.size() + 2 + var.second.size());
5240 store16(&pData[pos], var.first.size());
5242 for (
int i = 0; i < var.first.size(); ++i)
5243 pData[pos++] = var.first[i];
5244 store16(&pData[pos], var.second.size());
5246 for (
int i = 0; i < var.second.size(); ++i)
5247 pData[pos++] = var.second[i];
5264 void Instrument::UpdateScriptFileOffsets() {
5266 if (pScriptRefs && pScriptRefs->size() > 0) {
5269 const int slotCount = (int) pScriptRefs->size();
5270 const int headerSize = 3 *
sizeof(uint32_t);
5271 ckSCSL->
SetPos(headerSize);
5272 for (
int i = 0; i < slotCount; ++i) {
5273 uint32_t fileOffset = uint32_t(
5274 (*pScriptRefs)[i].script->pChunk->GetFilePos() -
5275 (*pScriptRefs)[i].script->pChunk->GetPos() -
5280 ckSCSL->
SetPos(
sizeof(uint32_t), RIFF::stream_curpos);
5293 if (!pRegions || pRegions->empty() || Key > 127)
return NULL;
5294 return RegionKeyTable[Key];
5314 if (!pRegions)
return NULL;
5315 if (pos >= pRegions->size())
return NULL;
5316 return static_cast<gig::Region*
>( (*pRegions)[pos] );
5329 if (!pRegions)
return NULL;
5330 RegionsIterator = pRegions->begin();
5331 return static_cast<gig::Region*
>( (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL );
5345 if (!pRegions)
return NULL;
5347 return static_cast<gig::Region*
>( (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL );
5350 Region* Instrument::AddRegion() {
5353 if (!lrgn) lrgn = pCkInstrument->
AddSubList(LIST_TYPE_LRGN);
5356 const size_t idxIt = RegionsIterator - pRegions->begin();
5357 pRegions->push_back(pNewRegion);
5358 RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size());
5359 Regions = (uint32_t) pRegions->size();
5361 UpdateRegionKeyTable();
5366 void Instrument::DeleteRegion(
Region* pRegion) {
5367 if (!pRegions)
return;
5368 DLS::Instrument::DeleteRegion((
DLS::Region*) pRegion);
5370 UpdateRegionKeyTable();
5402 if (dst && GetParent() != dst->GetParent())
5404 "gig::Instrument::MoveTo() can only be used for moving within " 5405 "the same gig file." 5412 File::InstrumentList& list = *pFile->pInstruments;
5414 File::InstrumentList::iterator itFrom =
5415 std::find(list.begin(), list.end(),
static_cast<DLS::Instrument*
>(
this));
5416 if (itFrom == list.end())
5418 "gig::Instrument::MoveTo(): unexpected missing membership " 5419 "of this instrument." 5423 File::InstrumentList::iterator itTo =
5424 std::find(list.begin(), list.end(),
static_cast<DLS::Instrument*
>(dst));
5426 list.insert(itTo,
this);
5432 this->pCkInstrument,
5433 (
RIFF::Chunk*) ((dst) ? dst->pCkInstrument : NULL)
5448 return pMidiRules[i];
5457 delete pMidiRules[0];
5470 delete pMidiRules[0];
5483 delete pMidiRules[0];
5496 delete pMidiRules[i];
5500 void Instrument::LoadScripts() {
5501 if (pScriptRefs)
return;
5502 pScriptRefs =
new std::vector<_ScriptPooolRef>;
5503 if (scriptPoolFileOffsets.empty())
return;
5505 for (uint k = 0; k < scriptPoolFileOffsets.size(); ++k) {
5506 uint32_t soughtOffset = scriptPoolFileOffsets[k].fileOffset;
5509 for (uint s = 0; group->
GetScript(s); ++s) {
5511 if (script->pChunk) {
5512 uint32_t offset = uint32_t(
5514 script->pChunk->
GetPos() -
5517 if (offset == soughtOffset)
5519 _ScriptPooolRef ref;
5520 ref.script = script;
5521 ref.bypass = scriptPoolFileOffsets[k].bypass;
5522 pScriptRefs->push_back(ref);
5530 scriptPoolFileOffsets.clear();
5547 if (index >= pScriptRefs->size())
return NULL;
5548 return pScriptRefs->at(index).script;
5588 _ScriptPooolRef ref = { pScript, bypass };
5589 pScriptRefs->push_back(ref);
5608 if (index1 >= pScriptRefs->size() || index2 >= pScriptRefs->size())
5610 _ScriptPooolRef tmp = (*pScriptRefs)[index1];
5611 (*pScriptRefs)[index1] = (*pScriptRefs)[index2];
5612 (*pScriptRefs)[index2] = tmp;
5623 if (index >= pScriptRefs->size())
return;
5624 pScriptRefs->erase( pScriptRefs->begin() + index );
5641 for (ssize_t i = pScriptRefs->size() - 1; i >= 0; --i) {
5642 if ((*pScriptRefs)[i].script == pScript) {
5643 pScriptRefs->erase( pScriptRefs->begin() + i );
5663 return pScriptRefs ? pScriptRefs->size() : scriptPoolFileOffsets.size();
5683 if (index >= ScriptSlotCount())
return false;
5684 return pScriptRefs ? pScriptRefs->at(index).bypass
5685 : scriptPoolFileOffsets.at(index).bypass;
5703 if (index >= ScriptSlotCount())
return;
5705 pScriptRefs->at(index).bypass = bBypass;
5707 scriptPoolFileOffsets.at(index).bypass = bBypass;
5712 std::array<uint8_t,16> uuid;
5713 memcpy(&uuid[0], pData, 16);
5721 bool Instrument::ReferencesScriptWithUuid(
const _UUID& uuid) {
5722 const size_t nSlots = ScriptSlotCount();
5723 for (
size_t iSlot = 0; iSlot < nSlots; ++iSlot)
5749 if (variable.empty())
return false;
5750 Script* script = GetScriptOfSlot(slot);
5751 if (!script)
return false;
5753 if (!scriptVars.count(uuid))
return false;
5754 const _VarsBySlot& slots = scriptVars.find(uuid)->second;
5755 if (slots.empty())
return false;
5756 if (slots.count(slot))
5757 return slots.find(slot)->second.count(variable);
5759 return slots.begin()->second.count(variable);
5783 Script* script = GetScriptOfSlot(slot);
5784 if (!script)
return std::map<String,String>();
5786 if (!scriptVars.count(uuid))
return std::map<String,String>();
5787 const _VarsBySlot& slots = scriptVars.find(uuid)->second;
5788 if (slots.empty())
return std::map<String,String>();
5789 const _PatchVars& vars =
5790 (slots.count(slot)) ?
5791 slots.find(slot)->second : slots.begin()->second;
5815 std::map<String,String> vars = GetScriptPatchVariables(slot);
5816 return (vars.count(variable)) ? vars.find(variable)->second :
"";
5842 if (variable.empty())
5843 throw Exception(
"Variable name must not be empty");
5844 Script* script = GetScriptOfSlot(slot);
5846 throw Exception(
"No script slot with index " + ToString(slot));
5848 scriptVars[uuid][slot][variable] = value;
5883 Script* script = GetScriptOfSlot(slot);
5886 if (slot != -1 && !variable.empty()) {
5887 if (!script)
return;
5889 if (!scriptVars.count(uuid))
return;
5890 if (!scriptVars[uuid].count(slot))
return;
5891 if (scriptVars[uuid][slot].count(variable))
5892 scriptVars[uuid][slot].erase(
5893 scriptVars[uuid][slot].find(variable)
5895 if (scriptVars[uuid][slot].empty())
5896 scriptVars[uuid].erase( scriptVars[uuid].find(slot) );
5897 if (scriptVars[uuid].empty())
5898 scriptVars.erase( scriptVars.find(uuid) );
5903 if (slot == -1 && variable.empty()) {
5910 if (!script)
return;
5912 if (scriptVars.count(uuid))
5913 scriptVars.erase( scriptVars.find(uuid) );
5918 _VarsByScript::iterator itScript = scriptVars.begin();
5919 _VarsByScript::iterator endScript = scriptVars.end();
5920 while (itScript != endScript) {
5921 _VarsBySlot& slots = itScript->second;
5922 _VarsBySlot::iterator itSlot = slots.begin();
5923 _VarsBySlot::iterator endSlot = slots.end();
5924 while (itSlot != endSlot) {
5925 _PatchVars& vars = itSlot->second;
5926 if (vars.count(variable))
5927 vars.erase( vars.find(variable) );
5929 slots.erase(itSlot++);
5934 scriptVars.erase(itScript++);
5947 Instrument::_VarsByScript Instrument::stripScriptVars() {
5949 _VarsByScript::const_iterator itScript = scriptVars.begin();
5950 _VarsByScript::const_iterator endScript = scriptVars.end();
5951 for (; itScript != endScript; ++itScript) {
5952 const _UUID& uuid = itScript->first;
5953 if (!ReferencesScriptWithUuid(uuid))
5955 const _VarsBySlot& slots = itScript->second;
5956 _VarsBySlot::const_iterator itSlot = slots.begin();
5957 _VarsBySlot::const_iterator endSlot = slots.end();
5958 for (; itSlot != endSlot; ++itSlot) {
5959 Script* script = GetScriptOfSlot(itSlot->first);
5960 if (!script)
continue;
5962 if (itSlot->second.empty())
continue;
5963 vars[uuid][itSlot->first] = itSlot->second;
5993 DLS::Instrument::CopyAssignCore(orig);
5997 EffectSend = orig->EffectSend;
6000 PianoReleaseMode = orig->PianoReleaseMode;
6002 scriptPoolFileOffsets = orig->scriptPoolFileOffsets;
6004 if (pScriptRefs)
delete pScriptRefs;
6005 pScriptRefs =
new std::vector<_ScriptPooolRef>;
6006 if (orig->pScriptRefs)
6007 *pScriptRefs = *orig->pScriptRefs;
6008 scriptVars = orig->scriptVars;
6011 for (
int i = 0 ; pMidiRules[i] ; i++) {
6012 delete pMidiRules[i];
6015 pMidiRules[0] = NULL;
6018 while (Regions) DeleteRegion(GetRegionAt(0));
6021 RegionList::const_iterator it = orig->pRegions->begin();
6022 for (
int i = 0; i < orig->
Regions; ++i, ++it) {
6023 Region* dstRgn = AddRegion();
6026 static_cast<gig::Region*>(*it),
6032 UpdateRegionKeyTable();
6048 bool Instrument::UsesAnyGigFormatExtension()
const {
6049 if (!pRegions)
return false;
6050 if (!scriptVars.empty())
return true;
6051 RegionList::const_iterator iter = pRegions->begin();
6052 RegionList::const_iterator end = pRegions->end();
6053 for (; iter != end; ++iter) {
6055 if (rgn->UsesAnyGigFormatExtension())
6073 pNameChunk = ck3gnm;
6074 SamplesIterator = 0;
6075 ::LoadString(pNameChunk, Name);
6092 pNameChunk->GetParent()->DeleteSubChunk(pNameChunk);
6111 _3gri = pFile->pRIFF->
AddSubList(LIST_TYPE_3GRI);
6115 if (!_3gnl) _3gnl = _3gri->
AddSubList(LIST_TYPE_3GNL);
6121 if (strcmp(static_cast<char*>(ck->LoadChunkData()),
"") == 0) {
6129 ::SaveString(CHUNK_ID_3GNM, pNameChunk, _3gnl, Name, String(
"Unnamed Group"),
true, 64);
6140 if (pFile->pSamples && index >= pFile->pSamples->size())
return NULL;
6141 size_t indexInFile = 0;
6142 size_t indexInGroup = 0;
6144 pSample = pFile->
GetSample(++indexInFile))
6146 if (pSample->GetGroup() !=
this)
continue;
6147 if (indexInGroup++ == index)
return pSample;
6166 size_t& i = this->SamplesIterator;
6171 if (pSample->GetGroup() ==
this)
6190 size_t& i = this->SamplesIterator;
6194 if (pSample->GetGroup() ==
this)
6216 Group* pOtherGroup = NULL;
6217 for (pOtherGroup = pFile->GetGroup(i); pOtherGroup;
6218 pOtherGroup = pFile->GetGroup(++i))
6220 if (pOtherGroup !=
this)
break;
6223 "Could not move samples to another group, since there is no " 6224 "other Group. This is a bug, report it!" 6228 while ((pSample = GetSample(0))) {
6240 0, 2, 19980628 & 0xffff, 19980628 >> 16
6245 0, 3, 20030331 & 0xffff, 20030331 >> 16
6250 0, 4, 20071012 & 0xffff, 20071012 >> 16
6253 static const DLS::Info::string_length_t _FileFixedStringLengths[] = {
6254 { CHUNK_ID_IARL, 256 },
6255 { CHUNK_ID_IART, 128 },
6256 { CHUNK_ID_ICMS, 128 },
6257 { CHUNK_ID_ICMT, 1024 },
6258 { CHUNK_ID_ICOP, 128 },
6259 { CHUNK_ID_ICRD, 128 },
6260 { CHUNK_ID_IENG, 128 },
6261 { CHUNK_ID_IGNR, 128 },
6262 { CHUNK_ID_IKEY, 128 },
6263 { CHUNK_ID_IMED, 128 },
6264 { CHUNK_ID_INAM, 128 },
6265 { CHUNK_ID_IPRD, 128 },
6266 { CHUNK_ID_ISBJ, 128 },
6267 { CHUNK_ID_ISFT, 128 },
6268 { CHUNK_ID_ISRC, 128 },
6269 { CHUNK_ID_ISRF, 128 },
6270 { CHUNK_ID_ITCH, 128 },
6276 *pVersion = VERSION_3;
6278 pScriptGroups = NULL;
6284 pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);
6285 pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);
6286 pRIFF->AddSubChunk(CHUNK_ID_DLID, 16);
6294 pScriptGroups = NULL;
6300 std::vector<Group*>::iterator iter = pGroups->begin();
6301 std::vector<Group*>::iterator end = pGroups->end();
6302 while (iter != end) {
6308 if (pScriptGroups) {
6309 std::vector<ScriptGroup*>::iterator iter = pScriptGroups->begin();
6310 std::vector<ScriptGroup*>::iterator end = pScriptGroups->end();
6311 while (iter != end) {
6315 delete pScriptGroups;
6328 if (!pSamples) LoadSamples(pProgress);
6329 if (!pSamples)
return NULL;
6330 SamplesIterator = pSamples->begin();
6331 return static_cast<gig::Sample*
>( (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL );
6342 if (!pSamples)
return NULL;
6344 return static_cast<gig::Sample*
>( (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL );
6355 if (!pSamples) LoadSamples(pProgress);
6356 if (!pSamples)
return NULL;
6357 if (index >= pSamples->size())
return NULL;
6358 return static_cast<gig::Sample*
>( (*pSamples)[index] );
6370 if (!pSamples) LoadSamples();
6371 if (!pSamples)
return 0;
6372 return pSamples->size();
6383 if (!pSamples) LoadSamples();
6384 __ensureMandatoryChunksExist();
6394 const size_t idxIt = SamplesIterator - pSamples->begin();
6395 pSamples->push_back(pSample);
6396 SamplesIterator = pSamples->begin() + std::min(idxIt, pSamples->size());
6410 if (!pSamples || !pSamples->size())
throw gig::Exception(
"Could not delete sample as there are no samples");
6411 SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), (
DLS::Sample*) pSample);
6412 if (iter == pSamples->end())
throw gig::Exception(
"Could not delete sample, could not find given sample");
6413 const size_t idxIt = SamplesIterator - pSamples->begin();
6414 pSamples->erase(iter);
6415 SamplesIterator = pSamples->begin() + std::min(idxIt, pSamples->size());
6421 for (
Instrument* instrument = GetInstrument(iIns); instrument;
6422 instrument = GetInstrument(++iIns))
6425 for (
Region* region = instrument->GetRegionAt(iRgn); region;
6426 region = instrument->GetRegionAt(++iRgn))
6428 if (region->GetSample() == pSample) region->SetSample(NULL);
6430 for (
int i = 0 ; i < region->DimensionRegions ; i++) {
6438 void File::LoadSamples() {
6442 void File::LoadSamples(
progress_t* pProgress) {
6445 if (!pGroups) LoadGroups();
6447 if (!pSamples) pSamples =
new SampleList;
6450 int iSampleIndex = 0;
6451 int iTotalSamples = WavePoolCount;
6454 const std::string folder = parentPath(pRIFF->GetFileName());
6455 const std::string baseName = pathWithoutExtension(pRIFF->GetFileName());
6459 std::vector<RIFF::File*> poolFiles;
6460 poolFiles.push_back(pRIFF);
6466 for (
int i = 0; i < n; i++) {
6470 std::string path = concatPath(folder, name);
6476 idExpected.ulData1 = ckXfil->
ReadInt32();
6477 idExpected.usData2 = ckXfil->
ReadInt16();
6478 idExpected.usData3 = ckXfil->
ReadInt16();
6479 ckXfil->
Read(idExpected.abData, 8, 1);
6481 ckDLSID->
Read(&idFound.ulData1, 1, 4);
6482 ckDLSID->
Read(&idFound.usData2, 1, 2);
6483 ckDLSID->
Read(&idFound.usData3, 1, 2);
6484 ckDLSID->
Read(idFound.abData, 8, 1);
6485 if (memcmp(&idExpected, &idFound, 16) != 0)
6486 throw gig::Exception(
"dlsid mismatch for extension file: %s", path.c_str());
6488 poolFiles.push_back(pExtFile);
6489 ExtensionFiles.push_back(pExtFile);
6496 std::string path = baseName +
".gx99";
6500 ckDoxf->
SetPos(132, RIFF::stream_curpos);
6506 idExpected.ulData1 = ckDoxf->
ReadInt32();
6507 idExpected.usData2 = ckDoxf->
ReadInt16();
6508 idExpected.usData3 = ckDoxf->
ReadInt16();
6509 ckDoxf->
Read(idExpected.abData, 8, 1);
6511 ckDLSID->
Read(&idFound.ulData1, 1, 4);
6512 ckDLSID->
Read(&idFound.usData2, 1, 2);
6513 ckDLSID->
Read(&idFound.usData3, 1, 2);
6514 ckDLSID->
Read(idFound.abData, 8, 1);
6515 if (memcmp(&idExpected, &idFound, 16) != 0)
6516 throw gig::Exception(
"dlsid mismatch for GigaPulse file: %s", path.c_str());
6518 poolFiles.push_back(pExtFile);
6519 ExtensionFiles.push_back(pExtFile);
6524 for (
int i = 0; i < poolFiles.size(); i++) {
6528 file_offset_t wvplFileOffset = wvpl->
GetFilePos() -
6534 if (wave->GetListType() == LIST_TYPE_WAVE) {
6537 const float subprogress = (float) iSampleIndex / (
float) iTotalSamples;
6538 __notify_progress(pProgress, subprogress);
6541 file_offset_t waveFileOffset = wave->GetFilePos();
6542 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - wvplFileOffset, i, iSampleIndex));
6551 __notify_progress(pProgress, 1.0);
6562 if (!pInstruments) LoadInstruments();
6563 if (!pInstruments)
return NULL;
6564 InstrumentsIterator = pInstruments->begin();
6565 return static_cast<gig::Instrument*
>( (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL );
6576 if (!pInstruments)
return NULL;
6577 InstrumentsIterator++;
6578 return static_cast<gig::Instrument*
>( (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL );
6590 if (!pInstruments) LoadInstruments();
6591 if (!pInstruments)
return 0;
6592 return pInstruments->size();
6603 if (!pInstruments) {
6609 __divide_progress(pProgress, &subprogress, 3.0f, 0.0f);
6610 __notify_progress(&subprogress, 0.0f);
6612 GetSample(0, &subprogress);
6613 __notify_progress(&subprogress, 1.0f);
6620 __notify_progress(&subprogress, 0.0f);
6621 LoadInstruments(&subprogress);
6622 __notify_progress(&subprogress, 1.0f);
6632 if (!pInstruments)
return NULL;
6633 if (index >= pInstruments->size())
return NULL;
6645 if (!pInstruments) LoadInstruments();
6646 __ensureMandatoryChunksExist();
6662 const size_t idxIt = InstrumentsIterator - pInstruments->begin();
6663 pInstruments->push_back(pInstrument);
6664 InstrumentsIterator = pInstruments->begin() + std::min(idxIt, pInstruments->size());
6701 static int iCallCount = -1;
6703 std::map<Group*,Group*> mGroups;
6704 std::map<Sample*,Sample*> mSamples;
6707 for (
int i = 0; pFile->
GetGroup(i); ++i) {
6708 Group* g = AddGroup();
6710 "COPY" + ToString(iCallCount) +
"_" + pFile->
GetGroup(i)->
Name;
6715 for (
int i = 0; pFile->
GetSample(i); ++i) {
6723 for (
size_t iGroup = 0; pFile->
GetScriptGroup(iGroup); ++iGroup) {
6726 dg->
Name =
"COPY" + ToString(iCallCount) +
"_" + sg->
Name;
6727 for (
int iScript = 0; sg->
GetScript(iScript); ++iScript) {
6741 Save(GetFileName());
6759 for (
int i = 0; pFile->
GetSample(i); ++i) {
6773 if (!pInstruments)
throw gig::Exception(
"Could not delete instrument as there are no instruments");
6774 InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), (
DLS::Instrument*) pInstrument);
6775 if (iter == pInstruments->end())
throw gig::Exception(
"Could not delete instrument, could not find given instrument");
6776 const size_t idxIt = InstrumentsIterator - pInstruments->begin();
6777 pInstruments->erase(iter);
6778 InstrumentsIterator = pInstruments->begin() + std::min(idxIt, pInstruments->size());
6783 void File::LoadInstruments() {
6784 LoadInstruments(NULL);
6787 void File::LoadInstruments(
progress_t* pProgress) {
6788 if (!pInstruments) pInstruments =
new InstrumentList;
6790 if (lstInstruments) {
6791 int iInstrumentIndex = 0;
6794 lstInstr; lstInstr = lstInstruments->
GetSubListAt(++i))
6796 if (lstInstr->GetListType() == LIST_TYPE_INS) {
6799 const float localProgress = (float) iInstrumentIndex / (
float) Instruments;
6800 __notify_progress(pProgress, localProgress);
6804 __divide_progress(pProgress, &subprogress, Instruments, iInstrumentIndex);
6806 pInstruments->push_back(
new Instrument(
this, lstInstr, &subprogress));
6808 pInstruments->push_back(
new Instrument(
this, lstInstr));
6815 __notify_progress(pProgress, 1.0);
6827 int iWaveIndex = GetWaveTableIndexOf(pSample);
6828 if (iWaveIndex < 0)
throw gig::Exception(
"Could not update crc, could not find sample");
6831 _3crc->
SetPos(iWaveIndex * 8);
6837 uint32_t File::GetSampleChecksum(
Sample* pSample) {
6839 int iWaveIndex = GetWaveTableIndexOf(pSample);
6840 if (iWaveIndex < 0)
throw gig::Exception(
"Could not retrieve reference crc of sample, could not resolve sample's wave table index");
6842 return GetSampleChecksumByIndex(iWaveIndex);
6845 uint32_t File::GetSampleChecksumByIndex(
int index) {
6846 if (index < 0)
throw gig::Exception(
"Could not retrieve reference crc of sample, invalid wave pool index of sample");
6849 if (!_3crc)
throw gig::Exception(
"Could not retrieve reference crc of sample, no checksums stored for this file yet");
6851 if (!pData)
throw gig::Exception(
"Could not retrieve reference crc of sample, no checksums stored for this file yet");
6854 size_t pos = index * 8;
6856 throw gig::Exception(
"Could not retrieve reference crc of sample, could not seek to required position in crc chunk");
6858 uint32_t one = load32(&pData[pos]);
6860 throw gig::Exception(
"Could not retrieve reference crc of sample, because reference checksum table is damaged");
6862 return load32(&pData[pos+4]);
6865 int File::GetWaveTableIndexOf(
gig::Sample* pSample) {
6866 if (!pSamples) GetSample(0);
6867 File::SampleList::iterator iter = pSamples->begin();
6868 File::SampleList::iterator end = pSamples->end();
6869 for (
int index = 0; iter != end; ++iter, ++index)
6870 if (*iter == pSample)
6883 if (!_3crc)
return false;
6886 if (!pSamples) GetSample(0);
6887 if (_3crc->
GetNewSize() != pSamples->size() * 8)
return false;
6889 const file_offset_t n = _3crc->
GetNewSize() / 8;
6892 if (!pData)
return false;
6894 for (file_offset_t i = 0; i < n; ++i) {
6895 uint32_t one = pData[i*2];
6896 if (one != 1)
return false;
6920 if (!pSamples) GetSample(0);
6922 bool bRequiresSave =
false;
6927 _3crc = pRIFF->
AddSubChunk(CHUNK_ID_3CRC, pSamples->size() * 8);
6930 if (einf && pVersion && pVersion->major > 2) pRIFF->
MoveSubChunk(_3crc, einf);
6931 bRequiresSave =
true;
6932 }
else if (_3crc->
GetNewSize() != pSamples->size() * 8) {
6933 _3crc->
Resize(pSamples->size() * 8);
6934 bRequiresSave =
true;
6937 if (bRequiresSave) {
6940 File::SampleList::iterator iter = pSamples->begin();
6941 File::SampleList::iterator end = pSamples->end();
6942 for (; iter != end; ++iter) {
6944 int index = GetWaveTableIndexOf(pSample);
6945 if (index < 0)
throw gig::Exception(
"Could not rebuild crc table for samples, wave table index of a sample could not be resolved");
6947 pData[index*2+1] = pSample->CalculateWaveDataChecksum();
6952 pRIFF->
SetMode(RIFF::stream_mode_read_write);
6954 File::SampleList::iterator iter = pSamples->begin();
6955 File::SampleList::iterator end = pSamples->end();
6956 for (; iter != end; ++iter) {
6958 int index = GetWaveTableIndexOf(pSample);
6959 if (index < 0)
throw gig::Exception(
"Could not rebuild crc table for samples, wave table index of a sample could not be resolved");
6960 pSample->
crc = pSample->CalculateWaveDataChecksum();
6961 SetSampleChecksum(pSample, pSample->
crc);
6966 return bRequiresSave;
6976 if (!pGroups) LoadGroups();
6978 GroupsIterator = pGroups->begin();
6979 return *GroupsIterator;
6989 if (!pGroups)
return NULL;
6991 return (GroupsIterator == pGroups->end()) ? NULL : *GroupsIterator;
7001 if (!pGroups) LoadGroups();
7002 if (index >= pGroups->size())
return NULL;
7003 return (*pGroups)[index];
7017 if (!pGroups) LoadGroups();
7024 Group* File::AddGroup() {
7025 if (!pGroups) LoadGroups();
7027 __ensureMandatoryChunksExist();
7029 pGroups->push_back(pGroup);
7043 if (!pGroups) LoadGroups();
7044 std::vector<Group*>::iterator iter =
7045 find(pGroups->begin(), pGroups->end(),
pGroup);
7046 if (iter == pGroups->end())
throw gig::Exception(
"Could not delete group, could not find given group");
7047 if (pGroups->size() == 1)
throw gig::Exception(
"Cannot delete group, there must be at least one default group!");
7050 while ((pSample = pGroup->
GetSample(0))) {
7051 DeleteSample(pSample);
7054 pGroups->erase(iter);
7070 if (!pGroups) LoadGroups();
7071 std::vector<Group*>::iterator iter =
7072 find(pGroups->begin(), pGroups->end(),
pGroup);
7073 if (iter == pGroups->end())
throw gig::Exception(
"Could not delete group, could not find given group");
7074 if (pGroups->size() == 1)
throw gig::Exception(
"Cannot delete group, there must be at least one default group!");
7077 pGroups->erase(iter);
7082 void File::LoadGroups() {
7083 if (!pGroups) pGroups =
new std::vector<Group*>;
7093 if (ck->GetChunkID() == CHUNK_ID_3GNM) {
7094 if (pVersion && pVersion->major > 2 &&
7095 strcmp(static_cast<char*>(ck->LoadChunkData()),
"") == 0)
break;
7097 pGroups->push_back(
new Group(
this, ck));
7103 if (!pGroups->size()) {
7105 pGroup->
Name =
"Default Group";
7106 pGroups->push_back(pGroup);
7118 if (!pScriptGroups) LoadScriptGroups();
7119 if (index >= pScriptGroups->size())
return NULL;
7120 return (*pScriptGroups)[index];
7132 if (!pScriptGroups) LoadScriptGroups();
7133 for (
size_t i = 0; i < pScriptGroups->size(); ++i) {
7149 if (!pScriptGroups) LoadScriptGroups();
7151 pScriptGroups->push_back(pScriptGroup);
7152 return pScriptGroup;
7168 if (!pScriptGroups) LoadScriptGroups();
7169 std::vector<ScriptGroup*>::iterator iter =
7170 find(pScriptGroups->begin(), pScriptGroups->end(), pScriptGroup);
7171 if (iter == pScriptGroups->end())
7172 throw gig::Exception(
"Could not delete script group, could not find given script group");
7173 pScriptGroups->erase(iter);
7174 for (
int i = 0; pScriptGroup->
GetScript(i); ++i)
7176 if (pScriptGroup->pList)
7179 delete pScriptGroup;
7182 void File::LoadScriptGroups() {
7183 if (pScriptGroups)
return;
7184 pScriptGroups =
new std::vector<ScriptGroup*>;
7191 if (lst->GetListType() == LIST_TYPE_RTIS) {
7192 pScriptGroups->push_back(
new ScriptGroup(
this, lst));
7210 bool newFile = pRIFF->
GetSubList(LIST_TYPE_INFO) == NULL;
7227 if (pScriptGroups) {
7229 for (std::vector<ScriptGroup*>::iterator it = pScriptGroups->begin();
7230 it != pScriptGroups->end(); ++it)
7232 (*it)->UpdateChunks(pProgress);
7251 if (first != info) {
7266 if (!_3gnl) _3gnl = _3gri->
AddSubList(LIST_TYPE_3GNL);
7270 if (pVersion && pVersion->major > 2) {
7277 ::SaveString(CHUNK_ID_3GNM, _3gnm, _3gnl,
"",
"",
true, 64);
7281 std::vector<Group*>::iterator iter = pGroups->begin();
7282 std::vector<Group*>::iterator end = pGroups->end();
7283 for (; iter != end; ++iter) {
7284 (*iter)->UpdateChunks(pProgress);
7304 int sublen = int(pSamples->size() / 8 + 49);
7305 int einfSize = (Instruments + 1) * sublen;
7309 if (einf->
GetSize() != einfSize) {
7313 }
else if (newFile) {
7314 einf = pRIFF->
AddSubChunk(CHUNK_ID_EINF, einfSize);
7319 std::map<gig::Sample*,int> sampleMap;
7320 size_t sampleIdx = 0;
7321 for (
Sample* pSample = GetSample(0); pSample;
7322 pSample = GetSample(++sampleIdx))
7324 sampleMap[pSample] = sampleIdx;
7327 int totnbusedsamples = 0;
7328 int totnbusedchannels = 0;
7329 int totnbregions = 0;
7330 int totnbdimregions = 0;
7332 int instrumentIdx = 0;
7334 memset(&pData[48], 0, sublen - 48);
7337 for (
Instrument* instrument = GetInstrument(iIns); instrument;
7338 instrument = GetInstrument(++iIns))
7340 int nbusedsamples = 0;
7341 int nbusedchannels = 0;
7342 int nbdimregions = 0;
7345 memset(&pData[(instrumentIdx + 1) * sublen + 48], 0, sublen - 48);
7348 for (
Region* region = instrument->GetRegionAt(iRgn); region;
7349 region = instrument->GetRegionAt(++iRgn))
7351 for (
int i = 0 ; i < region->DimensionRegions ; i++) {
7354 int sampleIdx = sampleMap[d->
pSample];
7355 int byte = 48 + sampleIdx / 8;
7356 int bit = 1 << (sampleIdx & 7);
7357 if ((pData[(instrumentIdx + 1) * sublen + byte] & bit) == 0) {
7358 pData[(instrumentIdx + 1) * sublen + byte] |= bit;
7362 if ((pData[byte] & bit) == 0) {
7371 nbdimregions += region->DimensionRegions;
7375 store32(&pData[(instrumentIdx + 1) * sublen + 4], nbusedchannels);
7376 store32(&pData[(instrumentIdx + 1) * sublen + 8], nbusedsamples);
7377 store32(&pData[(instrumentIdx + 1) * sublen + 12], 1);
7378 store32(&pData[(instrumentIdx + 1) * sublen + 16], instrument->Regions);
7379 store32(&pData[(instrumentIdx + 1) * sublen + 20], nbdimregions);
7380 store32(&pData[(instrumentIdx + 1) * sublen + 24], nbloops);
7382 store32(&pData[(instrumentIdx + 1) * sublen + 36], instrumentIdx);
7383 store32(&pData[(instrumentIdx + 1) * sublen + 40], (uint32_t) pSamples->size());
7386 totnbregions += instrument->Regions;
7387 totnbdimregions += nbdimregions;
7388 totnbloops += nbloops;
7393 store32(&pData[4], totnbusedchannels);
7394 store32(&pData[8], totnbusedsamples);
7395 store32(&pData[12], Instruments);
7396 store32(&pData[16], totnbregions);
7397 store32(&pData[20], totnbdimregions);
7398 store32(&pData[24], totnbloops);
7401 store32(&pData[40], (uint32_t) pSamples->size());
7421 _3crc->
Resize(pSamples->size() * 8);
7423 _3crc = pRIFF->
AddSubChunk(CHUNK_ID_3CRC, pSamples->size() * 8);
7425 if (einf && pVersion && pVersion->major > 2) pRIFF->
MoveSubChunk(_3crc, einf);
7428 uint32_t* pData = (uint32_t*) _3crc->LoadChunkData();
7430 File::SampleList::iterator iter = pSamples->begin();
7431 File::SampleList::iterator end = pSamples->end();
7432 for (
int index = 0; iter != end; ++iter, ++index) {
7435 pData[index*2+1] = pSample->
crc;
7445 for (
Instrument* instrument = GetInstrument(i); instrument;
7446 instrument = GetInstrument(++i))
7448 instrument->UpdateScriptFileOffsets();
7492 bool File::UsesAnyGigFormatExtension()
const {
7493 if (!pInstruments)
return false;
7494 InstrumentList::iterator iter = pInstruments->begin();
7495 InstrumentList::iterator end = pInstruments->end();
7496 for (; iter != end; ++iter) {
7498 if (pInstrument->UsesAnyGigFormatExtension())
7513 va_start(arg, format);
7514 Message = assemble(format, arg);
7518 Exception::Exception(String format, va_list arg) :
DLS::Exception() {
7519 Message = assemble(format, arg);
7522 void Exception::PrintMessage() {
7523 std::cout <<
"gig::Exception: " << Message << std::endl;
file_offset_t WriteUint32(uint32_t *pData, file_offset_t WordCount=1)
Writes WordCount number of 32 Bit unsigned integer words from the buffer pointed by pData to the chun...
void SetScriptAsText(const String &text)
Replaces the current script with the new script source code text given by text.
void AddContentOf(File *pFile)
Add content of another existing file.
void MoveAll()
Move all members of this group to another group (preferably the 1st one except this).
bool IsNew() const
Returns true if this file has been created new from scratch and has not been stored to disk yet...
file_offset_t position
Current position within the sample.
Encapsulates articulation informations of a dimension region.
range_t DimensionKeyRange
0-127 (where 0 means C1 and 127 means G9)
sample_loop_t * pSampleLoops
Points to the beginning of a sample loop array, or is NULL if there are no loops defined.
void SetDimensionType(dimension_t oldType, dimension_t newType)
Change type of an existing dimension.
bool reverse
If playback direction is currently backwards (in case there is a pingpong or reverse loop defined)...
Destination container for serialization, and source container for deserialization.
file_offset_t FrameOffset
Current offset (sample points) in current sample frame (for decompression only).
uint32_t Regions
Reflects the number of Region defintions this Instrument has.
Region * GetRegion(unsigned int Key)
Returns the appropriate Region for a triggered note.
void AddSample(Sample *pSample)
Move Sample given by pSample from another Group to this Group.
lfo_wave_t
Defines the wave form type used by an LFO (gig format extension).
String GetScriptAsText()
Returns the current script (i.e.
file_offset_t SamplePos
For compressed samples only: stores the current position (in sample points).
MidiRuleAlternator * AddMidiRuleAlternator()
Adds the alternator MIDI rule to the instrument.
Sample * AddSample()
Add a new sample.
file_offset_t SetPos(file_offset_t SampleCount, RIFF::stream_whence_t Whence=RIFF::stream_start)
Sets the position within the sample (in sample points, not in bytes).
Standard lowpass filter type (GigaStudio).
Parses DLS Level 1 and 2 compliant files and provides abstract access to the data.
void AddDimension(dimension_def_t *pDimDef)
Einstein would have dreamed of it - create a new dimension.
file_offset_t ReadUint16(uint16_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 16 Bit unsigned integer words and copies it into the buffer pointed by pDat...
stream_whence_t
File stream position dependent to these relations.
uint32_t FineTune
Specifies the fraction of a semitone up from the specified MIDI unity note field. A value of 0x800000...
file_offset_t SamplesPerFrame
For compressed samples only: number of samples in a full sample frame.
lfo1_ctrl_t
Defines how LFO1 is controlled by.
Group of Gigasampler samples.
uint32_t LoopType
Defines how the waveform samples will be looped (appropriate loop types for the gig format are define...
String Name
Stores the name of this Group.
DimensionRegion * GetDimensionRegionByBit(const uint8_t DimBits[8])
Returns the appropriate DimensionRegion for the given dimension bit numbers (zone index)...
Special dimension for triggering samples on releasing a key.
uint16_t PitchbendRange
Number of semitones pitchbend controller can pitch (default is 2).
Defines behavior options for envelope generators (gig format extension).
void SwapScriptSlots(size_t index1, size_t index2)
Flip two script slots with each other (gig format extension).
Script * AddScript()
Add new instrument script.
virtual void SetKeyRange(uint16_t Low, uint16_t High)
Modifies the key range of this Region and makes sure the respective chunks are in correct order...
uint32_t LoopSize
Caution: Use the respective fields in the DimensionRegion instead of this one! (Intended purpose: Len...
Instrument * AddInstrument()
Add a new instrument definition.
file_offset_t GetSize() const
Chunk size in bytes (without header, thus the chunk data body)
loop_type_t LoopType
Caution: Use the respective field in the DimensionRegion instead of this one! (Intended purpose: The ...
List * GetSubListAt(size_t pos)
Returns sublist chunk with list type ListType at supplied pos position among all subchunks of type Li...
Only internally controlled.
Sample * GetFirstSample()
Returns a pointer to the first Sample object of the file, NULL otherwise.
virtual void UpdateChunks(progress_t *pProgress)
Apply this script group to the respective RIFF chunks.
Will be thrown whenever a DLS specific error occurs while trying to access a DLS File.
MIDI rule for triggering notes by control change events.
file_offset_t ReadInt32(int32_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 32 Bit signed integer words and copies it into the buffer pointed by pData...
size_t CountInstruments()
Returns the total amount of instruments of this gig file.
virtual void CopyAssign(const Region *orig)
Make a (semi) deep copy of the Region object given by orig and assign it to this object.
void(* callback)(progress_t *)
Callback function pointer which has to be assigned to a function for progress notification.
file_offset_t WorstCaseFrameSize
For compressed samples only: size (in bytes) of the largest possible sample frame.
Instrument * GetInstrument(size_t index, progress_t *pProgress=NULL)
Returns the instrument with the given index.
file_offset_t Size
Size of the actual data in the buffer in bytes.
void AddScriptSlot(Script *pScript, bool bypass=false)
Add new instrument script slot (gig format extension).
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Instrument object.
static size_t Instances
Number of instances of class Sample.
dimension values are already the sought bit number
Group * GetGroup() const
Returns pointer to the Group this Sample belongs to.
Instrument * GetFirstInstrument()
Returns a pointer to the first Instrument object of the file, NULL otherwise.
void ReadString(String &s, int size)
Reads a null-padded string of size characters and copies it into the string s.
file_offset_t GetSize() const
Returns sample size.
Sample * GetSample(size_t index)
Returns Sample object at index of this sample group.
For MIDI tools like legato and repetition mode.
Group * GetGroup(size_t index)
Returns the group with the given index.
void CopyAssignWave(const Sample *orig)
Should be called after CopyAssignMeta() and File::Save() sequence.
uint32_t crc
Reflects CRC-32 checksum of the raw sample data at the last time when the sample's raw wave form data...
Defines a controller that has a certain contrained influence on a particular synthesis parameter (use...
sust_rel_trg_t
Defines behaviour of release triggered sample(s) on sustain pedal up event.
uint16_t Channels
Number of channels represented in the waveform data, e.g. 1 for mono, 2 for stereo (defaults to 1=mon...
void SetVCFVelocityScale(uint8_t scaling)
Updates the respective member variable and the lookup table / cache that depends on this value...
Defines Region information of a Gigasampler/GigaStudio instrument.
file_offset_t SamplesTotal
Reflects total number of sample points (only if known sample data format is used, 0 otherwise)...
uint32_t LoopPlayCount
Number of times the loop should be played (a value of 0 = infinite).
uint32_t MIDIUnityNote
Specifies the musical note at which the sample will be played at it's original sample rate...
ScriptGroup * GetScriptGroup(size_t index)
Get instrument script group (by index).
List * GetSubList(uint32_t ListType)
Returns sublist chunk with list type ListType within this chunk list.
void DeleteSubChunk(Chunk *pSubChunk)
Removes a sub chunk.
Defines Sample Loop Points.
Language_t Language
Programming language and dialect the script is written in.
void DeleteMidiRule(int i)
Deletes a MIDI rule from the instrument.
unsigned int Dimensions
Number of defined dimensions, do not alter!
Only controlled by external modulation wheel.
file_offset_t loop_cycles_left
How many times the loop has still to be passed, this value will be decremented with each loop cycle...
bool VerifySampleChecksumTable()
Checks whether the file's "3CRC" chunk was damaged.
MidiRuleCtrlTrigger * AddMidiRuleCtrlTrigger()
Adds the "controller trigger" MIDI rule to the instrument.
void RemoveScriptSlot(size_t index)
Remove script slot.
DimensionRegion * GetDimensionRegionByValue(const uint DimValues[8])
Use this method in your audio engine to get the appropriate dimension region with it's articulation d...
Compression_t Compression
Whether the script was/should be compressed, and if so, which compression algorithm shall be used...
Different samples triggered each time a note is played, any key advances the counter.
bool Dithered
For 24-bit compressed samples only: if dithering was used during compression with bit reduction...
Region * GetFirstRegion()
Returns the first Region of the instrument.
String libraryVersion()
Returns version of this C++ library.
uint8_t VelocityUpperLimit
Defines the upper velocity value limit of a velocity split (only if an user defined limit was set...
Will be thrown whenever a gig specific error occurs while trying to access a Gigasampler File...
buffer_t LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount)
Loads (and uncompresses if needed) the whole sample wave into RAM.
static const DLS::version_t VERSION_4
Reflects Gigasampler file format version 4.0 (2007-10-12).
void UpdateChunks(progress_t *pProgress)
Apply this script to the respective RIFF chunks.
void GenerateDLSID()
Generates a new DLSID for the resource.
void SetVCFCutoffController(vcf_cutoff_ctrl_t controller)
Updates the respective member variable and the lookup table / cache that depends on this value...
static const DLS::version_t VERSION_2
Reflects Gigasampler file format version 2.0 (1998-06-28).
Sample * pSample
Points to the Sample which is assigned to the dimension region.
uint FrameSize
Reflects the size (in bytes) of one single sample point (only if known sample data format is used...
buffer_t LoadSampleData()
Loads (and uncompresses if needed) the whole sample wave into RAM.
List * GetParent() const
Returns pointer to the chunk's parent list chunk.
uint32_t LoopStart
Caution: Use the respective field in the DimensionRegion instead of this one! (Intended purpose: The ...
Group * GetNextGroup()
Returns a pointer to the next Group object of the file, NULL otherwise.
void SetVCFVelocityCurve(curve_type_t curve)
Updates the respective member variable and the lookup table / cache that depends on this value...
Every subject of an DLS file and the file itself can have an unique, computer generated ID...
virtual void CopyAssign(const Sample *orig)
Make a deep copy of the Sample object given by orig and assign it to this object. ...
void SetAutoLoad(bool b)
Enable / disable automatic loading.
MidiRule * GetMidiRule(int i)
Returns a MIDI rule of the instrument.
Sine (sinus) wave form (this is the default wave form).
smpte_format_t SMPTEFormat
Specifies the Society of Motion Pictures and Television E time format used in the following SMPTEOffs...
uint16_t low
Low value of range.
bool ReleaseCancel
Whether the "release" stage is cancelled when receiving a note-on (default: true).
lfo3_ctrl_t
Defines how LFO3 is controlled by.
void SetFixedStringLengths(const string_length_t *lengths)
Forces specific Info fields to be of a fixed length when being saved to a file.
void RemoveScript(Script *pScript)
Remove reference to given Script (gig format extension).
file_offset_t Read(void *pData, file_offset_t WordCount, file_offset_t WordSize)
Reads WordCount number of data words with given WordSize and copies it into a buffer pointed by pData...
static buffer_t InternalDecompressionBuffer
Buffer used for decompression of samples, and only if no external decompression buffer was supplied...
static void DestroyDecompressionBuffer(buffer_t &DecompressionBuffer)
Free decompression buffer, previously created with CreateDecompressionBuffer().
Pointer address and size of a buffer.
bool Decay1Cancel
Whether the "decay 1" stage is cancelled when receiving a note-off (default: true).
dimension_t dimension
Specifies which source (usually a MIDI controller) is associated with the dimension.
bool Bypass
Global bypass: if enabled, this script shall not be executed by the sampler for any instrument...
virtual void DeleteChunks()
Remove all RIFF chunks associated with this ScriptGroup object.
Group * GetFirstGroup()
Returns a pointer to the first Group object of the file, NULL otherwise.
file_offset_t SetPos(file_offset_t Where, stream_whence_t Whence=stream_start)
Sets the position within the chunk body, thus within the data portion of the chunk (in bytes)...
String Name
Arbitrary name of the script, which may be displayed i.e. in an instrument editor.
Instrument * AddDuplicateInstrument(const Instrument *orig)
Add a duplicate of an existing instrument.
Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined).
bool Compressed
If the sample wave is compressed (probably just interesting for instrument and sample editors...
void ReleaseSampleData()
Frees the cached sample from RAM if loaded with LoadSampleData() previously.
uint32_t SampleLoops
Reflects the number of sample loops.
More poles than normal lowpass (GigaStudio).
void DeleteDimensionZone(dimension_t type, int zone)
Delete one split zone of a dimension (decrement zone amount).
void Resize(file_offset_t NewSize)
Resize sample.
The difference between none and none2 is unknown.
static buffer_t CreateDecompressionBuffer(file_offset_t MaxReadSize)
Allocates a decompression buffer for streaming (compressed) samples with Sample::Read().
virtual void UpdateFileOffsets()
Updates all file offsets stored all over the file.
size_t ScriptSlotCount() const
Instrument's amount of script slots.
void Resize(file_offset_t NewSize)
Resize sample.
Script * GetScript(size_t index)
Get instrument script.
uint16_t high
High value of range.
Sample * GetSample(size_t index, progress_t *pProgress=NULL)
Returns Sample object of index.
uint64_t file_offset_t
Type used by libgig for handling file positioning during file I/O tasks.
float __range_min
Only for internal usage, do not modify!
unsigned int Layers
Amount of defined layers (1 - 32). A value of 1 actually means no layering, a value > 1 means there i...
void * pStart
Points to the beginning of the buffer.
file_offset_t ReadUint32(uint32_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 32 Bit unsigned integer words and copies it into the buffer pointed by pDat...
Group * pGroup
pointer to the Group this sample belongs to (always not-NULL)
Chunk * GetSubChunk(uint32_t ChunkID)
Returns subchunk with chunk ID ChunkID within this chunk list.
file_offset_t GetPos() const
Returns the current position in the sample (in sample points).
MidiRuleLegato * AddMidiRuleLegato()
Adds the legato MIDI rule to the instrument.
bool IsScriptPatchVariableSet(size_t slot, String variable)
Checks whether a certain script 'patch' variable value is set.
void DeleteDimension(dimension_def_t *pDimDef)
Delete an existing dimension.
Instrument * GetNextInstrument()
Returns a pointer to the next Instrument object of the file, NULL otherwise.
void DeleteGroupOnly(Group *pGroup)
Delete a group.
uint16_t BitDepth
Size of each sample per channel (only if known sample data format is used, 0 otherwise).
std::array< uint8_t, 16 > _UUIDFromCArray(const uint8_t *pData)
type cast (by copy) uint8_t[16] -> std::array<uint8_t,16>
uint32_t LoopID
Specifies the unique ID that corresponds to one of the defined cue points in the cue point list (only...
void DeleteSample(Sample *pSample)
Delete a sample.
int GetFileOffsetSize() const
Returns the current size (in bytes) of file offsets stored in the headers of all chunks of this file...
static const DLS::version_t VERSION_3
Reflects Gigasampler file format version 3.0 (2003-03-31).
uint32_t LoopLength
Length of the looping area (in sample points).
uint8_t Uuid[16]
Persistent Universally Unique Identifier of this script, which remains identical after any changes to...
ScriptGroup * AddScriptGroup()
Add new instrument script group.
DimensionRegion * pDimensionRegions[256]
Pointer array to the 32 (gig2) or 256 (gig3) possible dimension regions (reflects NULL for dimension ...
uint32_t Product
Specifies the MIDI model ID defined by the manufacturer corresponding to the Manufacturer field...
split_type_t
Intended for internal usage: will be used to convert a dimension value into the corresponding dimensi...
Alternating loop (forward/backward, also known as Ping Pong)
file_offset_t RemainingBytes() const
Returns the number of bytes left to read in the chunk body.
bool RebuildSampleChecksumTable()
Recalculates CRC32 checksums for all samples and rebuilds this gig file's checksum table with those n...
void SetSampleChecksum(Sample *pSample, uint32_t crc)
Updates the 3crc chunk with the checksum of a sample.
Sample * GetNextSample()
Returns the next Sample of the Group.
Used for indicating the progress of a certain task.
file_offset_t ReadAndLoop(void *pBuffer, file_offset_t SampleCount, playback_state_t *pPlaybackState, DimensionRegion *pDimRgn, buffer_t *pExternalDecompressionBuffer=NULL)
Reads SampleCount number of sample points from the position stored in pPlaybackState into the buffer ...
file_offset_t Write(void *pData, file_offset_t WordCount, file_offset_t WordSize)
Writes WordCount number of data words with given WordSize from the buffer pointed by pData...
Region * GetRegionAt(size_t pos)
Returns Region at supplied pos position within the region list of this instrument.
uint32_t Loops
Caution: Use the respective field in the DimensionRegion instead of this one! (Intended purpose: Numb...
uint32_t GetListType() const
Returns unsigned integer representation of the list's ID.
uint32_t SMPTEOffset
The SMPTE Offset value specifies the time offset to be used for the synchronization / calibration to ...
file_offset_t ReadInt8(int8_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 8 Bit signed integer words and copies it into the buffer pointed by pData...
size_t CountSamples()
Returns the total amount of samples of this gig file.
Chunk * GetSubChunkAt(size_t pos)
Returns subchunk at supplied pos position within this chunk list.
uint32_t GetWaveDataCRC32Checksum()
Returns the CRC-32 checksum of the sample's raw wave form data at the time when this sample's wave fo...
unsigned long FileNo
File number (> 0 when sample is stored in an extension file, 0 when it's in the gig) ...
void SplitDimensionZone(dimension_t type, int zone)
Divide split zone of a dimension in two (increment zone amount).
Ordinary MIDI control change controller, see field 'controller_number'.
virtual void UpdateChunks(progress_t *pProgress)
Apply Instrument with all its Regions to the respective RIFF chunks.
vcf_type_t
Audio filter types.
Sample(File *pFile, RIFF::List *waveList, file_offset_t WavePoolOffset, unsigned long fileNo=0, int index=-1)
Constructor.
version_t * pVersion
Points to a version_t structure if the file provided a version number else is set to NULL...
void DeleteInstrument(Instrument *pInstrument)
Delete an instrument.
uint32_t LoopStart
The start value specifies the offset (in sample points) in the waveform data of the first sample poin...
virtual void UpdateChunks(progress_t *pProgress)
Update chunks with current group settings.
bool AttackHoldCancel
Whether the "attack hold" stage is cancelled when receiving a note-off (default: true).
String Name
Name of this script group. For example to be displayed in an instrument editor.
file_offset_t * FrameTable
For positioning within compressed samples only: stores the offset values for each frame...
file_offset_t Write(void *pBuffer, file_offset_t SampleCount)
Write sample wave data.
bool GetAutoLoad()
Returns whether automatic loading is enabled.
For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers).
void * LoadChunkData()
Load chunk body into RAM.
Different samples triggered each time a note is played, random order.
file_offset_t NullExtensionSize
The buffer might be bigger than the actual data, if that's the case that unused space at the end of t...
virtual void CopyAssign(const Region *orig)
Make a (semi) deep copy of the Region object given by orig and assign it to this object.
Abstract base class for all MIDI rules.
ScriptGroup * GetGroup() const
Returns the script group this script currently belongs to.
void SetVelocityResponseCurveScaling(uint8_t scaling)
Updates the respective member variable and the lookup table / cache that depends on this value...
virtual void UpdateChunks(progress_t *pProgress)
Apply all the gig file's current instruments, samples, groups and settings to the respective RIFF chu...
dimension_t
Defines the type of dimension, that is how the dimension zones (and thus how the dimension regions ar...
file_offset_t SamplesInLastFrame
For compressed samples only: length of the last sample frame.
uint32_t LoopEnd
Caution: Use the respective field in the DimensionRegion instead of this one! (Intended purpose: The ...
bool AttackCancel
Whether the "attack" stage is cancelled when receiving a note-off (default: true).
Different samples triggered each time a note is played, dimension regions selected in sequence...
dimension_def_t pDimensionDefinitions[8]
Defines the five (gig2) or eight (gig3) possible dimensions (the dimension's controller and number of...
uint8_t zones
Number of zones the dimension has.
String GetScriptPatchVariable(size_t slot, String variable)
Get overridden initial value for 'patch' variable.
Effect 5 Depth (MIDI Controller 95)
No release triggered sample(s) are played on sustain pedal up (default).
void GenerateUuid()
Generate a new Universally Unique Identifier (UUID) for this script.
buffer_t GetCache()
Returns current cached sample points.
void SetVCFVelocityDynamicRange(uint8_t range)
Updates the respective member variable and the lookup table / cache that depends on this value...
vcf_cutoff_ctrl_t
Defines how the filter cutoff frequency is controlled by.
void Resize(file_offset_t NewSize)
Resize chunk.
Encapsulates sample waves of Gigasampler/GigaStudio files used for playback.
virtual void SetGain(int32_t gain)
Updates the respective member variable and updates SampleAttenuation which depends on this value...
Sample * GetSample(size_t index)
Returns Sample object of index.
List * AddSubList(uint32_t uiListType)
Creates a new list sub chunk.
Group(File *file, RIFF::Chunk *ck3gnm)
Constructor.
file_offset_t Read(void *pBuffer, file_offset_t SampleCount, buffer_t *pExternalDecompressionBuffer=NULL)
Reads SampleCount number of sample points from the current position into the buffer pointed by pBuffe...
virtual void UpdateChunks(progress_t *pProgress)
Apply all sample player options to the respective RIFF chunk.
dimension value between 0-127
virtual void UpdateChunks(progress_t *pProgress)
Apply dimension region settings to the respective RIFF chunks.
String Software
<ISFT-ck>. Identifies the name of the sofware package used to create the file.
Sample * GetNextSample()
Returns a pointer to the next Sample object of the file, NULL otherwise.
String ArchivalLocation
<IARL-ck>. Indicates where the subject of the file is stored.
file_offset_t GetNewSize() const
New chunk size if it was modified with Resize(), otherwise value returned will be equal to GetSize()...
Encapsulates sample waves used for playback.
virtual void UpdateChunks(progress_t *pProgress)
Apply Instrument with all its Regions to the respective RIFF chunks.
type_t type
Controller type.
uint controller_number
MIDI controller number if this controller is a control change controller, 0 otherwise.
uint8_t * VelocityTable
For velocity dimensions with custom defined zone ranges only: used for fast converting from velocity ...
void MoveSubChunk(Chunk *pSrc, Chunk *pDst)
Moves a sub chunk witin this list.
uint32_t SamplesPerSecond
Sampling rate at which each channel should be played (defaults to 44100 if Sample was created with In...
File * GetFile() const
Returns pointer to the chunk's File object.
A MIDI rule not yet implemented by libgig.
std::map< String, String > GetScriptPatchVariables(size_t slot)
Get all overridden script 'patch' variables.
size_t CountSubChunks()
Returns number of subchunks within the list (including list chunks).
Real-time instrument script (gig format extension).
bool SetMode(stream_mode_t NewMode)
Change file access mode.
void SetVelocityResponseDepth(uint8_t depth)
Updates the respective member variable and the lookup table / cache that depends on this value...
Gigasampler/GigaStudio specific classes and definitions.
float __range_max
Only for internal usage, do not modify!
uint8_t DimensionUpperLimits[8]
gig3: defines the upper limit of the dimension values for this dimension region. In case you wondered...
Script * GetScriptOfSlot(size_t index)
Get instrument script (gig format extension).
virtual void CopyAssign(const DimensionRegion *orig)
Make a (semi) deep copy of the DimensionRegion object given by orig and assign it to this object...
virtual void UpdateChunks(progress_t *pProgress)
Apply Region settings and all its DimensionRegions to the respective RIFF chunks. ...
uint32_t LoopFraction
The fractional value specifies a fraction of a sample at which to loop. This allows a loop to be fine...
bool IsScriptSlotBypassed(size_t index)
Whether script execution shall be skipped.
uint32_t TruncatedBits
For 24-bit compressed samples only: number of bits truncated during compression (0, 4 or 6)
void CopyAssignCore(const Sample *orig)
Make a deep copy of the Sample object given by orig (without the actual sample waveform data however)...
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Group object.
void SetScriptSlotBypassed(size_t index, bool bBypass)
Defines whether execution shall be skipped.
Group of instrument scripts (gig format extension).
file_offset_t GetFilePos() const
Current, actual offset in file of current chunk data body read/write position.
Only internally controlled.
Provides convenient access to Gigasampler/GigaStudio .gig files.
void SetGroup(ScriptGroup *pGroup)
Move this script from its current ScriptGroup to another ScriptGroup given by pGroup.
lfo2_ctrl_t
Defines how LFO2 is controlled by.
Dimension for keyswitching.
MIDI rule for instruments with legato samples.
virtual ~Group()
Destructor.
void SetReleaseVelocityResponseDepth(uint8_t depth)
Updates the respective member variable and the lookup table / cache that depends on this value...
virtual void UpdateChunks(progress_t *pProgress)
Apply sample and its settings to the respective RIFF chunks.
Sample * GetFirstSample()
Returns the first Sample of this Group.
dimension_def_t * GetDimensionDefinition(dimension_t type)
Searches in the current Region for a dimension of the given dimension type and returns the precise co...
bool VerifyWaveData(uint32_t *pActually=NULL)
Checks the integrity of this sample's raw audio wave data.
file_offset_t GetCurrentFileSize() const
Returns the current size of this file (in bytes) as it is currently yet stored on disk...
Provides all neccessary information for the synthesis of a DLS Instrument.
Provides access to a Gigasampler/GigaStudio instrument.
void SetScriptPatchVariable(size_t slot, String variable, String value)
Override initial value for 'patch' variable.
void UnsetScriptPatchVariable(ssize_t slot=-1, String variable="")
Drop overridden initial value(s) for 'patch' variable(s).
void DeleteGroup(Group *pGroup)
Delete a group and its samples.
Encoding_t Encoding
Format the script's source code text is encoded with.
buffer_t RAMCache
Buffers samples (already uncompressed) in RAM.
virtual void CopyAssign(const Instrument *orig)
Make a (semi) deep copy of the Instrument object given by orig and assign it to this object...
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Sample object.
String libraryName()
Returns the name of this C++ library.
Quadtuple version number ("major.minor.release.build").
bool Decay2Cancel
Whether the "decay 2" stage is cancelled when receiving a note-off (default: true).
void MoveTo(Instrument *dst)
Move this instrument at the position before.
uint32_t SamplePeriod
Specifies the duration of time that passes during the playback of one sample in nanoseconds (normally...
void CopyAssign(const Script *orig)
Make a (semi) deep copy of the Script object given by orig and assign it to this object.
curve_type_t
Defines the shape of a function graph.
uint8_t bits
Number of "bits" (1 bit = 2 splits/zones, 2 bit = 4 splits/zones, 3 bit = 8 splits/zones,...).
file_offset_t GetPos() const
Current read/write position within the chunk data body (starting with 0).
No MIDI controller assigned for filter resonance.
virtual void SetKeyRange(uint16_t Low, uint16_t High)
Modifies the key range of this Region and makes sure the respective chunks are in correct order...
DLS specific classes and definitions.
Info * pInfo
Points (in any case) to an Info object, providing additional, optional infos and comments.
uint32_t Manufacturer
Specifies the MIDI Manufacturer's Association (MMA) Manufacturer code for the sampler intended to rec...
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Region object.
file_offset_t ReadInt16(int16_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 16 Bit signed integer words and copies it into the buffer pointed by pData...
MIDI rule to automatically cycle through specified sequences of different articulations.
Reflects the current playback state for a sample.
void DeleteChunks()
Remove all RIFF chunks associated with this Script object.
General dimension definition.
void CopyAssignMeta(const Sample *orig)
Make a (semi) deep copy of the Sample object given by orig (without the actual waveform data) and ass...
No MIDI controller assigned for filter cutoff frequency.
split_type_t split_type
Intended for internal usage: will be used to convert a dimension value into the corresponding dimensi...
virtual void UpdateChunks(progress_t *pProgress)
Apply Region settings to the respective RIFF chunks.
void DeleteScript(Script *pScript)
Delete an instrument script.
If used sample has more than one channel (thus is not mono).
virtual void UpdateChunks(progress_t *pProgress)
Apply sample and its settings to the respective RIFF chunks.
void SetReleaseVelocityResponseCurve(curve_type_t curve)
Updates the respective member variable and the lookup table / cache that depends on this value...
file_offset_t ReadUint8(uint8_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 8 Bit unsigned integer words and copies it into the buffer pointed by pData...
Defines Region information of an Instrument.
Effect 4 Depth (MIDI Controller 94)
double GetVelocityAttenuation(uint8_t MIDIKeyVelocity)
Returns the correct amplitude factor for the given MIDIKeyVelocity.
Sample * GetSample()
Returns pointer address to the Sample referenced with this region.
void SetVelocityResponseCurve(curve_type_t curve)
Updates the respective member variable and the lookup table / cache that depends on this value...
Chunk * AddSubChunk(uint32_t uiChunkID, file_offset_t ullBodySize)
Creates a new sub chunk.
void DeleteScriptGroup(ScriptGroup *pGroup)
Delete an instrument script group.
Region * GetNextRegion()
Returns the next Region of the instrument.
virtual void UpdateChunks(progress_t *pProgress)
Apply all the DLS file's current instruments, samples and settings to the respective RIFF chunks...
virtual void UpdateFileOffsets()
Updates all file offsets stored all over the file.