27 #include "Serialization.h"
36 #define GIG_FILE_EXT_VERSION 2
43 #define INITIAL_SAMPLE_BUFFER_SIZE 512000
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() {
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::list<Group*>::iterator iter = pFile->pGroups->begin();
613 std::list<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());
677 ((pCkData->
RemainingBytes() - headerSize[mode]) << 3) / bitsPerSample[mode];
682 pCkData->
SetPos(frameSize, RIFF::stream_curpos);
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;
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;
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) {
1752 pEGOpts[i]->AttackCancel =
byte & 1;
1753 pEGOpts[i]->AttackHoldCancel =
byte & (1 << 1);
1754 pEGOpts[i]->Decay1Cancel =
byte & (1 << 2);
1755 pEGOpts[i]->Decay2Cancel =
byte & (1 << 3);
1756 pEGOpts[i]->ReleaseCancel =
byte & (1 << 4);
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));
1814 DimensionRegion::DimensionRegion(
RIFF::List* _3ewl,
const DimensionRegion& src) :
DLS::Sampler(_3ewl) {
1818 pParentList = _3ewl;
1821 if (src.VelocityTable) {
1822 VelocityTable =
new uint8_t[128];
1823 for (
int k = 0 ; k < 128 ; k++)
1824 VelocityTable[k] = src.VelocityTable[k];
1826 if (src.pSampleLoops) {
1828 for (
int k = 0 ; k < src.SampleLoops ; k++)
1829 pSampleLoops[k] = src.pSampleLoops[k];
1871 pRegion = pOriginalRegion;
1875 if (pOriginalRegion->GetParent()->GetParent() != orig->pRegion->GetParent()->GetParent()) {
1879 if (mSamples && mSamples->count(orig->
pSample)) {
1886 for (
int k = 0 ; k < 128 ; k++)
2001 DLS::Sampler::SetGain(gain);
2021 pData[13] = Crossfade.
in_end;
2023 pData[15] = Crossfade.
out_end;
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);
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);
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 =
2082 pData[45] = eg1ctrloptions;
2084 const uint8_t eg2ctl = (uint8_t) EncodeLeverageController(
EG2Controller);
2087 const uint8_t eg2ctrloptions =
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);
2107 const int32_t eg2release = (int32_t) GIG_EXP_ENCODE(
EG2Release);
2108 store32(&pData[64], eg2release);
2114 const int32_t lfo2freq = (int32_t) GIG_EXP_ENCODE(
LFO2Frequency);
2115 store32(&pData[72], lfo2freq);
2122 store32(&pData[80], eg1decay2);
2129 store32(&pData[88], eg2decay2);
2142 velocityresponse += 5;
2145 velocityresponse += 10;
2149 throw Exception(
"Could not update DimensionRegion's chunk, unknown VelocityResponseCurve selected");
2151 pData[96] = velocityresponse;
2161 releasevelocityresponse += 5;
2164 releasevelocityresponse += 10;
2168 throw Exception(
"Could not update DimensionRegion's chunk, unknown ReleaseVelocityResponseCurve selected");
2170 pData[97] = releasevelocityresponse;
2184 uint8_t pitchTrackDimensionBypass = GIG_PITCH_TRACK_ENCODE(
PitchTrack);
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;
2214 pData[112] = lfo3ctrl;
2218 pData[113] = attenctl;
2225 pData[114] = lfo2ctrl;
2234 pData[115] = lfo1ctrl;
2238 : uint16_t(((-
EG3Depth) - 1) ^ 0xfff);
2239 store16(&pData[116], eg3depth);
2244 pData[120] = channeloffset;
2247 uint8_t regoptions = 0;
2250 pData[121] = regoptions;
2263 const uint8_t eg1hold = (
EG1Hold) ? 0x80 : 0x00;
2264 pData[131] = eg1hold;
2266 const uint8_t vcfcutoff = (
VCFEnabled ? 0x80 : 0x00) |
2268 pData[132] = vcfcutoff;
2274 pData[134] = vcfvelscale;
2280 pData[136] = vcfresonance;
2284 pData[137] = vcfbreakpoint;
2288 pData[138] = vcfvelocity;
2291 pData[139] = vcftype;
2293 if (chunksize >= 148) {
2300 const int lsdeSize =
2304 if (!lsde && UsesAnyGigFormatExtension()) {
2308 lsde = pParentList->
AddSubChunk(CHUNK_ID_LSDE, lsdeSize);
2316 unsigned char* pData = (
unsigned char*) lsde->
LoadChunkData();
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);
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);
2341 store32(&pData[24], flags);
2345 static_assert(lsdeSize == 28,
"Inconsistency in assumed 'LSDE' RIFF chunk size");
2364 bool DimensionRegion::UsesAnyGigFormatExtension()
const {
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) {
2461 leverage_ctrl_t decodedcontroller;
2462 switch (EncodedController) {
2464 case _lev_ctrl_none:
2466 decodedcontroller.controller_number = 0;
2468 case _lev_ctrl_velocity:
2470 decodedcontroller.controller_number = 0;
2472 case _lev_ctrl_channelaftertouch:
2474 decodedcontroller.controller_number = 0;
2478 case _lev_ctrl_modwheel:
2480 decodedcontroller.controller_number = 1;
2482 case _lev_ctrl_breath:
2484 decodedcontroller.controller_number = 2;
2486 case _lev_ctrl_foot:
2488 decodedcontroller.controller_number = 4;
2490 case _lev_ctrl_effect1:
2492 decodedcontroller.controller_number = 12;
2494 case _lev_ctrl_effect2:
2496 decodedcontroller.controller_number = 13;
2498 case _lev_ctrl_genpurpose1:
2500 decodedcontroller.controller_number = 16;
2502 case _lev_ctrl_genpurpose2:
2504 decodedcontroller.controller_number = 17;
2506 case _lev_ctrl_genpurpose3:
2508 decodedcontroller.controller_number = 18;
2510 case _lev_ctrl_genpurpose4:
2512 decodedcontroller.controller_number = 19;
2514 case _lev_ctrl_portamentotime:
2516 decodedcontroller.controller_number = 5;
2518 case _lev_ctrl_sustainpedal:
2520 decodedcontroller.controller_number = 64;
2522 case _lev_ctrl_portamento:
2524 decodedcontroller.controller_number = 65;
2526 case _lev_ctrl_sostenutopedal:
2528 decodedcontroller.controller_number = 66;
2530 case _lev_ctrl_softpedal:
2532 decodedcontroller.controller_number = 67;
2534 case _lev_ctrl_genpurpose5:
2536 decodedcontroller.controller_number = 80;
2538 case _lev_ctrl_genpurpose6:
2540 decodedcontroller.controller_number = 81;
2542 case _lev_ctrl_genpurpose7:
2544 decodedcontroller.controller_number = 82;
2546 case _lev_ctrl_genpurpose8:
2548 decodedcontroller.controller_number = 83;
2550 case _lev_ctrl_effect1depth:
2552 decodedcontroller.controller_number = 91;
2554 case _lev_ctrl_effect2depth:
2556 decodedcontroller.controller_number = 92;
2558 case _lev_ctrl_effect3depth:
2560 decodedcontroller.controller_number = 93;
2562 case _lev_ctrl_effect4depth:
2564 decodedcontroller.controller_number = 94;
2566 case _lev_ctrl_effect5depth:
2568 decodedcontroller.controller_number = 95;
2574 case _lev_ctrl_CC3_EXT:
2576 decodedcontroller.controller_number = 3;
2578 case _lev_ctrl_CC6_EXT:
2580 decodedcontroller.controller_number = 6;
2582 case _lev_ctrl_CC7_EXT:
2584 decodedcontroller.controller_number = 7;
2586 case _lev_ctrl_CC8_EXT:
2588 decodedcontroller.controller_number = 8;
2590 case _lev_ctrl_CC9_EXT:
2592 decodedcontroller.controller_number = 9;
2594 case _lev_ctrl_CC10_EXT:
2596 decodedcontroller.controller_number = 10;
2598 case _lev_ctrl_CC11_EXT:
2600 decodedcontroller.controller_number = 11;
2602 case _lev_ctrl_CC14_EXT:
2604 decodedcontroller.controller_number = 14;
2606 case _lev_ctrl_CC15_EXT:
2608 decodedcontroller.controller_number = 15;
2610 case _lev_ctrl_CC20_EXT:
2612 decodedcontroller.controller_number = 20;
2614 case _lev_ctrl_CC21_EXT:
2616 decodedcontroller.controller_number = 21;
2618 case _lev_ctrl_CC22_EXT:
2620 decodedcontroller.controller_number = 22;
2622 case _lev_ctrl_CC23_EXT:
2624 decodedcontroller.controller_number = 23;
2626 case _lev_ctrl_CC24_EXT:
2628 decodedcontroller.controller_number = 24;
2630 case _lev_ctrl_CC25_EXT:
2632 decodedcontroller.controller_number = 25;
2634 case _lev_ctrl_CC26_EXT:
2636 decodedcontroller.controller_number = 26;
2638 case _lev_ctrl_CC27_EXT:
2640 decodedcontroller.controller_number = 27;
2642 case _lev_ctrl_CC28_EXT:
2644 decodedcontroller.controller_number = 28;
2646 case _lev_ctrl_CC29_EXT:
2648 decodedcontroller.controller_number = 29;
2650 case _lev_ctrl_CC30_EXT:
2652 decodedcontroller.controller_number = 30;
2654 case _lev_ctrl_CC31_EXT:
2656 decodedcontroller.controller_number = 31;
2658 case _lev_ctrl_CC68_EXT:
2660 decodedcontroller.controller_number = 68;
2662 case _lev_ctrl_CC69_EXT:
2664 decodedcontroller.controller_number = 69;
2666 case _lev_ctrl_CC70_EXT:
2668 decodedcontroller.controller_number = 70;
2670 case _lev_ctrl_CC71_EXT:
2672 decodedcontroller.controller_number = 71;
2674 case _lev_ctrl_CC72_EXT:
2676 decodedcontroller.controller_number = 72;
2678 case _lev_ctrl_CC73_EXT:
2680 decodedcontroller.controller_number = 73;
2682 case _lev_ctrl_CC74_EXT:
2684 decodedcontroller.controller_number = 74;
2686 case _lev_ctrl_CC75_EXT:
2688 decodedcontroller.controller_number = 75;
2690 case _lev_ctrl_CC76_EXT:
2692 decodedcontroller.controller_number = 76;
2694 case _lev_ctrl_CC77_EXT:
2696 decodedcontroller.controller_number = 77;
2698 case _lev_ctrl_CC78_EXT:
2700 decodedcontroller.controller_number = 78;
2702 case _lev_ctrl_CC79_EXT:
2704 decodedcontroller.controller_number = 79;
2706 case _lev_ctrl_CC84_EXT:
2708 decodedcontroller.controller_number = 84;
2710 case _lev_ctrl_CC85_EXT:
2712 decodedcontroller.controller_number = 85;
2714 case _lev_ctrl_CC86_EXT:
2716 decodedcontroller.controller_number = 86;
2718 case _lev_ctrl_CC87_EXT:
2720 decodedcontroller.controller_number = 87;
2722 case _lev_ctrl_CC89_EXT:
2724 decodedcontroller.controller_number = 89;
2726 case _lev_ctrl_CC90_EXT:
2728 decodedcontroller.controller_number = 90;
2730 case _lev_ctrl_CC96_EXT:
2732 decodedcontroller.controller_number = 96;
2734 case _lev_ctrl_CC97_EXT:
2736 decodedcontroller.controller_number = 97;
2738 case _lev_ctrl_CC102_EXT:
2740 decodedcontroller.controller_number = 102;
2742 case _lev_ctrl_CC103_EXT:
2744 decodedcontroller.controller_number = 103;
2746 case _lev_ctrl_CC104_EXT:
2748 decodedcontroller.controller_number = 104;
2750 case _lev_ctrl_CC105_EXT:
2752 decodedcontroller.controller_number = 105;
2754 case _lev_ctrl_CC106_EXT:
2756 decodedcontroller.controller_number = 106;
2758 case _lev_ctrl_CC107_EXT:
2760 decodedcontroller.controller_number = 107;
2762 case _lev_ctrl_CC108_EXT:
2764 decodedcontroller.controller_number = 108;
2766 case _lev_ctrl_CC109_EXT:
2768 decodedcontroller.controller_number = 109;
2770 case _lev_ctrl_CC110_EXT:
2772 decodedcontroller.controller_number = 110;
2774 case _lev_ctrl_CC111_EXT:
2776 decodedcontroller.controller_number = 111;
2778 case _lev_ctrl_CC112_EXT:
2780 decodedcontroller.controller_number = 112;
2782 case _lev_ctrl_CC113_EXT:
2784 decodedcontroller.controller_number = 113;
2786 case _lev_ctrl_CC114_EXT:
2788 decodedcontroller.controller_number = 114;
2790 case _lev_ctrl_CC115_EXT:
2792 decodedcontroller.controller_number = 115;
2794 case _lev_ctrl_CC116_EXT:
2796 decodedcontroller.controller_number = 116;
2798 case _lev_ctrl_CC117_EXT:
2800 decodedcontroller.controller_number = 117;
2802 case _lev_ctrl_CC118_EXT:
2804 decodedcontroller.controller_number = 118;
2806 case _lev_ctrl_CC119_EXT:
2808 decodedcontroller.controller_number = 119;
2814 decodedcontroller.controller_number = 0;
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;
2840 switch (DecodedController.controller_number) {
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;
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 =
3158 pVelocityAttenuationTable =
3170 pVelocityAttenuationTable =
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);
3302 Region::Region(Instrument* pInstrument,
RIFF::List* rgnList) :
DLS::Region((
DLS::Instrument*) pInstrument, rgnList) {
3305 for (
int i = 0; i < 256; i++) {
3306 pDimensionRegions[i] = NULL;
3309 File* file = (File*) GetParent()->GetParent();
3310 int dimensionBits = (file->pVersion && file->pVersion->major > 2) ? 8 : 5;
3314 if (!file->GetAutoLoad())
return;
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();
3356 if (file->pVersion && file->pVersion->major > 2)
3362 if (file->GetAutoLoad()) {
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);
3384 pDimensionRegions[0] =
new DimensionRegion(
this, _3ewl);
3385 DimensionRegions = 1;
3414 File* pFile = (
File*) GetParent()->GetParent();
3416 const int iMaxDimensions = versiongt2 ? 8 : 5;
3417 const int iMaxDimensionRegions = versiongt2 ? 256 : 32;
3422 const int _3lnkChunkSize = versiongt2 ? 1092 : 172;
3423 _3lnk = pCkRegion->
AddSubChunk(CHUNK_ID_3LNK, _3lnkChunkSize);
3434 for (
int i = 0; i < iMaxDimensions; i++) {
3446 const int iWavePoolOffset = versiongt2 ? 68 : 44;
3447 for (uint i = 0; i < iMaxDimensionRegions; i++) {
3448 int iWaveIndex = -1;
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) {
3460 store32(&pData[iWavePoolOffset + i * 4], iWaveIndex);
3470 if (versiongt2 && !UsesAnyGigFormatExtension()) {
3473 if (!_3dnm) _3dnm = pCkRegion->
AddSubList(LIST_TYPE_3DNM);
3477 if (!_3ddp) _3ddp = pCkRegion->
AddSubChunk(CHUNK_ID_3DDP, 16);
3479 for (
int i = 0; i < 16; i += 4) {
3480 store32(&pData[i], 0xFFFFFFFF);
3497 void Region::LoadDimensionRegions(
RIFF::List* rgn) {
3500 int dimensionRegionNr = 0;
3505 dimensionRegionNr++;
3509 if (dimensionRegionNr == 0)
throw gig::Exception(
"No dimension region found.");
3520 void Region::UpdateVelocityTable() {
3529 if (veldim == -1)
return;
3546 table =
new uint8_t[128];
3550 int velocityZone = 0;
3552 for (
int k = i ; k < end ; k += step) {
3554 for (; tableidx <= d->DimensionUpperLimits[veldim] ; tableidx++) table[tableidx] = velocityZone;
3558 for (
int k = i ; k < end ; k += step) {
3560 for (; tableidx <= d->VelocityUpperLimit ; tableidx++) table[tableidx] = velocityZone;
3575 if (j == veldim) i += skipveldim;
3609 if (pDimDef->
zones < 2)
3610 throw gig::Exception(
"Could not add new dimension, amount of requested zones must always be at least two");
3611 if (pDimDef->
bits < 1)
3612 throw gig::Exception(
"Could not add new dimension, amount of requested requested zone bits must always be at least one");
3614 if (pDimDef->
zones != 2)
3615 throw gig::Exception(
"Could not add new 'sample channel' dimensions, the requested amount of zones must always be 2 for this dimension type");
3616 if (pDimDef->
bits != 1)
3617 throw gig::Exception(
"Could not add new 'sample channel' dimensions, the requested amount of zone bits must always be 1 for this dimension type");
3621 File* file = (
File*) GetParent()->GetParent();
3622 const int iMaxDimensions = (file->
pVersion && file->
pVersion->major > 2) ? 8 : 5;
3624 throw gig::Exception(
"Could not add new dimension, max. amount of " + ToString(iMaxDimensions) +
" dimensions already reached");
3626 int iCurrentBits = 0;
3629 if (iCurrentBits >= iMaxDimensions)
3630 throw gig::Exception(
"Could not add new dimension, max. amount of " + ToString(iMaxDimensions) +
" dimension bits already reached");
3631 const int iNewBits = iCurrentBits + pDimDef->
bits;
3632 if (iNewBits > iMaxDimensions)
3633 throw gig::Exception(
"Could not add new dimension, new dimension would exceed max. amount of " + ToString(iMaxDimensions) +
" dimension bits");
3637 throw gig::Exception(
"Could not add new dimension, there is already a dimension of the same type");
3644 for (
int i = 0 ; i < pos ; i++)
3649 for (
int i = 0 ; i < (1 << iCurrentBits) ; i++) {
3670 for (
int i = (1 << iCurrentBits) - (1 << bitpos) ; i >= 0 ; i -= (1 << bitpos)) {
3671 for (
int k = 0 ; k < (1 << bitpos) ; k++) {
3674 for (
int j = 1 ; j < (1 << pDimDef->
bits) ; j++) {
3675 for (
int k = 0 ; k < (1 << bitpos) ; k++) {
3677 if (moveTo) _3prg->
MoveSubChunk(pNewDimRgnListChunk, moveTo);
3690 int mask = (1 << bitpos) - 1;
3691 for (
int z = 0 ; z < pDimDef->
zones ; z++) {
3692 uint8_t upperLimit = uint8_t((z + 1) * 128.0 / pDimDef->
zones - 1);
3693 for (
int i = 0 ; i < 1 << iCurrentBits ; i++) {
3705 UpdateVelocityTable();
3721 int iDimensionNr = -1;
3728 if (iDimensionNr < 0)
throw gig::Exception(
"Invalid dimension_def_t pointer");
3732 for (
int i = 0; i < iDimensionNr; i++)
3737 for (
int i = iDimensionNr + 1; i <
Dimensions; i++)
3744 for (
int iUpperBit = 0; iUpperBit < 1 << iUpperBits; iUpperBit++) {
3746 for (
int iLowerBit = 0; iLowerBit < 1 << iLowerBits; iLowerBit++) {
3748 iObsoleteBit << iLowerBits |
3761 for (
int iFrom = 2, iTo = 1; iFrom < 256 && iTo < 256 - 1; iTo++) {
3763 if (iFrom <= iTo) iFrom = iTo + 1;
3775 for (
int i = iDimensionNr + 1; i <
Dimensions; i++) {
3782 for (
int i = iDimensionNr + 1; i <
Dimensions; i++) {
3812 throw gig::Exception(
"Could not delete dimension zone, no such dimension of given type");
3813 if (oldDef->
zones <= 2)
3814 throw gig::Exception(
"Could not delete dimension zone, because it would end up with only one zone.");
3815 if (zone < 0 || zone >= oldDef->
zones)
3816 throw gig::Exception(
"Could not delete dimension zone, requested zone index out of bounds.");
3818 const int newZoneSize = oldDef->
zones - 1;
3827 RIFF::List* pCkInstrument = instr->pCkInstrument;
3829 if (!lrgn) lrgn = pCkInstrument->
AddSubList(LIST_TYPE_LRGN);
3831 tempRgn =
new Region(instr, rgn);
3843 def.
zones = newZoneSize;
3852 int tempReducedDimensionIndex = -1;
3853 for (
int d = 0; d < tempRgn->
Dimensions; ++d) {
3855 tempReducedDimensionIndex = d;
3861 for (
int iDst = 0; iDst < 256; ++iDst) {
3863 if (!dstDimRgn)
continue;
3864 std::map<dimension_t,int> dimCase;
3865 bool isValidZone =
true;
3866 for (
int d = 0, baseBits = 0; d < tempRgn->
Dimensions; ++d) {
3869 (iDst >> baseBits) & ((1 << dstBits) - 1);
3870 baseBits += dstBits;
3873 isValidZone =
false;
3877 if (!isValidZone)
continue;
3880 const bool isLastZone = (dimCase[type] == newZoneSize - 1);
3881 if (dimCase[type] >= zone) dimCase[type]++;
3898 std::vector<dimension_def_t> oldDefs;
3903 for (
int i = 0; i < oldDefs.size(); ++i) {
3910 for (
int iSrc = 0; iSrc < 256; ++iSrc) {
3912 if (!srcDimRgn)
continue;
3913 std::map<dimension_t,int> dimCase;
3914 for (
int d = 0, baseBits = 0; d < tempRgn->
Dimensions; ++d) {
3917 (iSrc >> baseBits) & ((1 << srcBits) - 1);
3918 baseBits += srcBits;
3923 if (!dstDimRgn)
continue;
3931 UpdateVelocityTable();
3951 throw gig::Exception(
"Could not split dimension zone, no such dimension of given type");
3952 if (zone < 0 || zone >= oldDef->
zones)
3953 throw gig::Exception(
"Could not split dimension zone, requested zone index out of bounds.");
3955 const int newZoneSize = oldDef->
zones + 1;
3964 RIFF::List* pCkInstrument = instr->pCkInstrument;
3966 if (!lrgn) lrgn = pCkInstrument->
AddSubList(LIST_TYPE_LRGN);
3968 tempRgn =
new Region(instr, rgn);
3980 def.
zones = newZoneSize;
3981 if ((1 << oldDef->
bits) < newZoneSize) def.
bits++;
3989 int tempIncreasedDimensionIndex = -1;
3990 for (
int d = 0; d < tempRgn->
Dimensions; ++d) {
3992 tempIncreasedDimensionIndex = d;
3998 for (
int iSrc = 0; iSrc < 256; ++iSrc) {
4000 if (!srcDimRgn)
continue;
4001 std::map<dimension_t,int> dimCase;
4002 bool isValidZone =
true;
4003 for (
int d = 0, baseBits = 0; d <
Dimensions; ++d) {
4006 (iSrc >> baseBits) & ((1 << srcBits) - 1);
4009 isValidZone =
false;
4012 baseBits += srcBits;
4014 if (!isValidZone)
continue;
4017 if (dimCase[type] > zone) dimCase[type]++;
4023 if (dimCase[type] == zone) {
4030 std::map<dimension_t,int> lowerCase = dimCase;
4052 std::vector<dimension_def_t> oldDefs;
4057 for (
int i = 0; i < oldDefs.size(); ++i) {
4064 for (
int iSrc = 0; iSrc < 256; ++iSrc) {
4066 if (!srcDimRgn)
continue;
4067 std::map<dimension_t,int> dimCase;
4068 for (
int d = 0, baseBits = 0; d < tempRgn->
Dimensions; ++d) {
4071 (iSrc >> baseBits) & ((1 << srcBits) - 1);
4072 baseBits += srcBits;
4077 if (!dstDimRgn)
continue;
4085 UpdateVelocityTable();
4103 if (oldType == newType)
return;
4106 throw gig::Exception(
"No dimension with provided old dimension type exists on this region");
4108 throw gig::Exception(
"Cannot change to dimension type 'sample channel', because existing dimension does not have 2 zones");
4110 throw gig::Exception(
"There is already a dimension with requested new dimension type on this region");
4112 def->
split_type = __resolveSplitType(newType);
4116 uint8_t bits[8] = {};
4117 for (std::map<dimension_t,int>::const_iterator it = DimCase.begin();
4118 it != DimCase.end(); ++it)
4122 bits[d] = it->second;
4123 goto nextDimCaseSlice;
4150 for (
int i = 0; i < 256; i++) {
4190 if (DimValues[i] <=
pDimensionRegions[bits << bitpos]->DimensionUpperLimits[i])
break;
4199 bits = DimValues[i] & limiter_mask;
4202 dimregidx |= bits << bitpos;
4207 if (!dimreg)
return NULL;
4216 dimregidx |= (bits & limiter_mask) << velbitpos;
4222 int Region::GetDimensionRegionIndexByValue(
const uint DimValues[8]) {
4239 if (DimValues[i] <=
pDimensionRegions[bits << bitpos]->DimensionUpperLimits[i])
break;
4248 bits = DimValues[i] & limiter_mask;
4251 dimregidx |= bits << bitpos;
4257 if (!dimreg)
return -1;
4260 if (dimreg->VelocityTable)
4266 dimregidx |= (bits & limiter_mask) << velbitpos;
4302 if (pSample)
return static_cast<gig::Sample*
>(pSample);
4303 else return static_cast<gig::Sample*
>(pSample = GetSampleFromWavePool(WavePoolTableIndex));
4306 Sample* Region::GetSampleFromWavePool(
unsigned int WavePoolTableIndex,
progress_t* pProgress) {
4307 if ((int32_t)WavePoolTableIndex == -1)
return NULL;
4308 File* file = (
File*) GetParent()->GetParent();
4309 if (!file->pWavePoolTable)
return NULL;
4310 if (WavePoolTableIndex + 1 > file->WavePoolCount)
return NULL;
4314 uint64_t soughtoffset =
4315 uint64_t(file->pWavePoolTable[WavePoolTableIndex]) |
4316 uint64_t(file->pWavePoolTableHi[WavePoolTableIndex]) << 32;
4319 if (sample->ullWavePoolOffset == soughtoffset)
4325 file_offset_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
4326 file_offset_t soughtfileno = file->pWavePoolTableHi[WavePoolTableIndex];
4329 if (sample->ullWavePoolOffset == soughtoffset &&
4330 sample->FileNo == soughtfileno)
return static_cast<gig::Sample*
>(sample);
4361 if (mSamples && mSamples->count((
gig::Sample*)orig->pSample)) {
4362 pSample = mSamples->find((
gig::Sample*)orig->pSample)->second;
4376 for (
int i = 0; i < 256; i++) {
4400 bool Region::UsesAnyGigFormatExtension()
const {
4401 for (
int i = 0; i < 256; i++) {
4414 MidiRuleCtrlTrigger::MidiRuleCtrlTrigger(
RIFF::Chunk* _3ewg) {
4420 for (
int i = 0 ; i <
Triggers ; i++) {
4421 pTriggers[i].TriggerPoint = _3ewg->
ReadUint8();
4422 pTriggers[i].Descending = _3ewg->
ReadUint8();
4423 pTriggers[i].VelSensitivity = _3ewg->
ReadUint8();
4425 pTriggers[i].NoteOff = _3ewg->
ReadUint8();
4426 pTriggers[i].Velocity = _3ewg->
ReadUint8();
4427 pTriggers[i].OverridePedal = _3ewg->
ReadUint8();
4432 MidiRuleCtrlTrigger::MidiRuleCtrlTrigger() :
4433 ControllerNumber(0),
4437 void MidiRuleCtrlTrigger::UpdateChunks(uint8_t* pData)
const {
4442 for (
int i = 0 ; i <
Triggers ; i++) {
4443 pData[46 + i * 8] = pTriggers[i].TriggerPoint;
4444 pData[47 + i * 8] = pTriggers[i].Descending;
4445 pData[48 + i * 8] = pTriggers[i].VelSensitivity;
4446 pData[49 + i * 8] = pTriggers[i].Key;
4447 pData[50 + i * 8] = pTriggers[i].NoteOff;
4448 pData[51 + i * 8] = pTriggers[i].Velocity;
4449 pData[52 + i * 8] = pTriggers[i].OverridePedal;
4453 MidiRuleLegato::MidiRuleLegato(
RIFF::Chunk* _3ewg) {
4472 MidiRuleLegato::MidiRuleLegato() :
4474 BypassUseController(false),
4476 BypassController(1),
4479 ReleaseTriggerKey(0),
4486 void MidiRuleLegato::UpdateChunks(uint8_t* pData)
const {
4502 MidiRuleAlternator::MidiRuleAlternator(
RIFF::Chunk* _3ewg) {
4508 Selector = (flags & 2) ? selector_controller :
4509 (flags & 1) ? selector_key_switch : selector_none;
4522 for (
int i = 0 ; i < n ; i++) {
4527 for (
int i = 0 ; i < n ; i++) {
4534 MidiRuleAlternator::MidiRuleAlternator() :
4537 Selector(selector_none),
4542 PlayRange.low = PlayRange.high = 0;
4543 KeySwitchRange.low = KeySwitchRange.high = 0;
4546 void MidiRuleAlternator::UpdateChunks(uint8_t* pData)
const {
4551 (
Selector == selector_controller ? 2 :
4552 (
Selector == selector_key_switch ? 1 : 0));
4561 char* str =
reinterpret_cast<char*
>(pData);
4564 for (
int i = 0 ; i < n ; i++, pos += 32) {
4570 for (
int i = 0 ; i < n ; i++, pos += 49) {
4571 strncpy(&str[pos],
pPatterns[i].Name.c_str(), 16);
4573 memcpy(&pData[pos + 16], &(
pPatterns[i][0]), 32);
4580 Script::Script(ScriptGroup* group,
RIFF::Chunk* ckScri) {
4594 Name.resize(nameSize,
' ');
4595 for (
int i = 0; i < nameSize; ++i)
4598 if (headerSize >= 6*
sizeof(int32_t) + nameSize + 16) {
4599 for (uint i = 0; i < 16; ++i) {
4606 ckScri->
SetPos(
sizeof(int32_t) + headerSize);
4608 uint32_t scriptSize = uint32_t(ckScri->
GetSize() - ckScri->
GetPos());
4609 data.resize(scriptSize);
4610 for (
int i = 0; i < scriptSize; ++i)
4618 Name =
"Unnamed Script";
4631 s.resize(data.size(),
' ');
4632 memcpy(&s[0], &data[0], data.size());
4643 data.resize(text.size());
4644 memcpy(&data[0], &text[0], text.size());
4671 __calculateCRC(&data[0], data.size(), crc);
4674 const file_offset_t chunkSize =
4675 (file_offset_t) 7*
sizeof(int32_t) +
Name.size() + 16 + data.size();
4676 if (!pChunk) pChunk = pGroup->pList->
AddSubChunk(CHUNK_ID_SCRI, chunkSize);
4677 else pChunk->
Resize(chunkSize);
4681 store32(&pData[pos], uint32_t(6*
sizeof(int32_t) +
Name.size() + 16));
4682 pos +=
sizeof(int32_t);
4684 pos +=
sizeof(int32_t);
4686 pos +=
sizeof(int32_t);
4688 pos +=
sizeof(int32_t);
4689 store32(&pData[pos],
Bypass ? 1 : 0);
4690 pos +=
sizeof(int32_t);
4691 store32(&pData[pos], crc);
4692 pos +=
sizeof(int32_t);
4693 store32(&pData[pos], (uint32_t)
Name.size());
4694 pos +=
sizeof(int32_t);
4695 for (
int i = 0; i <
Name.size(); ++i, ++pos)
4696 pData[pos] =
Name[i];
4697 for (
int i = 0; i < 16; ++i, ++pos)
4698 pData[pos] =
Uuid[i];
4699 for (
int i = 0; i < data.size(); ++i, ++pos)
4700 pData[pos] = data[i];
4709 Uuid[0] = dlsid.ulData1 & 0xff;
4710 Uuid[1] = dlsid.ulData1 >> 8 & 0xff;
4711 Uuid[2] = dlsid.ulData1 >> 16 & 0xff;
4712 Uuid[3] = dlsid.ulData1 >> 24 & 0xff;
4713 Uuid[4] = dlsid.usData2 & 0xff;
4714 Uuid[5] = dlsid.usData2 >> 8 & 0xff;
4715 Uuid[6] = dlsid.usData3 & 0xff;
4716 Uuid[7] = dlsid.usData3 >> 8 & 0xff;
4717 Uuid[8] = dlsid.abData[0];
4718 Uuid[9] = dlsid.abData[1];
4719 Uuid[10] = dlsid.abData[2];
4720 Uuid[11] = dlsid.abData[3];
4721 Uuid[12] = dlsid.abData[4];
4722 Uuid[13] = dlsid.abData[5];
4723 Uuid[14] = dlsid.abData[6];
4724 Uuid[15] = dlsid.abData[7];
4734 if (this->pGroup == pGroup)
return;
4737 this->pGroup = pGroup;
4766 void Script::RemoveAllScriptReferences() {
4767 File* pFile = pGroup->pFile;
4777 ScriptGroup::ScriptGroup(File* file,
RIFF::List* lstRTIS) {
4783 ::LoadString(ckName,
Name);
4785 Name =
"Default Group";
4789 ScriptGroup::~ScriptGroup() {
4791 std::list<Script*>::iterator iter = pScripts->begin();
4792 std::list<Script*>::iterator end = pScripts->end();
4793 while (iter != end) {
4828 ::SaveString(CHUNK_ID_LSNM, NULL, pList,
Name, String(
"Unnamed Group"),
true, 64);
4830 for (std::list<Script*>::iterator it = pScripts->begin();
4831 it != pScripts->end(); ++it)
4833 (*it)->UpdateChunks(pProgress);
4846 if (!pScripts) LoadScripts();
4847 std::list<Script*>::iterator it = pScripts->begin();
4848 for (uint i = 0; it != pScripts->end(); ++i, ++it)
4849 if (i == index)
return *it;
4865 if (!pScripts) LoadScripts();
4867 pScripts->push_back(pScript);
4882 if (!pScripts) LoadScripts();
4883 std::list<Script*>::iterator iter =
4884 find(pScripts->begin(), pScripts->end(), pScript);
4885 if (iter == pScripts->end())
4886 throw gig::Exception(
"Could not delete script, could not find given script");
4887 pScripts->erase(iter);
4888 pScript->RemoveAllScriptReferences();
4889 if (pScript->pChunk)
4894 void ScriptGroup::LoadScripts() {
4895 if (pScripts)
return;
4896 pScripts =
new std::list<Script*>;
4902 if (ck->GetChunkID() == CHUNK_ID_SCRI) {
4903 pScripts->push_back(
new Script(
this, ck));
4911 Instrument::Instrument(File* pFile,
RIFF::List* insList, progress_t* pProgress) :
DLS::Instrument((
DLS::File*)pFile, insList) {
4912 static const DLS::Info::string_length_t fixedStringLengths[] = {
4913 { CHUNK_ID_INAM, 64 },
4914 { CHUNK_ID_ISFT, 12 },
4917 pInfo->SetFixedStringLengths(fixedStringLengths);
4920 for (
int i = 0; i < 128; i++) RegionKeyTable[i] = NULL;
4925 PianoReleaseMode =
false;
4926 DimensionKeyRange.low = 0;
4927 DimensionKeyRange.high = 0;
4928 pMidiRules =
new MidiRule*[3];
4929 pMidiRules[0] = NULL;
4943 uint8_t dimkeystart = _3ewg->
ReadUint8();
4944 PianoReleaseMode = dimkeystart & 0x01;
4945 DimensionKeyRange.low = dimkeystart >> 1;
4946 DimensionKeyRange.high = _3ewg->
ReadUint8();
4957 pMidiRules[i++] =
new MidiRuleCtrlTrigger(_3ewg);
4958 }
else if (id1 == 0) {
4959 pMidiRules[i++] =
new MidiRuleLegato(_3ewg);
4960 }
else if (id1 == 3) {
4961 pMidiRules[i++] =
new MidiRuleAlternator(_3ewg);
4963 pMidiRules[i++] =
new MidiRuleUnknown;
4966 else if (id1 != 0 || id2 != 0) {
4967 pMidiRules[i++] =
new MidiRuleUnknown;
4971 pMidiRules[i] = NULL;
4976 if (pFile->GetAutoLoad()) {
4977 if (!pRegions) pRegions =
new RegionList;
4984 __notify_progress(pProgress, (
float) pRegions->size() / (
float) Regions);
4985 pRegions->push_back(
new Region(
this, rgn));
4990 UpdateRegionKeyTable();
5006 ckSCSL->
SetPos(headerSize);
5007 int unknownSpace = slotSize - 2*
sizeof(uint32_t);
5008 for (
int i = 0; i < slotCount; ++i) {
5009 _ScriptPooolEntry e;
5012 if (unknownSpace) ckSCSL->
SetPos(unknownSpace, RIFF::stream_curpos);
5013 scriptPoolFileOffsets.push_back(e);
5024 for (
int iScript = 0; iScript < nScripts; ++iScript) {
5026 for (
int i = 0; i < 16; ++i)
5031 for (
int iVar = 0; iVar < nVars; ++iVar) {
5041 for (
int i = 0; i < len; ++i)
5044 for (
int i = 0; i < len; ++i)
5047 scriptVars[uuid][slot][name] = value;
5051 ckSCPV->
SetPos(pos + blobSize);
5058 __notify_progress(pProgress, 1.0f);
5061 void Instrument::UpdateRegionKeyTable() {
5063 RegionList::iterator iter = pRegions->begin();
5064 RegionList::iterator end = pRegions->end();
5065 for (; iter != end; ++iter) {
5067 const int low = std::max(
int(pRegion->
KeyRange.
low), 0);
5068 const int high = std::min(
int(pRegion->
KeyRange.
high), 127);
5069 for (
int iKey = low; iKey <= high; iKey++) {
5076 for (
int i = 0 ; pMidiRules[i] ; i++) {
5077 delete pMidiRules[i];
5079 delete[] pMidiRules;
5080 if (pScriptRefs)
delete pScriptRefs;
5099 RegionList::iterator iter = pRegions->begin();
5100 RegionList::iterator end = pRegions->end();
5101 for (; iter != end; ++iter)
5102 (*iter)->UpdateChunks(pProgress);
5107 if (!lart) lart = pCkInstrument->
AddSubList(LIST_TYPE_LART);
5120 store16(&pData[0], EffectSend);
5124 const uint8_t dimkeystart = (PianoReleaseMode ? 0x01 : 0x00) |
5126 pData[10] = dimkeystart;
5129 if (pMidiRules[0] == 0 && _3ewg->
GetSize() >= 34) {
5133 for (
int i = 0 ; pMidiRules[i] ; i++) {
5134 pMidiRules[i]->UpdateChunks(pData);
5145 if (!lst3LS) lst3LS = pCkInstrument->
AddSubList(LIST_TYPE_3LS);
5148 const int slotCount = (int) pScriptRefs->size();
5149 const int headerSize = 3 *
sizeof(uint32_t);
5150 const int slotSize = 2 *
sizeof(uint32_t);
5151 const int totalChunkSize = headerSize + slotCount * slotSize;
5153 if (!ckSCSL) ckSCSL = lst3LS->
AddSubChunk(CHUNK_ID_SCSL, totalChunkSize);
5154 else ckSCSL->
Resize(totalChunkSize);
5157 store32(&pData[pos], headerSize);
5158 pos +=
sizeof(uint32_t);
5159 store32(&pData[pos], slotCount);
5160 pos +=
sizeof(uint32_t);
5161 store32(&pData[pos], slotSize);
5162 pos +=
sizeof(uint32_t);
5163 for (
int i = 0; i < slotCount; ++i) {
5166 int bogusFileOffset = 0;
5167 store32(&pData[pos], bogusFileOffset);
5168 pos +=
sizeof(uint32_t);
5169 store32(&pData[pos], (*pScriptRefs)[i].bypass ? 1 : 0);
5170 pos +=
sizeof(uint32_t);
5182 _VarsByScript vars = stripScriptVars();
5183 if (!vars.empty()) {
5188 size_t totalChunkSize = 4;
5189 size_t totalScriptsOverridden = 0;
5190 for (
const auto& script : vars) {
5191 for (
const auto& slot : script.second) {
5192 totalScriptsOverridden++;
5193 totalChunkSize += 16 + 4 + 4 + 4;
5194 for (
const auto& var : slot.second) {
5195 totalChunkSize += 4 + 2 + var.first.length() +
5196 2 + var.second.length();
5203 if (!ckSCPV) ckSCPV = lst3LS->
AddSubChunk(CHUNK_ID_SCPV, totalChunkSize);
5204 else ckSCPV->
Resize(totalChunkSize);
5209 store32(&pData[pos], (uint32_t) totalScriptsOverridden);
5211 for (
const auto& script : vars) {
5212 for (
const auto& slot : script.second) {
5213 for (
int i = 0; i < 16; ++i)
5214 pData[pos+i] = script.first[i];
5216 store32(&pData[pos], (uint32_t) slot.first);
5218 store32(&pData[pos], (uint32_t) 0);
5220 store32(&pData[pos], (uint32_t) slot.second.size());
5222 for (
const auto& var : slot.second) {
5225 store16(&pData[pos], 2 + var.first.size() + 2 + var.second.size());
5227 store16(&pData[pos], var.first.size());
5229 for (
int i = 0; i < var.first.size(); ++i)
5230 pData[pos++] = var.first[i];
5231 store16(&pData[pos], var.second.size());
5233 for (
int i = 0; i < var.second.size(); ++i)
5234 pData[pos++] = var.second[i];
5251 void Instrument::UpdateScriptFileOffsets() {
5253 if (pScriptRefs && pScriptRefs->size() > 0) {
5256 const int slotCount = (int) pScriptRefs->size();
5257 const int headerSize = 3 *
sizeof(uint32_t);
5258 ckSCSL->
SetPos(headerSize);
5259 for (
int i = 0; i < slotCount; ++i) {
5260 uint32_t fileOffset = uint32_t(
5261 (*pScriptRefs)[i].script->pChunk->GetFilePos() -
5262 (*pScriptRefs)[i].script->pChunk->GetPos() -
5267 ckSCSL->
SetPos(
sizeof(uint32_t), RIFF::stream_curpos);
5280 if (!pRegions || pRegions->empty() || Key > 127)
return NULL;
5298 if (!pRegions)
return NULL;
5299 RegionsIterator = pRegions->begin();
5300 return static_cast<gig::Region*
>( (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL );
5312 if (!pRegions)
return NULL;
5314 return static_cast<gig::Region*
>( (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL );
5317 Region* Instrument::AddRegion() {
5320 if (!lrgn) lrgn = pCkInstrument->
AddSubList(LIST_TYPE_LRGN);
5323 pRegions->push_back(pNewRegion);
5324 Regions = (uint32_t) pRegions->size();
5326 UpdateRegionKeyTable();
5331 void Instrument::DeleteRegion(Region* pRegion) {
5332 if (!pRegions)
return;
5333 DLS::Instrument::DeleteRegion((
DLS::Region*) pRegion);
5335 UpdateRegionKeyTable();
5366 if (dst && GetParent() != dst->GetParent())
5368 "gig::Instrument::MoveTo() can only be used for moving within "
5369 "the same gig file."
5376 File::InstrumentList& list = *pFile->pInstruments;
5378 File::InstrumentList::iterator itFrom =
5379 std::find(list.begin(), list.end(),
static_cast<DLS::Instrument*
>(
this));
5381 File::InstrumentList::iterator itTo =
5382 std::find(list.begin(), list.end(),
static_cast<DLS::Instrument*
>(dst));
5384 list.splice(itTo, list, itFrom);
5390 this->pCkInstrument,
5391 (
RIFF::Chunk*) ((dst) ? dst->pCkInstrument : NULL)
5406 return pMidiRules[i];
5415 delete pMidiRules[0];
5428 delete pMidiRules[0];
5441 delete pMidiRules[0];
5454 delete pMidiRules[i];
5458 void Instrument::LoadScripts() {
5459 if (pScriptRefs)
return;
5460 pScriptRefs =
new std::vector<_ScriptPooolRef>;
5461 if (scriptPoolFileOffsets.empty())
return;
5463 for (uint k = 0; k < scriptPoolFileOffsets.size(); ++k) {
5464 uint32_t soughtOffset = scriptPoolFileOffsets[k].fileOffset;
5467 for (uint s = 0; group->
GetScript(s); ++s) {
5469 if (script->pChunk) {
5470 uint32_t offset = uint32_t(
5472 script->pChunk->
GetPos() -
5475 if (offset == soughtOffset)
5477 _ScriptPooolRef ref;
5478 ref.script = script;
5479 ref.bypass = scriptPoolFileOffsets[k].bypass;
5480 pScriptRefs->push_back(ref);
5488 scriptPoolFileOffsets.clear();
5505 if (index >= pScriptRefs->size())
return NULL;
5506 return pScriptRefs->at(index).script;
5546 _ScriptPooolRef ref = { pScript, bypass };
5547 pScriptRefs->push_back(ref);
5566 if (index1 >= pScriptRefs->size() || index2 >= pScriptRefs->size())
5568 _ScriptPooolRef tmp = (*pScriptRefs)[index1];
5569 (*pScriptRefs)[index1] = (*pScriptRefs)[index2];
5570 (*pScriptRefs)[index2] = tmp;
5581 if (index >= pScriptRefs->size())
return;
5582 pScriptRefs->erase( pScriptRefs->begin() + index );
5599 for (ssize_t i = pScriptRefs->size() - 1; i >= 0; --i) {
5600 if ((*pScriptRefs)[i].script == pScript) {
5601 pScriptRefs->erase( pScriptRefs->begin() + i );
5621 return uint(pScriptRefs ? pScriptRefs->size() : scriptPoolFileOffsets.size());
5642 return pScriptRefs ? pScriptRefs->at(index).bypass
5643 : scriptPoolFileOffsets.at(index).bypass;
5663 pScriptRefs->at(index).bypass = bBypass;
5665 scriptPoolFileOffsets.at(index).bypass = bBypass;
5670 std::array<uint8_t,16> uuid;
5671 memcpy(&uuid[0], pData, 16);
5679 bool Instrument::ReferencesScriptWithUuid(
const _UUID& uuid) {
5681 for (uint iSlot = 0; iSlot < nSlots; ++iSlot)
5707 if (variable.empty())
return false;
5709 if (!script)
return false;
5711 if (!scriptVars.count(uuid))
return false;
5712 const _VarsBySlot& slots = scriptVars.find(uuid)->second;
5713 if (slots.empty())
return false;
5714 if (slots.count(slot))
5715 return slots.find(slot)->second.count(variable);
5717 return slots.begin()->second.count(variable);
5742 if (!script)
return std::map<String,String>();
5744 if (!scriptVars.count(uuid))
return std::map<String,String>();
5745 const _VarsBySlot& slots = scriptVars.find(uuid)->second;
5746 if (slots.empty())
return std::map<String,String>();
5747 const _PatchVars& vars =
5748 (slots.count(slot)) ?
5749 slots.find(slot)->second : slots.begin()->second;
5774 return (vars.count(variable)) ? vars.find(variable)->second :
"";
5800 if (variable.empty())
5801 throw Exception(
"Variable name must not be empty");
5804 throw Exception(
"No script slot with index " + ToString(slot));
5806 scriptVars[uuid][slot][variable] = value;
5844 if (slot != -1 && !variable.empty()) {
5845 if (!script)
return;
5847 if (!scriptVars.count(uuid))
return;
5848 if (!scriptVars[uuid].count(slot))
return;
5849 if (scriptVars[uuid][slot].count(variable))
5850 scriptVars[uuid][slot].erase(
5851 scriptVars[uuid][slot].find(variable)
5853 if (scriptVars[uuid][slot].empty())
5854 scriptVars[uuid].erase( scriptVars[uuid].find(slot) );
5855 if (scriptVars[uuid].empty())
5856 scriptVars.erase( scriptVars.find(uuid) );
5861 if (slot == -1 && variable.empty()) {
5868 if (!script)
return;
5870 if (scriptVars.count(uuid))
5871 scriptVars.erase( scriptVars.find(uuid) );
5876 _VarsByScript::iterator itScript = scriptVars.begin();
5877 _VarsByScript::iterator endScript = scriptVars.end();
5878 while (itScript != endScript) {
5879 _VarsBySlot& slots = itScript->second;
5880 _VarsBySlot::iterator itSlot = slots.begin();
5881 _VarsBySlot::iterator endSlot = slots.end();
5882 while (itSlot != endSlot) {
5883 _PatchVars& vars = itSlot->second;
5884 if (vars.count(variable))
5885 vars.erase( vars.find(variable) );
5887 slots.erase(itSlot++);
5892 scriptVars.erase(itScript++);
5905 Instrument::_VarsByScript Instrument::stripScriptVars() {
5907 _VarsByScript::const_iterator itScript = scriptVars.begin();
5908 _VarsByScript::const_iterator endScript = scriptVars.end();
5909 for (; itScript != endScript; ++itScript) {
5910 const _UUID& uuid = itScript->first;
5911 if (!ReferencesScriptWithUuid(uuid))
5913 const _VarsBySlot& slots = itScript->second;
5914 _VarsBySlot::const_iterator itSlot = slots.begin();
5915 _VarsBySlot::const_iterator endSlot = slots.end();
5916 for (; itSlot != endSlot; ++itSlot) {
5918 if (!script)
continue;
5920 if (itSlot->second.empty())
continue;
5921 vars[uuid][itSlot->first] = itSlot->second;
5951 DLS::Instrument::CopyAssignCore(orig);
5955 EffectSend = orig->EffectSend;
5958 PianoReleaseMode = orig->PianoReleaseMode;
5960 scriptPoolFileOffsets = orig->scriptPoolFileOffsets;
5962 if (pScriptRefs)
delete pScriptRefs;
5963 pScriptRefs =
new std::vector<_ScriptPooolRef>;
5964 if (orig->pScriptRefs)
5965 *pScriptRefs = *orig->pScriptRefs;
5966 scriptVars = orig->scriptVars;
5969 for (
int i = 0 ; pMidiRules[i] ; i++) {
5970 delete pMidiRules[i];
5973 pMidiRules[0] = NULL;
5979 RegionList::const_iterator it = orig->pRegions->begin();
5980 for (
int i = 0; i < orig->
Regions; ++i, ++it) {
5981 Region* dstRgn = AddRegion();
5990 UpdateRegionKeyTable();
6006 bool Instrument::UsesAnyGigFormatExtension()
const {
6007 if (!pRegions)
return false;
6008 if (!scriptVars.empty())
return true;
6009 RegionList::const_iterator iter = pRegions->begin();
6010 RegionList::const_iterator end = pRegions->end();
6011 for (; iter != end; ++iter) {
6013 if (rgn->UsesAnyGigFormatExtension())
6031 pNameChunk = ck3gnm;
6032 ::LoadString(pNameChunk,
Name);
6068 _3gri = pFile->pRIFF->
AddSubList(LIST_TYPE_3GRI);
6072 if (!_3gnl) _3gnl = _3gri->
AddSubList(LIST_TYPE_3GNL);
6077 if (strcmp(
static_cast<char*
>(ck->LoadChunkData()),
"") == 0) {
6085 ::SaveString(CHUNK_ID_3GNM, pNameChunk, _3gnl,
Name, String(
"Unnamed Group"),
true, 64);
6102 if (pSample->GetGroup() ==
this)
return pSample;
6120 if (pSample->GetGroup() ==
this)
return pSample;
6140 Group* pOtherGroup = NULL;
6142 if (pOtherGroup !=
this)
break;
6145 "Could not move samples to another group, since there is no "
6146 "other Group. This is a bug, report it!"
6161 0, 2, 19980628 & 0xffff, 19980628 >> 16
6166 0, 3, 20030331 & 0xffff, 20030331 >> 16
6171 0, 4, 20071012 & 0xffff, 20071012 >> 16
6174 static const DLS::Info::string_length_t _FileFixedStringLengths[] = {
6175 { CHUNK_ID_IARL, 256 },
6176 { CHUNK_ID_IART, 128 },
6177 { CHUNK_ID_ICMS, 128 },
6178 { CHUNK_ID_ICMT, 1024 },
6179 { CHUNK_ID_ICOP, 128 },
6180 { CHUNK_ID_ICRD, 128 },
6181 { CHUNK_ID_IENG, 128 },
6182 { CHUNK_ID_IGNR, 128 },
6183 { CHUNK_ID_IKEY, 128 },
6184 { CHUNK_ID_IMED, 128 },
6185 { CHUNK_ID_INAM, 128 },
6186 { CHUNK_ID_IPRD, 128 },
6187 { CHUNK_ID_ISBJ, 128 },
6188 { CHUNK_ID_ISFT, 128 },
6189 { CHUNK_ID_ISRC, 128 },
6190 { CHUNK_ID_ISRF, 128 },
6191 { CHUNK_ID_ITCH, 128 },
6195 File::File() :
DLS::File() {
6197 *pVersion = VERSION_3;
6199 pScriptGroups = NULL;
6200 pInfo->SetFixedStringLengths(_FileFixedStringLengths);
6201 pInfo->ArchivalLocation = String(256,
' ');
6205 pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);
6206 pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);
6207 pRIFF->AddSubChunk(CHUNK_ID_DLID, 16);
6215 pScriptGroups = NULL;
6216 pInfo->SetFixedStringLengths(_FileFixedStringLengths);
6221 std::list<Group*>::iterator iter = pGroups->begin();
6222 std::list<Group*>::iterator end = pGroups->end();
6223 while (iter != end) {
6229 if (pScriptGroups) {
6230 std::list<ScriptGroup*>::iterator iter = pScriptGroups->begin();
6231 std::list<ScriptGroup*>::iterator end = pScriptGroups->end();
6232 while (iter != end) {
6236 delete pScriptGroups;
6241 if (!pSamples) LoadSamples(pProgress);
6242 if (!pSamples)
return NULL;
6243 SamplesIterator = pSamples->begin();
6244 return static_cast<gig::Sample*
>( (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL );
6248 if (!pSamples)
return NULL;
6250 return static_cast<gig::Sample*
>( (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL );
6259 if (!pSamples) LoadSamples();
6260 if (!pSamples)
return NULL;
6261 DLS::File::SampleList::iterator it = pSamples->begin();
6262 for (
int i = 0; i < index; ++i) {
6264 if (it == pSamples->end())
return NULL;
6266 if (it == pSamples->end())
return NULL;
6279 if (!pSamples) LoadSamples();
6280 if (!pSamples)
return 0;
6281 return pSamples->size();
6292 if (!pSamples) LoadSamples();
6303 pSamples->push_back(pSample);
6317 if (!pSamples || !pSamples->size())
throw gig::Exception(
"Could not delete sample as there are no samples");
6318 SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), (
DLS::Sample*) pSample);
6319 if (iter == pSamples->end())
throw gig::Exception(
"Could not delete sample, could not find given sample");
6320 if (SamplesIterator != pSamples->end() && *SamplesIterator == pSample) ++SamplesIterator;
6321 pSamples->erase(iter);
6325 SampleList::iterator tmp = SamplesIterator;
6329 for (
Region* region = instrument->GetFirstRegion() ; region ;
6330 region = instrument->GetNextRegion()) {
6332 if (region->GetSample() == pSample) region->SetSample(NULL);
6334 for (
int i = 0 ; i < region->DimensionRegions ; i++) {
6340 SamplesIterator = tmp;
6343 void File::LoadSamples() {
6347 void File::LoadSamples(progress_t* pProgress) {
6350 if (!pGroups) LoadGroups();
6352 if (!pSamples) pSamples =
new SampleList;
6357 int iSampleIndex = 0;
6358 int iTotalSamples = WavePoolCount;
6361 const std::string folder = parentPath(pRIFF->GetFileName());
6362 const std::string baseName = pathWithoutExtension(pRIFF->GetFileName());
6366 std::vector<RIFF::File*> poolFiles;
6367 poolFiles.push_back(pRIFF);
6373 for (
int i = 0; i < n; i++) {
6377 std::string path = concatPath(folder, name);
6383 idExpected.ulData1 = ckXfil->
ReadInt32();
6384 idExpected.usData2 = ckXfil->
ReadInt16();
6385 idExpected.usData3 = ckXfil->
ReadInt16();
6386 ckXfil->
Read(idExpected.abData, 8, 1);
6388 ckDLSID->
Read(&idFound.ulData1, 1, 4);
6389 ckDLSID->
Read(&idFound.usData2, 1, 2);
6390 ckDLSID->
Read(&idFound.usData3, 1, 2);
6391 ckDLSID->
Read(idFound.abData, 8, 1);
6392 if (memcmp(&idExpected, &idFound, 16) != 0)
6393 throw gig::Exception(
"dlsid mismatch for extension file: %s", path.c_str());
6395 poolFiles.push_back(pExtFile);
6396 ExtensionFiles.push_back(pExtFile);
6403 std::string path = baseName +
".gx99";
6407 ckDoxf->
SetPos(132, RIFF::stream_curpos);
6413 idExpected.ulData1 = ckDoxf->
ReadInt32();
6414 idExpected.usData2 = ckDoxf->
ReadInt16();
6415 idExpected.usData3 = ckDoxf->
ReadInt16();
6416 ckDoxf->
Read(idExpected.abData, 8, 1);
6418 ckDLSID->
Read(&idFound.ulData1, 1, 4);
6419 ckDLSID->
Read(&idFound.usData2, 1, 2);
6420 ckDLSID->
Read(&idFound.usData3, 1, 2);
6421 ckDLSID->
Read(idFound.abData, 8, 1);
6422 if (memcmp(&idExpected, &idFound, 16) != 0)
6423 throw gig::Exception(
"dlsid mismatch for GigaPulse file: %s", path.c_str());
6425 poolFiles.push_back(pExtFile);
6426 ExtensionFiles.push_back(pExtFile);
6430 for (
int i = 0; i < poolFiles.size(); i++) {
6441 const float subprogress = (float) iSampleIndex / (
float) iTotalSamples;
6442 __notify_progress(pProgress, subprogress);
6446 pSamples->push_back(
new Sample(
this, wave, waveFileOffset - wvplFileOffset, i, iSampleIndex));
6456 __notify_progress(pProgress, 1.0);
6460 if (!pInstruments) LoadInstruments();
6461 if (!pInstruments)
return NULL;
6462 InstrumentsIterator = pInstruments->begin();
6463 return static_cast<gig::Instrument*
>( (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL );
6467 if (!pInstruments)
return NULL;
6468 InstrumentsIterator++;
6469 return static_cast<gig::Instrument*
>( (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL );
6481 if (!pInstruments) LoadInstruments();
6482 if (!pInstruments)
return 0;
6483 return pInstruments->size();
6494 if (!pInstruments) {
6500 __divide_progress(pProgress, &subprogress, 3.0f, 0.0f);
6501 __notify_progress(&subprogress, 0.0f);
6504 __notify_progress(&subprogress, 1.0f);
6511 __notify_progress(&subprogress, 0.0f);
6512 LoadInstruments(&subprogress);
6513 __notify_progress(&subprogress, 1.0f);
6523 if (!pInstruments)
return NULL;
6524 InstrumentsIterator = pInstruments->begin();
6525 for (uint i = 0; InstrumentsIterator != pInstruments->end(); i++) {
6526 if (i == index)
return static_cast<gig::Instrument*
>( *InstrumentsIterator );
6527 InstrumentsIterator++;
6540 if (!pInstruments) LoadInstruments();
6557 pInstruments->push_back(pInstrument);
6594 static int iCallCount = -1;
6596 std::map<Group*,Group*> mGroups;
6597 std::map<Sample*,Sample*> mSamples;
6600 for (
int i = 0; pFile->
GetGroup(i); ++i) {
6601 Group* g = AddGroup();
6603 "COPY" + ToString(iCallCount) +
"_" + pFile->
GetGroup(i)->
Name;
6608 for (
int i = 0; pFile->
GetSample(i); ++i) {
6619 dg->
Name =
"COPY" + ToString(iCallCount) +
"_" + sg->
Name;
6620 for (
int iScript = 0; sg->
GetScript(iScript); ++iScript) {
6652 for (
int i = 0; pFile->
GetSample(i); ++i) {
6666 if (!pInstruments)
throw gig::Exception(
"Could not delete instrument as there are no instruments");
6667 InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), (
DLS::Instrument*) pInstrument);
6668 if (iter == pInstruments->end())
throw gig::Exception(
"Could not delete instrument, could not find given instrument");
6669 pInstruments->erase(iter);
6674 void File::LoadInstruments() {
6675 LoadInstruments(NULL);
6678 void File::LoadInstruments(progress_t* pProgress) {
6679 if (!pInstruments) pInstruments =
new InstrumentList;
6681 if (lstInstruments) {
6682 int iInstrumentIndex = 0;
6688 const float localProgress = (float) iInstrumentIndex / (
float)
Instruments;
6689 __notify_progress(pProgress, localProgress);
6692 progress_t subprogress;
6693 __divide_progress(pProgress, &subprogress,
Instruments, iInstrumentIndex);
6695 pInstruments->push_back(
new Instrument(
this, lstInstr, &subprogress));
6697 pInstruments->push_back(
new Instrument(
this, lstInstr));
6705 __notify_progress(pProgress, 1.0);
6717 int iWaveIndex = GetWaveTableIndexOf(pSample);
6718 if (iWaveIndex < 0)
throw gig::Exception(
"Could not update crc, could not find sample");
6721 _3crc->
SetPos(iWaveIndex * 8);
6727 uint32_t File::GetSampleChecksum(
Sample* pSample) {
6729 int iWaveIndex = GetWaveTableIndexOf(pSample);
6730 if (iWaveIndex < 0)
throw gig::Exception(
"Could not retrieve reference crc of sample, could not resolve sample's wave table index");
6732 return GetSampleChecksumByIndex(iWaveIndex);
6735 uint32_t File::GetSampleChecksumByIndex(
int index) {
6736 if (index < 0)
throw gig::Exception(
"Could not retrieve reference crc of sample, invalid wave pool index of sample");
6739 if (!_3crc)
throw gig::Exception(
"Could not retrieve reference crc of sample, no checksums stored for this file yet");
6741 if (!pData)
throw gig::Exception(
"Could not retrieve reference crc of sample, no checksums stored for this file yet");
6744 size_t pos = index * 8;
6746 throw gig::Exception(
"Could not retrieve reference crc of sample, could not seek to required position in crc chunk");
6748 uint32_t one = load32(&pData[pos]);
6750 throw gig::Exception(
"Could not retrieve reference crc of sample, because reference checksum table is damaged");
6752 return load32(&pData[pos+4]);
6755 int File::GetWaveTableIndexOf(
gig::Sample* pSample) {
6757 File::SampleList::iterator iter = pSamples->begin();
6758 File::SampleList::iterator end = pSamples->end();
6759 for (
int index = 0; iter != end; ++iter, ++index)
6760 if (*iter == pSample)
6773 if (!_3crc)
return false;
6777 if (_3crc->
GetNewSize() != pSamples->size() * 8)
return false;
6779 const file_offset_t n = _3crc->
GetNewSize() / 8;
6782 if (!pData)
return false;
6784 for (file_offset_t i = 0; i < n; ++i) {
6785 uint32_t one = pData[i*2];
6786 if (one != 1)
return false;
6812 bool bRequiresSave =
false;
6817 _3crc = pRIFF->
AddSubChunk(CHUNK_ID_3CRC, pSamples->size() * 8);
6821 bRequiresSave =
true;
6822 }
else if (_3crc->
GetNewSize() != pSamples->size() * 8) {
6823 _3crc->
Resize(pSamples->size() * 8);
6824 bRequiresSave =
true;
6827 if (bRequiresSave) {
6830 File::SampleList::iterator iter = pSamples->begin();
6831 File::SampleList::iterator end = pSamples->end();
6832 for (; iter != end; ++iter) {
6834 int index = GetWaveTableIndexOf(pSample);
6835 if (index < 0)
throw gig::Exception(
"Could not rebuild crc table for samples, wave table index of a sample could not be resolved");
6837 pData[index*2+1] = pSample->CalculateWaveDataChecksum();
6842 pRIFF->
SetMode(RIFF::stream_mode_read_write);
6844 File::SampleList::iterator iter = pSamples->begin();
6845 File::SampleList::iterator end = pSamples->end();
6846 for (; iter != end; ++iter) {
6848 int index = GetWaveTableIndexOf(pSample);
6849 if (index < 0)
throw gig::Exception(
"Could not rebuild crc table for samples, wave table index of a sample could not be resolved");
6850 pSample->
crc = pSample->CalculateWaveDataChecksum();
6856 return bRequiresSave;
6860 if (!pGroups) LoadGroups();
6862 GroupsIterator = pGroups->begin();
6863 return *GroupsIterator;
6867 if (!pGroups)
return NULL;
6869 return (GroupsIterator == pGroups->end()) ? NULL : *GroupsIterator;
6879 if (!pGroups) LoadGroups();
6880 GroupsIterator = pGroups->begin();
6881 for (uint i = 0; GroupsIterator != pGroups->end(); i++) {
6882 if (i == index)
return *GroupsIterator;
6899 if (!pGroups) LoadGroups();
6900 GroupsIterator = pGroups->begin();
6901 for (uint i = 0; GroupsIterator != pGroups->end(); ++GroupsIterator, ++i)
6902 if ((*GroupsIterator)->Name == name)
return *GroupsIterator;
6906 Group* File::AddGroup() {
6907 if (!pGroups) LoadGroups();
6911 pGroups->push_back(pGroup);
6925 if (!pGroups) LoadGroups();
6926 std::list<Group*>::iterator iter = find(pGroups->begin(), pGroups->end(), pGroup);
6927 if (iter == pGroups->end())
throw gig::Exception(
"Could not delete group, could not find given group");
6928 if (pGroups->size() == 1)
throw gig::Exception(
"Cannot delete group, there must be at least one default group!");
6934 pGroups->erase(iter);
6950 if (!pGroups) LoadGroups();
6951 std::list<Group*>::iterator iter = find(pGroups->begin(), pGroups->end(), pGroup);
6952 if (iter == pGroups->end())
throw gig::Exception(
"Could not delete group, could not find given group");
6953 if (pGroups->size() == 1)
throw gig::Exception(
"Cannot delete group, there must be at least one default group!");
6956 pGroups->erase(iter);
6961 void File::LoadGroups() {
6962 if (!pGroups) pGroups =
new std::list<Group*>;
6972 strcmp(
static_cast<char*
>(ck->
LoadChunkData()),
"") == 0)
break;
6974 pGroups->push_back(
new Group(
this, ck));
6981 if (!pGroups->size()) {
6982 Group* pGroup =
new Group(
this, NULL);
6983 pGroup->Name =
"Default Group";
6984 pGroups->push_back(pGroup);
6996 if (!pScriptGroups) LoadScriptGroups();
6997 std::list<ScriptGroup*>::iterator it = pScriptGroups->begin();
6998 for (uint i = 0; it != pScriptGroups->end(); ++i, ++it)
6999 if (i == index)
return *it;
7012 if (!pScriptGroups) LoadScriptGroups();
7013 std::list<ScriptGroup*>::iterator it = pScriptGroups->begin();
7014 for (uint i = 0; it != pScriptGroups->end(); ++i, ++it)
7015 if ((*it)->Name == name)
return *it;
7028 if (!pScriptGroups) LoadScriptGroups();
7030 pScriptGroups->push_back(pScriptGroup);
7031 return pScriptGroup;
7047 if (!pScriptGroups) LoadScriptGroups();
7048 std::list<ScriptGroup*>::iterator iter =
7049 find(pScriptGroups->begin(), pScriptGroups->end(), pScriptGroup);
7050 if (iter == pScriptGroups->end())
7051 throw gig::Exception(
"Could not delete script group, could not find given script group");
7052 pScriptGroups->erase(iter);
7053 for (
int i = 0; pScriptGroup->
GetScript(i); ++i)
7055 if (pScriptGroup->pList)
7058 delete pScriptGroup;
7061 void File::LoadScriptGroups() {
7062 if (pScriptGroups)
return;
7063 pScriptGroups =
new std::list<ScriptGroup*>;
7069 if (lst->GetListType() == LIST_TYPE_RTIS) {
7070 pScriptGroups->push_back(
new ScriptGroup(
this, lst));
7088 bool newFile = pRIFF->
GetSubList(LIST_TYPE_INFO) == NULL;
7105 if (pScriptGroups) {
7107 for (std::list<ScriptGroup*>::iterator it = pScriptGroups->begin();
7108 it != pScriptGroups->end(); ++it)
7110 (*it)->UpdateChunks(pProgress);
7129 if (first != info) {
7144 if (!_3gnl) _3gnl = _3gri->
AddSubList(LIST_TYPE_3GNL);
7150 for (
int i = 0 ; i < 128 ; i++) {
7153 ::SaveString(CHUNK_ID_3GNM, _3gnm, _3gnl,
"",
"",
true, 64);
7158 std::list<Group*>::iterator iter = pGroups->begin();
7159 std::list<Group*>::iterator end = pGroups->end();
7160 for (; iter != end; ++iter) {
7161 (*iter)->UpdateChunks(pProgress);
7181 int sublen = int(pSamples->size() / 8 + 49);
7186 if (einf->
GetSize() != einfSize) {
7190 }
else if (newFile) {
7191 einf = pRIFF->
AddSubChunk(CHUNK_ID_EINF, einfSize);
7196 std::map<gig::Sample*,int> sampleMap;
7199 sampleMap[pSample] = sampleIdx++;
7202 int totnbusedsamples = 0;
7203 int totnbusedchannels = 0;
7204 int totnbregions = 0;
7205 int totnbdimregions = 0;
7207 int instrumentIdx = 0;
7209 memset(&pData[48], 0, sublen - 48);
7213 int nbusedsamples = 0;
7214 int nbusedchannels = 0;
7215 int nbdimregions = 0;
7218 memset(&pData[(instrumentIdx + 1) * sublen + 48], 0, sublen - 48);
7220 for (
Region* region = instrument->GetFirstRegion() ; region ;
7221 region = instrument->GetNextRegion()) {
7222 for (
int i = 0 ; i < region->DimensionRegions ; i++) {
7225 int sampleIdx = sampleMap[d->
pSample];
7226 int byte = 48 + sampleIdx / 8;
7227 int bit = 1 << (sampleIdx & 7);
7228 if ((pData[(instrumentIdx + 1) * sublen +
byte] & bit) == 0) {
7229 pData[(instrumentIdx + 1) * sublen +
byte] |= bit;
7233 if ((pData[
byte] & bit) == 0) {
7242 nbdimregions += region->DimensionRegions;
7246 store32(&pData[(instrumentIdx + 1) * sublen + 4], nbusedchannels);
7247 store32(&pData[(instrumentIdx + 1) * sublen + 8], nbusedsamples);
7248 store32(&pData[(instrumentIdx + 1) * sublen + 12], 1);
7249 store32(&pData[(instrumentIdx + 1) * sublen + 16], instrument->Regions);
7250 store32(&pData[(instrumentIdx + 1) * sublen + 20], nbdimregions);
7251 store32(&pData[(instrumentIdx + 1) * sublen + 24], nbloops);
7253 store32(&pData[(instrumentIdx + 1) * sublen + 36], instrumentIdx);
7254 store32(&pData[(instrumentIdx + 1) * sublen + 40], (uint32_t) pSamples->size());
7257 totnbregions += instrument->Regions;
7258 totnbdimregions += nbdimregions;
7259 totnbloops += nbloops;
7264 store32(&pData[4], totnbusedchannels);
7265 store32(&pData[8], totnbusedsamples);
7267 store32(&pData[16], totnbregions);
7268 store32(&pData[20], totnbdimregions);
7269 store32(&pData[24], totnbloops);
7272 store32(&pData[40], (uint32_t) pSamples->size());
7292 _3crc->
Resize(pSamples->size() * 8);
7294 _3crc = pRIFF->
AddSubChunk(CHUNK_ID_3CRC, pSamples->size() * 8);
7301 File::SampleList::iterator iter = pSamples->begin();
7302 File::SampleList::iterator end = pSamples->end();
7303 for (
int index = 0; iter != end; ++iter, ++index) {
7306 pData[index*2+1] = pSample->
crc;
7318 instrument->UpdateScriptFileOffsets();
7362 bool File::UsesAnyGigFormatExtension()
const {
7363 if (!pInstruments)
return false;
7364 InstrumentList::iterator iter = pInstruments->begin();
7365 InstrumentList::iterator end = pInstruments->end();
7366 for (; iter != end; ++iter) {
7368 if (pInstrument->UsesAnyGigFormatExtension())
7378 Exception::Exception() :
DLS::Exception() {
7381 Exception::Exception(String format, ...) :
DLS::Exception() {
7383 va_start(arg, format);
7384 Message = assemble(format, arg);
7388 Exception::Exception(String format, va_list arg) :
DLS::Exception() {
7389 Message = assemble(format, arg);
7392 void Exception::PrintMessage() {
7393 std::cout <<
"gig::Exception: " << Message << std::endl;
version_t * pVersion
Points to a version_t structure if the file provided a version number else is set to NULL.
virtual void UpdateChunks(progress_t *pProgress)
Apply all the DLS file's current instruments, samples and settings to the respective RIFF chunks.
void __ensureMandatoryChunksExist()
Checks if all (for DLS) mandatory chunks exist, if not they will be created.
virtual void UpdateFileOffsets()
Updates all file offsets stored all over the file.
uint32_t Instruments
Reflects the number of available Instrument objects.
virtual void Save(const String &Path, progress_t *pProgress=NULL)
Save changes to another file.
Sample * GetFirstSample()
Returns a pointer to the first Sample object of the file, NULL otherwise.
String GetFileName()
File name of this DLS file.
void SetFixedStringLengths(const string_length_t *lengths)
Forces specific Info fields to be of a fixed length when being saved to a file.
String Software
<ISFT-ck>. Identifies the name of the sofware package used to create the file.
Provides all neccessary information for the synthesis of a DLS Instrument.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Instrument object.
uint32_t Regions
Reflects the number of Region defintions this Instrument has.
virtual void UpdateChunks(progress_t *pProgress)
Apply Instrument with all its Regions to the respective RIFF chunks.
Defines Region information of an Instrument.
virtual void CopyAssign(const Region *orig)
Make a (semi) deep copy of the Region object given by orig and assign it to this object.
virtual void UpdateChunks(progress_t *pProgress)
Apply Region settings to the respective RIFF chunks.
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.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Region object.
Info * pInfo
Points (in any case) to an Info object, providing additional, optional infos and comments.
void GenerateDLSID()
Generates a new DLSID for the resource.
Encapsulates sample waves used for playback.
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 UpdateChunks(progress_t *pProgress)
Apply sample and its settings to the respective RIFF chunks.
void Resize(file_offset_t NewSize)
Resize sample.
uint16_t BitDepth
Size of each sample per channel (only if known sample data format is used, 0 otherwise).
uint16_t Channels
Number of channels represented in the waveform data, e.g. 1 for mono, 2 for stereo (defaults to 1=mon...
file_offset_t GetSize() const
Returns sample size.
uint32_t SamplesPerSecond
Sampling rate at which each channel should be played (defaults to 44100 if Sample was created with In...
file_offset_t SamplesTotal
Reflects total number of sample points (only if known sample data format is used, 0 otherwise),...
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Sample object.
uint FrameSize
Reflects the size (in bytes) of one single sample point (only if known sample data format is used,...
virtual void UpdateChunks(progress_t *pProgress)
Apply all sample player options to the respective RIFF chunk.
uint32_t SampleLoops
Reflects the number of sample loops.
sample_loop_t * pSampleLoops
Points to the beginning of a sample loop array, or is NULL if there are no loops defined.
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.
void Resize(file_offset_t NewSize)
Resize chunk.
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).
file_offset_t GetFilePos() const
Current, actual offset in file of current chunk data body read/write position.
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.
file_offset_t RemainingBytes() const
Returns the number of bytes left to read in the chunk body.
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...
file_offset_t GetPos() const
Position within the chunk data body (starting with 0).
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...
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...
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.
uint32_t GetChunkID() const
Chunk ID in unsigned integer representation.
void * LoadChunkData()
Load chunk body into RAM.
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.
List * GetParent() const
Returns pointer to the chunk's parent list chunk.
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...
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 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
Chunk size in bytes (without header, thus the chunk data body)
File * GetFile() const
Returns pointer to the chunk's File object.
file_offset_t GetNewSize() const
New chunk size if it was modified with Resize(), otherwise value returned will be equal to GetSize().
bool SetMode(stream_mode_t NewMode)
Change file access mode.
int GetFileOffsetSize() const
Returns the current size (in bytes) of file offsets stored in the headers of all chunks of this file.
file_offset_t GetCurrentFileSize() const
Returns the current size of this file (in bytes) as it is currently yet stored on disk.
bool IsNew() const
Returns true if this file has been created new from scratch and has not been stored to disk yet.
Chunk * GetSubChunk(uint32_t ChunkID)
Returns subchunk with chunk ID ChunkID within this chunk list.
void MoveSubChunk(Chunk *pSrc, Chunk *pDst)
Moves a sub chunk witin this list.
List * GetFirstSubList()
Returns the first sublist within the list (that is a subchunk with chunk ID "LIST").
List * AddSubList(uint32_t uiListType)
Creates a new list sub chunk.
Chunk * GetFirstSubChunk()
Returns the first subchunk within the list (which may be an ordinary chunk as well as a list chunk).
void DeleteSubChunk(Chunk *pSubChunk)
Removes a sub chunk.
size_t CountSubChunks()
Returns number of subchunks within the list (including list chunks).
List * GetSubList(uint32_t ListType)
Returns sublist chunk with list type ListType within this chunk list.
Chunk * GetNextSubChunk()
Returns the next subchunk within the list (which may be an ordinary chunk as well as a list chunk).
uint32_t GetListType() const
Returns unsigned integer representation of the list's ID.
List * GetNextSubList()
Returns the next sublist (that is a subchunk with chunk ID "LIST") within the list.
Chunk * AddSubChunk(uint32_t uiChunkID, file_offset_t ullBodySize)
Creates a new sub chunk.
Destination container for serialization, and source container for deserialization.
Encapsulates articulation informations of a dimension region.
uint8_t VelocityResponseCurveScaling
0 - 127 (usually you don't have to interpret this parameter, use GetVelocityAttenuation() instead).
vcf_cutoff_ctrl_t VCFCutoffController
Specifies which external controller has influence on the filter cutoff frequency.
void SetReleaseVelocityResponseDepth(uint8_t depth)
Updates the respective member variable and the lookup table / cache that depends on this value.
uint8_t VelocityResponseDepth
Dynamic range of velocity affecting amplitude (0 - 4) (usually you don't have to interpret this param...
bool EG2InfiniteSustain
If true, instead of going into Decay2 phase, Decay1 level will be hold until note will be released.
void SetVCFCutoffController(vcf_cutoff_ctrl_t controller)
Updates the respective member variable and the lookup table / cache that depends on this value.
eg2_ctrl_t EG2Controller
MIDI Controller which has influence on filter cutoff EG parameters (attack, decay,...
double EG2Release
Release time of the filter cutoff EG (0.000 - 60.000s).
eg1_ctrl_t EG1Controller
MIDI Controller which has influence on sample amplitude EG parameters (attack, decay,...
vcf_type_t VCFType
Defines the general filter characteristic (lowpass, highpass, bandpass, etc.).
double LFO3Phase
[gig extension]: Phase displacement of the pitch LFO's wave form (0.0° - 360.0°).
bool LFO3Sync
If set to true only one LFO should be used for all voices.
uint8_t VCFVelocityDynamicRange
0x04 = lowest, 0x00 = highest .
lfo3_ctrl_t LFO3Controller
MIDI Controller which controls the sample pitch LFO.
double EG1Decay1
Decay time of the sample amplitude EG (0.000 - 60.000s).
bool PitchTrack
If true: sample will be pitched according to the key position (this will be disabled for drums for ex...
double SampleAttenuation
Sample volume (calculated from DLS::Sampler::Gain)
uint8_t VCFVelocityScale
(0-127) Amount velocity controls VCF cutoff frequency (only if no other VCF cutoff controller is defi...
virtual void CopyAssign(const DimensionRegion *orig)
Make a (semi) deep copy of the DimensionRegion object given by orig and assign it to this object.
uint8_t EG1ControllerDecayInfluence
Amount EG1 Controller has influence on the EG1 Decay time (0 - 3, where 0 means off).
eg_opt_t EG1Options
[gig extension]: Behavior options which should be used for envelope generator 1 (volume amplitude EG)...
uint8_t EG2ControllerDecayInfluence
Amount EG2 Controller has influence on the EG2 Decay time (0 - 3, where 0 means off).
bool EG1InfiniteSustain
If true, instead of going into Decay2 phase, Decay1 level will be hold until note will be released.
double EG2Decay1
Decay time of the filter cutoff EG (0.000 - 60.000s).
bool LFO1FlipPhase
Inverts the polarity of the sample amplitude LFO wave, so it flips the wave form vertically.
int16_t EG3Depth
Depth of the sample pitch EG (-1200 - +1200).
uint8_t ChannelOffset
Audio output where the audio signal of the dimension region should be routed to (0 - 9).
Sample * pSample
Points to the Sample which is assigned to the dimension region.
lfo_wave_t LFO1WaveForm
[gig extension]: The fundamental wave form to be used by the amplitude LFO, e.g. sine,...
uint8_t EG2ControllerAttackInfluence
Amount EG2 Controller has influence on the EG2 Attack time (0 - 3, where 0 means off).
void SetVCFVelocityScale(uint8_t scaling)
Updates the respective member variable and the lookup table / cache that depends on this value.
lfo_wave_t LFO3WaveForm
[gig extension]: The fundamental wave form to be used by the pitch LFO, e.g. sine,...
int16_t LFO3ControlDepth
Controller depth of the sample pitch LFO (-1200 - +1200 cents).
uint8_t EG2ControllerReleaseInfluence
Amount EG2 Controller has influence on the EG2 Release time (0 - 3, where 0 means off).
uint8_t EG1ControllerAttackInfluence
Amount EG1 Controller has influence on the EG1 Attack time (0 - 3, where 0 means off).
void SetReleaseVelocityResponseCurve(curve_type_t curve)
Updates the respective member variable and the lookup table / cache that depends on this value.
lfo2_ctrl_t LFO2Controller
MIDI Controlle which controls the filter cutoff LFO.
uint8_t VCFKeyboardTrackingBreakpoint
See VCFKeyboardTracking (0 - 127).
bool VCFResonanceDynamic
If true: Increases the resonance Q according to changes of controllers that actually control the VCF ...
double LFO2Phase
[gig extension]: Phase displacement of the filter cutoff LFO's wave form (0.0° - 360....
uint8_t DimensionUpperLimits[8]
gig3: defines the upper limit of the dimension values for this dimension region. In case you wondered...
uint8_t EG1ControllerReleaseInfluence
Amount EG1 Controller has influence on the EG1 Release time (0 - 3, where 0 means off).
uint8_t VCFResonance
Firm internal filter resonance weight.
uint16_t EG1Sustain
Sustain value of the sample amplitude EG (0 - 1000 permille).
dim_bypass_ctrl_t DimensionBypass
If defined, the MIDI controller can switch on/off the dimension in realtime.
bool EG2ControllerInvert
Invert values coming from defined EG2 controller.
void SetVCFVelocityDynamicRange(uint8_t range)
Updates the respective member variable and the lookup table / cache that depends on this value.
uint8_t * VelocityTable
For velocity dimensions with custom defined zone ranges only: used for fast converting from velocity ...
bool LFO1Sync
If set to true only one LFO should be used for all voices.
double EG1Attack
Attack time of the sample amplitude EG (0.000 - 60.000s).
void SetVelocityResponseCurve(curve_type_t curve)
Updates the respective member variable and the lookup table / cache that depends on this value.
attenuation_ctrl_t AttenuationController
MIDI Controller which has influence on the volume level of the sample (or entire sample group).
double LFO1Phase
[gig extension]: Phase displacement of the amplitude LFO's wave form (0.0° - 360.0°).
virtual void UpdateChunks(progress_t *pProgress)
Apply dimension region settings to the respective RIFF chunks.
double GetVelocityAttenuation(uint8_t MIDIKeyVelocity)
Returns the correct amplitude factor for the given MIDIKeyVelocity.
double LFO1Frequency
Frequency of the sample amplitude LFO (0.10 - 10.00 Hz).
curve_type_t VelocityResponseCurve
Defines a transformation curve to the incoming velocity values affecting amplitude (usually you don't...
uint16_t EG2Sustain
Sustain value of the filter cutoff EG (0 - 1000 permille).
uint16_t LFO2ControlDepth
Controller depth influencing filter cutoff LFO pitch (0 - 1200).
lfo_wave_t LFO2WaveForm
[gig extension]: The fundamental wave form to be used by the filter cutoff LFO, e....
bool VCFKeyboardTracking
If true: VCF cutoff frequence will be dependend to the note key position relative to the defined brea...
uint8_t AttenuationControllerThreshold
0-127
double EG1Release
Release time of the sample amplitude EG (0.000 - 60.000s).
bool NoNoteOffReleaseTrigger
[gig extension]: If true then don't play a release trigger sample on MIDI note-off events.
void SetVelocityResponseCurveScaling(uint8_t scaling)
Updates the respective member variable and the lookup table / cache that depends on this value.
uint8_t VelocityUpperLimit
Defines the upper velocity value limit of a velocity split (only if an user defined limit was set,...
bool EG1Hold
If true, Decay1 stage should be postponed until the sample reached the sample loop start.
uint8_t ReleaseVelocityResponseDepth
Dynamic range of release velocity affecting envelope time (0 - 4).
curve_type_t ReleaseVelocityResponseCurve
Defines a transformation curve to the incoming release veloctiy values affecting envelope times.
void SetVCFVelocityCurve(curve_type_t curve)
Updates the respective member variable and the lookup table / cache that depends on this value.
double EG1Decay2
Only if EG1InfiniteSustain == false: 2nd decay stage time of the sample amplitude EG (0....
bool InvertAttenuationController
Inverts the values coming from the defined Attenuation Controller.
uint16_t SampleStartOffset
Number of samples the sample start should be moved (0 - 2000).
double EG2Decay2
Only if EG2InfiniteSustain == false: 2nd stage decay time of the filter cutoff EG (0....
uint16_t LFO1InternalDepth
Firm pitch of the sample amplitude LFO (0 - 1200 cents).
bool EG1ControllerInvert
Invert values coming from defined EG1 controller.
lfo1_ctrl_t LFO1Controller
MIDI Controller which controls sample amplitude LFO.
bool VCFCutoffControllerInvert
Inverts values coming from the defined cutoff controller.
double LFO3Frequency
Frequency of the sample pitch LFO (0.10 - 10.00 Hz).
uint8_t ReleaseTriggerDecay
0 - 8
double EG3Attack
Attack time of the sample pitch EG (0.000 - 10.000s).
virtual void SetGain(int32_t gain)
Updates the respective member variable and updates SampleAttenuation which depends on this value.
double LFO2Frequency
Frequency of the filter cutoff LFO (0.10 - 10.00 Hz).
bool SustainDefeat
If true: Sustain pedal will not hold a note.
eg_opt_t EG2Options
[gig extension]: Behavior options which should be used for envelope generator 2 (filter cutoff EG).
bool LFO2FlipPhase
Inverts the polarity of the filter cutoff LFO wave, so it flips the wave form vertically.
sust_rel_trg_t SustainReleaseTrigger
[gig extension]: Whether a sustain pedal up event shall play release trigger sample.
bool MSDecode
Gigastudio flag: defines if Mid Side Recordings should be decoded.
bool VCFEnabled
If filter should be used.
uint16_t LFO1ControlDepth
Controller depth influencing sample amplitude LFO pitch (0 - 1200 cents).
int8_t Pan
Panorama / Balance (-64..0..63 <-> left..middle..right)
void SetVelocityResponseDepth(uint8_t depth)
Updates the respective member variable and the lookup table / cache that depends on this value.
bool LFO2Sync
If set to true only one LFO should be used for all voices.
uint16_t EG1PreAttack
Preattack value of the sample amplitude EG (0 - 1000 permille).
bool SelfMask
If true: high velocity notes will stop low velocity notes at the same note, with that you can save vo...
uint8_t VCFCutoff
Max. cutoff frequency.
curve_type_t VCFVelocityCurve
Defines a transformation curve for the incoming velocity values, affecting the VCF.
double EG2Attack
Attack time of the filter cutoff EG (0.000 - 60.000s).
uint16_t EG2PreAttack
Preattack value of the filter cutoff EG (0 - 1000 permille).
uint16_t LFO2InternalDepth
Firm pitch of the filter cutoff LFO (0 - 1200 cents).
vcf_res_ctrl_t VCFResonanceController
Specifies which external controller has influence on the filter resonance Q.
int16_t LFO3InternalDepth
Firm depth of the sample pitch LFO (-1200 - +1200 cents).
bool LFO3FlipPhase
[gig extension]: Inverts the polarity of the pitch LFO wave, so it flips the wave form vertically (NO...
Will be thrown whenever a gig specific error occurs while trying to access a Gigasampler File.
Provides convenient access to Gigasampler/GigaStudio .gig files.
virtual void UpdateChunks(progress_t *pProgress)
Apply all the gig file's current instruments, samples, groups and settings to the respective RIFF chu...
Sample * GetNextSample()
Returns a pointer to the next Sample object of the file, NULL otherwise.
size_t CountInstruments()
Returns the total amount of instruments of this gig file.
static const DLS::version_t VERSION_3
Reflects Gigasampler file format version 3.0 (2003-03-31).
virtual void UpdateFileOffsets()
Updates all file offsets stored all over the file.
ScriptGroup * AddScriptGroup()
Add new instrument script group.
ScriptGroup * GetScriptGroup(uint index)
Get instrument script group (by index).
void SetSampleChecksum(Sample *pSample, uint32_t crc)
Updates the 3crc chunk with the checksum of a sample.
void DeleteScriptGroup(ScriptGroup *pGroup)
Delete an instrument script group.
size_t CountSamples()
Returns the total amount of samples of this gig file.
Instrument * AddInstrument()
Add a new instrument definition.
Instrument * GetNextInstrument()
Returns a pointer to the next Instrument object of the file, NULL otherwise.
static const DLS::version_t VERSION_2
Reflects Gigasampler file format version 2.0 (1998-06-28).
Sample * GetSample(uint index)
Returns Sample object of index.
Group * GetNextGroup()
Returns a pointer to the next Group object of the file, NULL otherwise.
bool GetAutoLoad()
Returns whether automatic loading is enabled.
void DeleteInstrument(Instrument *pInstrument)
Delete an instrument.
bool RebuildSampleChecksumTable()
Recalculates CRC32 checksums for all samples and rebuilds this gig file's checksum table with those n...
void DeleteSample(Sample *pSample)
Delete a sample.
Instrument * AddDuplicateInstrument(const Instrument *orig)
Add a duplicate of an existing instrument.
Group * GetFirstGroup()
Returns a pointer to the first Group object of the file, NULL otherwise.
Instrument * GetFirstInstrument()
Returns a pointer to the first Instrument object of the file, NULL otherwise.
void AddContentOf(File *pFile)
Add content of another existing file.
static const DLS::version_t VERSION_4
Reflects Gigasampler file format version 4.0 (2007-10-12).
Instrument * GetInstrument(uint index, progress_t *pProgress=NULL)
Returns the instrument with the given index.
Sample * AddSample()
Add a new sample.
void DeleteGroup(Group *pGroup)
Delete a group and its samples.
Group * GetGroup(uint index)
Returns the group with the given index.
void DeleteGroupOnly(Group *pGroup)
Delete a group.
void SetAutoLoad(bool b)
Enable / disable automatic loading.
Sample * GetFirstSample(progress_t *pProgress=NULL)
Returns a pointer to the first Sample object of the file, NULL otherwise.
bool VerifySampleChecksumTable()
Checks whether the file's "3CRC" chunk was damaged.
Group of Gigasampler samples.
Group(File *file, RIFF::Chunk *ck3gnm)
Constructor.
Sample * GetFirstSample()
Returns the first Sample of this Group.
Sample * GetNextSample()
Returns the next Sample of the Group.
void MoveAll()
Move all members of this group to another group (preferably the 1st one except this).
virtual void UpdateChunks(progress_t *pProgress)
Update chunks with current group settings.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this Group object.
virtual ~Group()
Destructor.
void AddSample(Sample *pSample)
Move Sample given by pSample from another Group to this Group.
String Name
Stores the name of this Group.
Provides access to a Gigasampler/GigaStudio instrument.
MidiRule * GetMidiRule(int i)
Returns a MIDI rule of the instrument.
void DeleteMidiRule(int i)
Deletes a MIDI rule from the instrument.
Script * GetScriptOfSlot(uint index)
Get instrument script (gig format extension).
void SetScriptSlotBypassed(uint index, bool bBypass)
Defines whether execution shall be skipped.
virtual void CopyAssign(const Instrument *orig)
Make a (semi) deep copy of the Instrument object given by orig and assign it to this object.
std::map< String, String > GetScriptPatchVariables(int slot)
Get all overridden script 'patch' variables.
Region * GetNextRegion()
Returns the next Region of the instrument.
String GetScriptPatchVariable(int slot, String variable)
Get overridden initial value for 'patch' variable.
MidiRuleCtrlTrigger * AddMidiRuleCtrlTrigger()
Adds the "controller trigger" MIDI rule to the instrument.
void SetScriptPatchVariable(int slot, String variable, String value)
Override initial value for 'patch' variable.
void SwapScriptSlots(uint index1, uint index2)
Flip two script slots with each other (gig format extension).
MidiRuleAlternator * AddMidiRuleAlternator()
Adds the alternator MIDI rule to the instrument.
void MoveTo(Instrument *dst)
Move this instrument at the position before.
MidiRuleLegato * AddMidiRuleLegato()
Adds the legato MIDI rule to the instrument.
uint16_t PitchbendRange
Number of semitones pitchbend controller can pitch (default is 2).
bool IsScriptSlotBypassed(uint index)
Whether script execution shall be skipped.
range_t DimensionKeyRange
0-127 (where 0 means C1 and 127 means G9)
void RemoveScriptSlot(uint index)
Remove script slot.
Region * GetRegion(unsigned int Key)
Returns the appropriate Region for a triggered note.
void AddScriptSlot(Script *pScript, bool bypass=false)
Add new instrument script slot (gig format extension).
Region * RegionKeyTable[128]
fast lookup for the corresponding Region of a MIDI key
virtual void UpdateChunks(progress_t *pProgress)
Apply Instrument with all its Regions to the respective RIFF chunks.
void RemoveScript(Script *pScript)
Remove reference to given Script (gig format extension).
uint ScriptSlotCount() const
Instrument's amount of script slots.
bool IsScriptPatchVariableSet(int slot, String variable)
Checks whether a certain script 'patch' variable value is set.
Region * GetFirstRegion()
Returns the first Region of the instrument.
void UnsetScriptPatchVariable(int slot=-1, String variable="")
Drop overridden initial value(s) for 'patch' variable(s).
MIDI rule to automatically cycle through specified sequences of different articulations.
uint8_t Controller
CC number for controller selector.
struct gig::MidiRuleAlternator::pattern_t pPatterns[32]
A pattern is a sequence of articulation numbers.
range_t KeySwitchRange
Key range for key switch selector.
bool Polyphonic
If alternator should step forward only when all notes are off.
selector_t Selector
Method by which pattern is chosen.
uint8_t Patterns
Number of alternator patterns.
range_t PlayRange
Key range of the playable keys in the instrument.
uint8_t Articulations
Number of articulations in the instrument.
String pArticulations[32]
Names of the articulations.
bool Chained
If all patterns should be chained together.
MIDI rule for triggering notes by control change events.
uint8_t ControllerNumber
MIDI controller number.
uint8_t Triggers
Number of triggers.
MIDI rule for instruments with legato samples.
uint16_t ThresholdTime
Maximum time (ms) between two notes that should be played legato.
uint8_t LegatoSamples
Number of legato samples per key in each direction (always 12)
uint8_t BypassKey
Key to be used to bypass the sustain note.
uint8_t AltSustain1Key
Key triggering alternate sustain samples.
bool BypassUseController
If a controller should be used to bypass the sustain note.
uint8_t AltSustain2Key
Key triggering a second set of alternate sustain samples.
uint16_t ReleaseTime
Release time.
range_t KeyRange
Key range for legato notes.
uint8_t ReleaseTriggerKey
Key triggering release samples.
uint8_t BypassController
Controller to be used to bypass the sustain note.
Abstract base class for all MIDI rules.
Defines Region information of a Gigasampler/GigaStudio instrument.
DimensionRegion * pDimensionRegions[256]
Pointer array to the 32 (gig2) or 256 (gig3) possible dimension regions (reflects NULL for dimension ...
unsigned int Dimensions
Number of defined dimensions, do not alter!
dimension_def_t pDimensionDefinitions[8]
Defines the five (gig2) or eight (gig3) possible dimensions (the dimension's controller and number of...
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 SetDimensionType(dimension_t oldType, dimension_t newType)
Change type of an existing dimension.
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...
void SplitDimensionZone(dimension_t type, int zone)
Divide split zone of a dimension in two (increment zone amount).
DimensionRegion * GetDimensionRegionByValue(const uint DimValues[8])
Use this method in your audio engine to get the appropriate dimension region with it's articulation d...
void DeleteDimensionZone(dimension_t type, int zone)
Delete one split zone of a dimension (decrement zone amount).
void AddDimension(dimension_def_t *pDimDef)
Einstein would have dreamed of it - create a new dimension.
unsigned int Layers
Amount of defined layers (1 - 32). A value of 1 actually means no layering, a value > 1 means there i...
Sample * GetSample()
Returns pointer address to the Sample referenced with this region.
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.
DimensionRegion * GetDimensionRegionByBit(const uint8_t DimBits[8])
Returns the appropriate DimensionRegion for the given dimension bit numbers (zone index).
void DeleteDimension(dimension_def_t *pDimDef)
Delete an existing dimension.
virtual void UpdateChunks(progress_t *pProgress)
Apply Region settings and all its DimensionRegions to the respective RIFF chunks.
uint32_t DimensionRegions
Total number of DimensionRegions this Region contains, do not alter!
Encapsulates sample waves of Gigasampler/GigaStudio files used for playback.
static void DestroyDecompressionBuffer(buffer_t &DecompressionBuffer)
Free decompression buffer, previously created with CreateDecompressionBuffer().
file_offset_t SamplesInLastFrame
For compressed samples only: length of the last sample frame.
loop_type_t LoopType
Caution: Use the respective field in the DimensionRegion instead of this one! (Intended purpose: The ...
uint32_t Loops
Caution: Use the respective field in the DimensionRegion instead of this one! (Intended purpose: Numb...
bool VerifyWaveData(uint32_t *pActually=NULL)
Checks the integrity of this sample's raw audio wave data.
uint32_t LoopFraction
The fractional value specifies a fraction of a sample at which to loop. This allows a loop to be fine...
unsigned long FileNo
File number (> 0 when sample is stored in an extension file, 0 when it's in the gig)
void CopyAssignMeta(const Sample *orig)
Make a (semi) deep copy of the Sample object given by orig (without the actual waveform data) and ass...
uint32_t LoopStart
Caution: Use the respective field in the DimensionRegion instead of this one! (Intended purpose: The ...
uint32_t SMPTEOffset
The SMPTE Offset value specifies the time offset to be used for the synchronization / calibration to ...
buffer_t RAMCache
Buffers samples (already uncompressed) in RAM.
file_offset_t * FrameTable
For positioning within compressed samples only: stores the offset values for each frame.
uint32_t Product
Specifies the MIDI model ID defined by the manufacturer corresponding to the Manufacturer field....
uint32_t LoopEnd
Caution: Use the respective field in the DimensionRegion instead of this one! (Intended purpose: The ...
Group * pGroup
pointer to the Group this sample belongs to (always not-NULL)
file_offset_t WorstCaseFrameSize
For compressed samples only: size (in bytes) of the largest possible sample frame.
static buffer_t CreateDecompressionBuffer(file_offset_t MaxReadSize)
Allocates a decompression buffer for streaming (compressed) samples with Sample::Read().
Sample(File *pFile, RIFF::List *waveList, file_offset_t WavePoolOffset, unsigned long fileNo=0, int index=-1)
Constructor.
void Resize(file_offset_t NewSize)
Resize sample.
file_offset_t SamplePos
For compressed samples only: stores the current position (in sample points).
file_offset_t FrameOffset
Current offset (sample points) in current sample frame (for decompression only).
bool Compressed
If the sample wave is compressed (probably just interesting for instrument and sample editors,...
Group * GetGroup() const
Returns pointer to the Group this Sample belongs to.
uint32_t MIDIUnityNote
Specifies the musical note at which the sample will be played at it's original sample rate.
uint32_t crc
Reflects CRC-32 checksum of the raw sample data at the last time when the sample's raw wave form data...
buffer_t LoadSampleData()
Loads (and uncompresses if needed) the whole sample wave into RAM.
void CopyAssignWave(const Sample *orig)
Should be called after CopyAssignMeta() and File::Save() sequence.
smpte_format_t SMPTEFormat
Specifies the Society of Motion Pictures and Television E time format used in the following SMPTEOffs...
file_offset_t GetPos() const
Returns the current position in the sample (in sample points).
static size_t Instances
Number of instances of class 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).
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...
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 ...
bool Dithered
For 24-bit compressed samples only: if dithering was used during compression with bit reduction.
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...
uint32_t LoopID
Specifies the unique ID that corresponds to one of the defined cue points in the cue point list (only...
static buffer_t InternalDecompressionBuffer
Buffer used for decompression as well as for truncation of 24 Bit -> 16 Bit samples.
uint32_t SamplePeriod
Specifies the duration of time that passes during the playback of one sample in nanoseconds (normally...
uint32_t LoopPlayCount
Number of times the loop should be played (a value of 0 = infinite).
buffer_t LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount)
Loads (and uncompresses if needed) the whole sample wave into RAM.
void ReleaseSampleData()
Frees the cached sample from RAM if loaded with LoadSampleData() previously.
virtual void UpdateChunks(progress_t *pProgress)
Apply sample and its settings to the respective RIFF chunks.
file_offset_t Write(void *pBuffer, file_offset_t SampleCount)
Write sample wave data.
uint32_t Manufacturer
Specifies the MIDI Manufacturer's Association (MMA) Manufacturer code for the sampler intended to rec...
uint32_t TruncatedBits
For 24-bit compressed samples only: number of bits truncated during compression (0,...
buffer_t GetCache()
Returns current cached sample points.
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.
uint32_t LoopSize
Caution: Use the respective fields in the DimensionRegion instead of this one! (Intended purpose: Len...
Group of instrument scripts (gig format extension).
virtual void UpdateChunks(progress_t *pProgress)
Apply this script group to the respective RIFF chunks.
void DeleteScript(Script *pScript)
Delete an instrument script.
Script * AddScript()
Add new instrument script.
String Name
Name of this script group. For example to be displayed in an instrument editor.
Script * GetScript(uint index)
Get instrument script.
virtual void DeleteChunks()
Remove all RIFF chunks associated with this ScriptGroup object.
Real-time instrument script (gig format extension).
Compression_t Compression
Whether the script was/should be compressed, and if so, which compression algorithm shall be used.
@ COMPRESSION_NONE
Is not compressed at all (default).
void SetGroup(ScriptGroup *pGroup)
Move this script from its current ScriptGroup to another ScriptGroup given by pGroup.
Language_t Language
Programming language and dialect the script is written in.
Encoding_t Encoding
Format the script's source code text is encoded with.
uint8_t Uuid[16]
Persistent Universally Unique Identifier of this script, which remains identical after any changes to...
@ ENCODING_ASCII
Standard 8 bit US ASCII character encoding (default).
void UpdateChunks(progress_t *pProgress)
Apply this script to the respective RIFF chunks.
@ LANGUAGE_NKSP
NKSP stands for "Is Not KSP" (default). Refer to the NKSP Reference Manual for details about this scr...
bool Bypass
Global bypass: if enabled, this script shall not be executed by the sampler for any instrument.
String Name
Arbitrary name of the script, which may be displayed i.e. in an instrument editor.
void DeleteChunks()
Remove all RIFF chunks associated with this Script object.
void SetScriptAsText(const String &text)
Replaces the current script with the new script source code text given by text.
String GetScriptAsText()
Returns the current script (i.e.
void CopyAssign(const Script *orig)
Make a (semi) deep copy of the Script object given by orig and assign it to this object.
ScriptGroup * GetGroup() const
Returns the script group this script currently belongs to.
void GenerateUuid()
Generate a new Universally Unique Identifier (UUID) for this script.
DLS specific classes and definitions.
stream_whence_t
File stream position dependent to these relations.
uint64_t file_offset_t
Type used by libgig for handling file positioning during file I/O tasks.
Gigasampler/GigaStudio specific classes and definitions.
@ dim_bypass_ctrl_94
Effect 4 Depth (MIDI Controller 94)
@ dim_bypass_ctrl_95
Effect 5 Depth (MIDI Controller 95)
@ dim_bypass_ctrl_none
No controller bypass.
vcf_res_ctrl_t
Defines how the filter resonance is controlled by.
@ vcf_res_ctrl_none
No MIDI controller assigned for filter resonance.
String libraryName()
Returns the name of this C++ library.
@ smpte_format_no_offset
no SMPTE offset
curve_type_t
Defines the shape of a function graph.
@ curve_type_nonlinear
Non-linear curve type.
@ curve_type_unknown
Unknown curve type.
@ curve_type_linear
Linear curve type.
@ curve_type_special
Special curve type.
lfo1_ctrl_t
Defines how LFO1 is controlled by.
@ lfo1_ctrl_internal
Only internally controlled.
sust_rel_trg_t
Defines behaviour of release triggered sample(s) on sustain pedal up event.
@ sust_rel_trg_none
No release triggered sample(s) are played on sustain pedal up (default).
vcf_cutoff_ctrl_t
Defines how the filter cutoff frequency is controlled by.
@ vcf_cutoff_ctrl_none2
The difference between none and none2 is unknown.
@ vcf_cutoff_ctrl_none
No MIDI controller assigned for filter cutoff frequency.
lfo_wave_t
Defines the wave form type used by an LFO (gig format extension).
@ lfo_wave_sine
Sine (sinus) wave form (this is the default wave form).
std::array< uint8_t, 16 > _UUIDFromCArray(const uint8_t *pData)
type cast (by copy) uint8_t[16] -> std::array<uint8_t,16>
split_type_t
Intended for internal usage: will be used to convert a dimension value into the corresponding dimensi...
@ split_type_bit
dimension values are already the sought bit number
@ split_type_normal
dimension value between 0-127
String libraryVersion()
Returns version of this C++ library.
@ loop_type_bidirectional
Alternating loop (forward/backward, also known as Ping Pong)
@ loop_type_backward
Loop backward (reverse)
@ loop_type_normal
Loop forward (normal)
lfo3_ctrl_t
Defines how LFO3 is controlled by.
@ lfo3_ctrl_modwheel
Only controlled by external modulation wheel.
lfo2_ctrl_t
Defines how LFO2 is controlled by.
@ lfo2_ctrl_internal
Only internally controlled.
dimension_t
Defines the type of dimension, that is how the dimension zones (and thus how the dimension regions ar...
@ dimension_keyboard
Dimension for keyswitching.
@ dimension_roundrobinkeyboard
Different samples triggered each time a note is played, any key advances the counter.
@ dimension_samplechannel
If used sample has more than one channel (thus is not mono).
@ dimension_smartmidi
For MIDI tools like legato and repetition mode.
@ dimension_releasetrigger
Special dimension for triggering samples on releasing a key.
@ dimension_velocity
Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined).
@ dimension_random
Different samples triggered each time a note is played, random order.
@ dimension_none
Dimension not in use.
@ dimension_roundrobin
Different samples triggered each time a note is played, dimension regions selected in sequence.
@ dimension_layer
For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers).
vcf_type_t
Audio filter types.
@ vcf_type_lowpassturbo
More poles than normal lowpass (GigaStudio).
@ vcf_type_lowpass
Standard lowpass filter type (GigaStudio).
Every subject of an DLS file and the file itself can have an unique, computer generated ID.
uint16_t low
Low value of range.
uint16_t high
High value of range.
Defines Sample Loop Points.
uint32_t LoopLength
Length of the looping area (in sample points).
uint32_t LoopStart
The start value specifies the offset (in sample points) in the waveform data of the first sample poin...
uint32_t LoopType
Defines how the waveform samples will be looped (appropriate loop types for the gig format are define...
Quadtuple version number ("major.minor.release.build").
Used for indicating the progress of a certain task.
float __range_min
Only for internal usage, do not modify!
void(* callback)(progress_t *)
Callback function pointer which has to be assigned to a function for progress notification.
float __range_max
Only for internal usage, do not modify!
Pointer address and size of a buffer.
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...
void * pStart
Points to the beginning of the buffer.
file_offset_t Size
Size of the actual data in the buffer in bytes.
uint8_t in_end
End position of fade in.
uint8_t in_start
Start position of fade in.
uint8_t out_end
End postition of fade out.
uint8_t out_start
Start position of fade out.
General dimension definition.
dimension_t dimension
Specifies which source (usually a MIDI controller) is associated with the dimension.
uint8_t zones
Number of zones the dimension has.
uint8_t bits
Number of "bits" (1 bit = 2 splits/zones, 2 bit = 4 splits/zones, 3 bit = 8 splits/zones,...
float zone_size
Intended for internal usage: reflects the size of each zone (128/zones) for normal split types only,...
split_type_t split_type
Intended for internal usage: will be used to convert a dimension value into the corresponding dimensi...
Defines behavior options for envelope generators (gig format extension).
bool AttackHoldCancel
Whether the "attack hold" stage is cancelled when receiving a note-off (default: true).
bool Decay1Cancel
Whether the "decay 1" stage is cancelled when receiving a note-off (default: true).
bool ReleaseCancel
Whether the "release" stage is cancelled when receiving a note-on (default: true).
bool AttackCancel
Whether the "attack" stage is cancelled when receiving a note-off (default: true).
bool Decay2Cancel
Whether the "decay 2" stage is cancelled when receiving a note-off (default: true).
@ type_none
No controller defined.
@ type_velocity
Key Velocity.
@ type_controlchange
Ordinary MIDI control change controller, see field 'controller_number'.
@ type_channelaftertouch
Channel Key Pressure.
uint controller_number
MIDI controller number if this controller is a control change controller, 0 otherwise.
type_t type
Controller type.
Reflects the current playback state for a sample.
bool reverse
If playback direction is currently backwards (in case there is a pingpong or reverse loop defined).
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.
file_offset_t position
Current position within the sample.
uint8_t high
High value of range.
uint8_t low
Low value of range.