/[svn]/libgig/trunk/src/gig.cpp
ViewVC logotype

Contents of /libgig/trunk/src/gig.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3799 - (show annotations) (download)
Sat Jul 25 09:28:56 2020 UTC (3 years, 8 months ago) by schoenebeck
File size: 323370 byte(s)
* src/gig.cpp: Fixed undefined behaviour when modifying script slots on an
  instrument that had been cloned and not been saved yet (e.g. unintended
  modification of original instrument's script slots, and crash on
  Instrument destruction due to double free of pScriptRefs).

* Bumped version (4.2.0.svn17).

1 /***************************************************************************
2 * *
3 * libgig - C++ cross-platform Gigasampler format file access library *
4 * *
5 * Copyright (C) 2003-2020 by Christian Schoenebeck *
6 * <cuse@users.sourceforge.net> *
7 * *
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include "gig.h"
25
26 #include "helper.h"
27 #include "Serialization.h"
28
29 #include <algorithm>
30 #include <math.h>
31 #include <iostream>
32 #include <assert.h>
33
34 /// libgig's current file format version (for extending the original Giga file
35 /// format with libgig's own custom data / custom features).
36 #define GIG_FILE_EXT_VERSION 2
37
38 /// Initial size of the sample buffer which is used for decompression of
39 /// compressed sample wave streams - this value should always be bigger than
40 /// the biggest sample piece expected to be read by the sampler engine,
41 /// otherwise the buffer size will be raised at runtime and thus the buffer
42 /// reallocated which is time consuming and unefficient.
43 #define INITIAL_SAMPLE_BUFFER_SIZE 512000 // 512 kB
44
45 /** (so far) every exponential paramater in the gig format has a basis of 1.000000008813822 */
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)
58
59 #define SRLZ(member) \
60 archive->serializeMember(*this, member, #member);
61
62 namespace gig {
63
64 // *************** Internal functions for sample decompression ***************
65 // *
66
67 namespace {
68
69 inline int get12lo(const unsigned char* pSrc)
70 {
71 const int x = pSrc[0] | (pSrc[1] & 0x0f) << 8;
72 return x & 0x800 ? x - 0x1000 : x;
73 }
74
75 inline int get12hi(const unsigned char* pSrc)
76 {
77 const int x = pSrc[1] >> 4 | pSrc[2] << 4;
78 return x & 0x800 ? x - 0x1000 : x;
79 }
80
81 inline int16_t get16(const unsigned char* pSrc)
82 {
83 return int16_t(pSrc[0] | pSrc[1] << 8);
84 }
85
86 inline int get24(const unsigned char* pSrc)
87 {
88 const int x = pSrc[0] | pSrc[1] << 8 | pSrc[2] << 16;
89 return x & 0x800000 ? x - 0x1000000 : x;
90 }
91
92 inline void store24(unsigned char* pDst, int x)
93 {
94 pDst[0] = x;
95 pDst[1] = x >> 8;
96 pDst[2] = x >> 16;
97 }
98
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)
104 {
105 switch (compressionmode) {
106 case 0: // 16 bit uncompressed
107 pSrc += currentframeoffset * srcStep;
108 while (copysamples) {
109 *pDst = get16(pSrc);
110 pDst += dstStep;
111 pSrc += srcStep;
112 copysamples--;
113 }
114 break;
115
116 case 1: // 16 bit compressed to 8 bit
117 int y = get16(params);
118 int dy = get16(params + 2);
119 while (currentframeoffset) {
120 dy -= int8_t(*pSrc);
121 y -= dy;
122 pSrc += srcStep;
123 currentframeoffset--;
124 }
125 while (copysamples) {
126 dy -= int8_t(*pSrc);
127 y -= dy;
128 *pDst = y;
129 pDst += dstStep;
130 pSrc += srcStep;
131 copysamples--;
132 }
133 break;
134 }
135 }
136
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)
141 {
142 int y, dy, ddy, dddy;
143
144 #define GET_PARAMS(params) \
145 y = get24(params); \
146 dy = y - get24((params) + 3); \
147 ddy = get24((params) + 6); \
148 dddy = get24((params) + 9)
149
150 #define SKIP_ONE(x) \
151 dddy -= (x); \
152 ddy -= dddy; \
153 dy = -dy - ddy; \
154 y += dy
155
156 #define COPY_ONE(x) \
157 SKIP_ONE(x); \
158 store24(pDst, y << truncatedBits); \
159 pDst += dstStep
160
161 switch (compressionmode) {
162 case 2: // 24 bit uncompressed
163 pSrc += currentframeoffset * 3;
164 while (copysamples) {
165 store24(pDst, get24(pSrc) << truncatedBits);
166 pDst += dstStep;
167 pSrc += 3;
168 copysamples--;
169 }
170 break;
171
172 case 3: // 24 bit compressed to 16 bit
173 GET_PARAMS(params);
174 while (currentframeoffset) {
175 SKIP_ONE(get16(pSrc));
176 pSrc += 2;
177 currentframeoffset--;
178 }
179 while (copysamples) {
180 COPY_ONE(get16(pSrc));
181 pSrc += 2;
182 copysamples--;
183 }
184 break;
185
186 case 4: // 24 bit compressed to 12 bit
187 GET_PARAMS(params);
188 while (currentframeoffset > 1) {
189 SKIP_ONE(get12lo(pSrc));
190 SKIP_ONE(get12hi(pSrc));
191 pSrc += 3;
192 currentframeoffset -= 2;
193 }
194 if (currentframeoffset) {
195 SKIP_ONE(get12lo(pSrc));
196 currentframeoffset--;
197 if (copysamples) {
198 COPY_ONE(get12hi(pSrc));
199 pSrc += 3;
200 copysamples--;
201 }
202 }
203 while (copysamples > 1) {
204 COPY_ONE(get12lo(pSrc));
205 COPY_ONE(get12hi(pSrc));
206 pSrc += 3;
207 copysamples -= 2;
208 }
209 if (copysamples) {
210 COPY_ONE(get12lo(pSrc));
211 }
212 break;
213
214 case 5: // 24 bit compressed to 8 bit
215 GET_PARAMS(params);
216 while (currentframeoffset) {
217 SKIP_ONE(int8_t(*pSrc++));
218 currentframeoffset--;
219 }
220 while (copysamples) {
221 COPY_ONE(int8_t(*pSrc++));
222 copysamples--;
223 }
224 break;
225 }
226 }
227
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 };
232 }
233
234
235
236 // *************** Internal CRC-32 (Cyclic Redundancy Check) functions ***************
237 // *
238
239 static uint32_t* __initCRCTable() {
240 static uint32_t res[256];
241
242 for (int i = 0 ; i < 256 ; i++) {
243 uint32_t c = i;
244 for (int j = 0 ; j < 8 ; j++) {
245 c = (c & 1) ? 0xedb88320 ^ (c >> 1) : c >> 1;
246 }
247 res[i] = c;
248 }
249 return res;
250 }
251
252 static const uint32_t* __CRCTable = __initCRCTable();
253
254 /**
255 * Initialize a CRC variable.
256 *
257 * @param crc - variable to be initialized
258 */
259 inline static void __resetCRC(uint32_t& crc) {
260 crc = 0xffffffff;
261 }
262
263 /**
264 * Used to calculate checksums of the sample data in a gig file. The
265 * checksums are stored in the 3crc chunk of the gig file and
266 * automatically updated when a sample is written with Sample::Write().
267 *
268 * One should call __resetCRC() to initialize the CRC variable to be
269 * used before calling this function the first time.
270 *
271 * After initializing the CRC variable one can call this function
272 * arbitrary times, i.e. to split the overall CRC calculation into
273 * steps.
274 *
275 * Once the whole data was processed by __calculateCRC(), one should
276 * call __finalizeCRC() to get the final CRC result.
277 *
278 * @param buf - pointer to data the CRC shall be calculated of
279 * @param bufSize - size of the data to be processed
280 * @param crc - variable the CRC sum shall be stored to
281 */
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);
285 }
286 }
287
288 /**
289 * Returns the final CRC result.
290 *
291 * @param crc - variable previously passed to __calculateCRC()
292 */
293 inline static void __finalizeCRC(uint32_t& crc) {
294 crc ^= 0xffffffff;
295 }
296
297
298
299 // *************** Other Internal functions ***************
300 // *
301
302 static split_type_t __resolveSplitType(dimension_t dimension) {
303 return (
304 dimension == dimension_layer ||
305 dimension == dimension_samplechannel ||
306 dimension == dimension_releasetrigger ||
307 dimension == dimension_keyboard ||
308 dimension == dimension_roundrobin ||
309 dimension == dimension_random ||
310 dimension == dimension_smartmidi ||
311 dimension == dimension_roundrobinkeyboard
312 ) ? split_type_bit : split_type_normal;
313 }
314
315 static int __resolveZoneSize(dimension_def_t& dimension_definition) {
316 return (dimension_definition.split_type == split_type_normal)
317 ? int(128.0 / dimension_definition.zones) : 0;
318 }
319
320
321
322 // *************** leverage_ctrl_t ***************
323 // *
324
325 void leverage_ctrl_t::serialize(Serialization::Archive* archive) {
326 SRLZ(type);
327 SRLZ(controller_number);
328 }
329
330
331
332 // *************** crossfade_t ***************
333 // *
334
335 void crossfade_t::serialize(Serialization::Archive* archive) {
336 SRLZ(in_start);
337 SRLZ(in_end);
338 SRLZ(out_start);
339 SRLZ(out_end);
340 }
341
342
343
344 // *************** eg_opt_t ***************
345 // *
346
347 eg_opt_t::eg_opt_t() {
348 AttackCancel = true;
349 AttackHoldCancel = true;
350 Decay1Cancel = true;
351 Decay2Cancel = true;
352 ReleaseCancel = true;
353 }
354
355 void eg_opt_t::serialize(Serialization::Archive* archive) {
356 SRLZ(AttackCancel);
357 SRLZ(AttackHoldCancel);
358 SRLZ(Decay1Cancel);
359 SRLZ(Decay2Cancel);
360 SRLZ(ReleaseCancel);
361 }
362
363
364
365 // *************** Sample ***************
366 // *
367
368 size_t Sample::Instances = 0;
369 buffer_t Sample::InternalDecompressionBuffer;
370
371 /** @brief Constructor.
372 *
373 * Load an existing sample or create a new one. A 'wave' list chunk must
374 * be given to this constructor. In case the given 'wave' list chunk
375 * contains a 'fmt', 'data' (and optionally a '3gix', 'smpl') chunk, the
376 * format and sample data will be loaded from there, otherwise default
377 * values will be used and those chunks will be created when
378 * File::Save() will be called later on.
379 *
380 * @param pFile - pointer to gig::File where this sample is
381 * located (or will be located)
382 * @param waveList - pointer to 'wave' list chunk which is (or
383 * will be) associated with this sample
384 * @param WavePoolOffset - offset of this sample data from wave pool
385 * ('wvpl') list chunk
386 * @param fileNo - number of an extension file where this sample
387 * is located, 0 otherwise
388 * @param index - wave pool index of sample (may be -1 on new sample)
389 */
390 Sample::Sample(File* pFile, RIFF::List* waveList, file_offset_t WavePoolOffset, unsigned long fileNo, int index)
391 : DLS::Sample((DLS::File*) pFile, waveList, WavePoolOffset)
392 {
393 static const DLS::Info::string_length_t fixedStringLengths[] = {
394 { CHUNK_ID_INAM, 64 },
395 { 0, 0 }
396 };
397 pInfo->SetFixedStringLengths(fixedStringLengths);
398 Instances++;
399 FileNo = fileNo;
400
401 __resetCRC(crc);
402 // if this is not a new sample, try to get the sample's already existing
403 // CRC32 checksum from disk, this checksum will reflect the sample's CRC32
404 // checksum of the time when the sample was consciously modified by the
405 // user for the last time (by calling Sample::Write() that is).
406 if (index >= 0) { // not a new file ...
407 try {
408 uint32_t crc = pFile->GetSampleChecksumByIndex(index);
409 this->crc = crc;
410 } catch (...) {}
411 }
412
413 pCk3gix = waveList->GetSubChunk(CHUNK_ID_3GIX);
414 if (pCk3gix) {
415 pCk3gix->SetPos(0);
416
417 uint16_t iSampleGroup = pCk3gix->ReadInt16();
418 pGroup = pFile->GetGroup(iSampleGroup);
419 } else { // '3gix' chunk missing
420 // by default assigned to that mandatory "Default Group"
421 pGroup = pFile->GetGroup(0);
422 }
423
424 pCkSmpl = waveList->GetSubChunk(CHUNK_ID_SMPL);
425 if (pCkSmpl) {
426 pCkSmpl->SetPos(0);
427
428 Manufacturer = pCkSmpl->ReadInt32();
429 Product = pCkSmpl->ReadInt32();
430 SamplePeriod = pCkSmpl->ReadInt32();
431 MIDIUnityNote = pCkSmpl->ReadInt32();
432 FineTune = pCkSmpl->ReadInt32();
433 pCkSmpl->Read(&SMPTEFormat, 1, 4);
434 SMPTEOffset = pCkSmpl->ReadInt32();
435 Loops = pCkSmpl->ReadInt32();
436 pCkSmpl->ReadInt32(); // manufByt
437 LoopID = pCkSmpl->ReadInt32();
438 pCkSmpl->Read(&LoopType, 1, 4);
439 LoopStart = pCkSmpl->ReadInt32();
440 LoopEnd = pCkSmpl->ReadInt32();
441 LoopFraction = pCkSmpl->ReadInt32();
442 LoopPlayCount = pCkSmpl->ReadInt32();
443 } else { // 'smpl' chunk missing
444 // use default values
445 Manufacturer = 0;
446 Product = 0;
447 SamplePeriod = uint32_t(1000000000.0 / SamplesPerSecond + 0.5);
448 MIDIUnityNote = 60;
449 FineTune = 0;
450 SMPTEFormat = smpte_format_no_offset;
451 SMPTEOffset = 0;
452 Loops = 0;
453 LoopID = 0;
454 LoopType = loop_type_normal;
455 LoopStart = 0;
456 LoopEnd = 0;
457 LoopFraction = 0;
458 LoopPlayCount = 0;
459 }
460
461 FrameTable = NULL;
462 SamplePos = 0;
463 RAMCache.Size = 0;
464 RAMCache.pStart = NULL;
465 RAMCache.NullExtensionSize = 0;
466
467 if (BitDepth > 24) throw gig::Exception("Only samples up to 24 bit supported");
468
469 RIFF::Chunk* ewav = waveList->GetSubChunk(CHUNK_ID_EWAV);
470 Compressed = ewav;
471 Dithered = false;
472 TruncatedBits = 0;
473 if (Compressed) {
474 ewav->SetPos(0);
475
476 uint32_t version = ewav->ReadInt32();
477 if (version > 2 && BitDepth == 24) {
478 Dithered = ewav->ReadInt32();
479 ewav->SetPos(Channels == 2 ? 84 : 64);
480 TruncatedBits = ewav->ReadInt32();
481 }
482 ScanCompressedSample();
483 }
484
485 // we use a buffer for decompression and for truncating 24 bit samples to 16 bit
486 if ((Compressed || BitDepth == 24) && !InternalDecompressionBuffer.Size) {
487 InternalDecompressionBuffer.pStart = new unsigned char[INITIAL_SAMPLE_BUFFER_SIZE];
488 InternalDecompressionBuffer.Size = INITIAL_SAMPLE_BUFFER_SIZE;
489 }
490 FrameOffset = 0; // just for streaming compressed samples
491
492 LoopSize = LoopEnd - LoopStart + 1;
493 }
494
495 /**
496 * Make a (semi) deep copy of the Sample object given by @a orig (without
497 * the actual waveform data) and assign it to this object.
498 *
499 * Discussion: copying .gig samples is a bit tricky. It requires three
500 * steps:
501 * 1. Copy sample's meta informations (done by CopyAssignMeta()) including
502 * its new sample waveform data size.
503 * 2. Saving the file (done by File::Save()) so that it gains correct size
504 * and layout for writing the actual wave form data directly to disc
505 * in next step.
506 * 3. Copy the waveform data with disk streaming (done by CopyAssignWave()).
507 *
508 * @param orig - original Sample object to be copied from
509 */
510 void Sample::CopyAssignMeta(const Sample* orig) {
511 // handle base classes
512 DLS::Sample::CopyAssignCore(orig);
513
514 // handle actual own attributes of this class
515 Manufacturer = orig->Manufacturer;
516 Product = orig->Product;
517 SamplePeriod = orig->SamplePeriod;
518 MIDIUnityNote = orig->MIDIUnityNote;
519 FineTune = orig->FineTune;
520 SMPTEFormat = orig->SMPTEFormat;
521 SMPTEOffset = orig->SMPTEOffset;
522 Loops = orig->Loops;
523 LoopID = orig->LoopID;
524 LoopType = orig->LoopType;
525 LoopStart = orig->LoopStart;
526 LoopEnd = orig->LoopEnd;
527 LoopSize = orig->LoopSize;
528 LoopFraction = orig->LoopFraction;
529 LoopPlayCount = orig->LoopPlayCount;
530
531 // schedule resizing this sample to the given sample's size
532 Resize(orig->GetSize());
533 }
534
535 /**
536 * Should be called after CopyAssignMeta() and File::Save() sequence.
537 * Read more about it in the discussion of CopyAssignMeta(). This method
538 * copies the actual waveform data by disk streaming.
539 *
540 * @e CAUTION: this method is currently not thread safe! During this
541 * operation the sample must not be used for other purposes by other
542 * threads!
543 *
544 * @param orig - original Sample object to be copied from
545 */
546 void Sample::CopyAssignWave(const Sample* orig) {
547 const int iReadAtOnce = 32*1024;
548 char* buf = new char[iReadAtOnce * orig->FrameSize];
549 Sample* pOrig = (Sample*) orig; //HACK: remove constness for now
550 file_offset_t restorePos = pOrig->GetPos();
551 pOrig->SetPos(0);
552 SetPos(0);
553 for (file_offset_t n = pOrig->Read(buf, iReadAtOnce); n;
554 n = pOrig->Read(buf, iReadAtOnce))
555 {
556 Write(buf, n);
557 }
558 pOrig->SetPos(restorePos);
559 delete [] buf;
560 }
561
562 /**
563 * Apply sample and its settings to the respective RIFF chunks. You have
564 * to call File::Save() to make changes persistent.
565 *
566 * Usually there is absolutely no need to call this method explicitly.
567 * It will be called automatically when File::Save() was called.
568 *
569 * @param pProgress - callback function for progress notification
570 * @throws DLS::Exception if FormatTag != DLS_WAVE_FORMAT_PCM or no sample data
571 * was provided yet
572 * @throws gig::Exception if there is any invalid sample setting
573 */
574 void Sample::UpdateChunks(progress_t* pProgress) {
575 // first update base class's chunks
576 DLS::Sample::UpdateChunks(pProgress);
577
578 // make sure 'smpl' chunk exists
579 pCkSmpl = pWaveList->GetSubChunk(CHUNK_ID_SMPL);
580 if (!pCkSmpl) {
581 pCkSmpl = pWaveList->AddSubChunk(CHUNK_ID_SMPL, 60);
582 memset(pCkSmpl->LoadChunkData(), 0, 60);
583 }
584 // update 'smpl' chunk
585 uint8_t* pData = (uint8_t*) pCkSmpl->LoadChunkData();
586 SamplePeriod = uint32_t(1000000000.0 / SamplesPerSecond + 0.5);
587 store32(&pData[0], Manufacturer);
588 store32(&pData[4], Product);
589 store32(&pData[8], SamplePeriod);
590 store32(&pData[12], MIDIUnityNote);
591 store32(&pData[16], FineTune);
592 store32(&pData[20], SMPTEFormat);
593 store32(&pData[24], SMPTEOffset);
594 store32(&pData[28], Loops);
595
596 // we skip 'manufByt' for now (4 bytes)
597
598 store32(&pData[36], LoopID);
599 store32(&pData[40], LoopType);
600 store32(&pData[44], LoopStart);
601 store32(&pData[48], LoopEnd);
602 store32(&pData[52], LoopFraction);
603 store32(&pData[56], LoopPlayCount);
604
605 // make sure '3gix' chunk exists
606 pCk3gix = pWaveList->GetSubChunk(CHUNK_ID_3GIX);
607 if (!pCk3gix) pCk3gix = pWaveList->AddSubChunk(CHUNK_ID_3GIX, 4);
608 // determine appropriate sample group index (to be stored in chunk)
609 uint16_t iSampleGroup = 0; // 0 refers to default sample group
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++) {
615 if (*iter == pGroup) {
616 iSampleGroup = i;
617 break; // found
618 }
619 }
620 }
621 // update '3gix' chunk
622 pData = (uint8_t*) pCk3gix->LoadChunkData();
623 store16(&pData[0], iSampleGroup);
624
625 // if the library user toggled the "Compressed" attribute from true to
626 // false, then the EWAV chunk associated with compressed samples needs
627 // to be deleted
628 RIFF::Chunk* ewav = pWaveList->GetSubChunk(CHUNK_ID_EWAV);
629 if (ewav && !Compressed) {
630 pWaveList->DeleteSubChunk(ewav);
631 }
632 }
633
634 /// Scans compressed samples for mandatory informations (e.g. actual number of total sample points).
635 void Sample::ScanCompressedSample() {
636 //TODO: we have to add some more scans here (e.g. determine compression rate)
637 this->SamplesTotal = 0;
638 std::list<file_offset_t> frameOffsets;
639
640 SamplesPerFrame = BitDepth == 24 ? 256 : 2048;
641 WorstCaseFrameSize = SamplesPerFrame * FrameSize + Channels; // +Channels for compression flag
642
643 // Scanning
644 pCkData->SetPos(0);
645 if (Channels == 2) { // Stereo
646 for (int i = 0 ; ; i++) {
647 // for 24 bit samples every 8:th frame offset is
648 // stored, to save some memory
649 if (BitDepth != 24 || (i & 7) == 0) frameOffsets.push_back(pCkData->GetPos());
650
651 const int mode_l = pCkData->ReadUint8();
652 const int mode_r = pCkData->ReadUint8();
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];
655
656 if (pCkData->RemainingBytes() <= frameSize) {
657 SamplesInLastFrame =
658 ((pCkData->RemainingBytes() - headerSize[mode_l] - headerSize[mode_r]) << 3) /
659 (bitsPerSample[mode_l] + bitsPerSample[mode_r]);
660 SamplesTotal += SamplesInLastFrame;
661 break;
662 }
663 SamplesTotal += SamplesPerFrame;
664 pCkData->SetPos(frameSize, RIFF::stream_curpos);
665 }
666 }
667 else { // Mono
668 for (int i = 0 ; ; i++) {
669 if (BitDepth != 24 || (i & 7) == 0) frameOffsets.push_back(pCkData->GetPos());
670
671 const int mode = pCkData->ReadUint8();
672 if (mode > 5) throw gig::Exception("Unknown compression mode");
673 const file_offset_t frameSize = bytesPerFrame[mode];
674
675 if (pCkData->RemainingBytes() <= frameSize) {
676 SamplesInLastFrame =
677 ((pCkData->RemainingBytes() - headerSize[mode]) << 3) / bitsPerSample[mode];
678 SamplesTotal += SamplesInLastFrame;
679 break;
680 }
681 SamplesTotal += SamplesPerFrame;
682 pCkData->SetPos(frameSize, RIFF::stream_curpos);
683 }
684 }
685 pCkData->SetPos(0);
686
687 // Build the frames table (which is used for fast resolving of a frame's chunk offset)
688 if (FrameTable) delete[] FrameTable;
689 FrameTable = new file_offset_t[frameOffsets.size()];
690 std::list<file_offset_t>::iterator end = frameOffsets.end();
691 std::list<file_offset_t>::iterator iter = frameOffsets.begin();
692 for (int i = 0; iter != end; i++, iter++) {
693 FrameTable[i] = *iter;
694 }
695 }
696
697 /**
698 * Loads (and uncompresses if needed) the whole sample wave into RAM. Use
699 * ReleaseSampleData() to free the memory if you don't need the cached
700 * sample data anymore.
701 *
702 * @returns buffer_t structure with start address and size of the buffer
703 * in bytes
704 * @see ReleaseSampleData(), Read(), SetPos()
705 */
706 buffer_t Sample::LoadSampleData() {
707 return LoadSampleDataWithNullSamplesExtension(this->SamplesTotal, 0); // 0 amount of NullSamples
708 }
709
710 /**
711 * Reads (uncompresses if needed) and caches the first \a SampleCount
712 * numbers of SamplePoints in RAM. Use ReleaseSampleData() to free the
713 * memory space if you don't need the cached samples anymore. There is no
714 * guarantee that exactly \a SampleCount samples will be cached; this is
715 * not an error. The size will be eventually truncated e.g. to the
716 * beginning of a frame of a compressed sample. This is done for
717 * efficiency reasons while streaming the wave by your sampler engine
718 * later. Read the <i>Size</i> member of the <i>buffer_t</i> structure
719 * that will be returned to determine the actual cached samples, but note
720 * that the size is given in bytes! You get the number of actually cached
721 * samples by dividing it by the frame size of the sample:
722 * @code
723 * buffer_t buf = pSample->LoadSampleData(acquired_samples);
724 * long cachedsamples = buf.Size / pSample->FrameSize;
725 * @endcode
726 *
727 * @param SampleCount - number of sample points to load into RAM
728 * @returns buffer_t structure with start address and size of
729 * the cached sample data in bytes
730 * @see ReleaseSampleData(), Read(), SetPos()
731 */
732 buffer_t Sample::LoadSampleData(file_offset_t SampleCount) {
733 return LoadSampleDataWithNullSamplesExtension(SampleCount, 0); // 0 amount of NullSamples
734 }
735
736 /**
737 * Loads (and uncompresses if needed) the whole sample wave into RAM. Use
738 * ReleaseSampleData() to free the memory if you don't need the cached
739 * sample data anymore.
740 * The method will add \a NullSamplesCount silence samples past the
741 * official buffer end (this won't affect the 'Size' member of the
742 * buffer_t structure, that means 'Size' always reflects the size of the
743 * actual sample data, the buffer might be bigger though). Silence
744 * samples past the official buffer are needed for differential
745 * algorithms that always have to take subsequent samples into account
746 * (resampling/interpolation would be an important example) and avoids
747 * memory access faults in such cases.
748 *
749 * @param NullSamplesCount - number of silence samples the buffer should
750 * be extended past it's data end
751 * @returns buffer_t structure with start address and
752 * size of the buffer in bytes
753 * @see ReleaseSampleData(), Read(), SetPos()
754 */
755 buffer_t Sample::LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount) {
756 return LoadSampleDataWithNullSamplesExtension(this->SamplesTotal, NullSamplesCount);
757 }
758
759 /**
760 * Reads (uncompresses if needed) and caches the first \a SampleCount
761 * numbers of SamplePoints in RAM. Use ReleaseSampleData() to free the
762 * memory space if you don't need the cached samples anymore. There is no
763 * guarantee that exactly \a SampleCount samples will be cached; this is
764 * not an error. The size will be eventually truncated e.g. to the
765 * beginning of a frame of a compressed sample. This is done for
766 * efficiency reasons while streaming the wave by your sampler engine
767 * later. Read the <i>Size</i> member of the <i>buffer_t</i> structure
768 * that will be returned to determine the actual cached samples, but note
769 * that the size is given in bytes! You get the number of actually cached
770 * samples by dividing it by the frame size of the sample:
771 * @code
772 * buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(acquired_samples, null_samples);
773 * long cachedsamples = buf.Size / pSample->FrameSize;
774 * @endcode
775 * The method will add \a NullSamplesCount silence samples past the
776 * official buffer end (this won't affect the 'Size' member of the
777 * buffer_t structure, that means 'Size' always reflects the size of the
778 * actual sample data, the buffer might be bigger though). Silence
779 * samples past the official buffer are needed for differential
780 * algorithms that always have to take subsequent samples into account
781 * (resampling/interpolation would be an important example) and avoids
782 * memory access faults in such cases.
783 *
784 * @param SampleCount - number of sample points to load into RAM
785 * @param NullSamplesCount - number of silence samples the buffer should
786 * be extended past it's data end
787 * @returns buffer_t structure with start address and
788 * size of the cached sample data in bytes
789 * @see ReleaseSampleData(), Read(), SetPos()
790 */
791 buffer_t Sample::LoadSampleDataWithNullSamplesExtension(file_offset_t SampleCount, uint NullSamplesCount) {
792 if (SampleCount > this->SamplesTotal) SampleCount = this->SamplesTotal;
793 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
794 file_offset_t allocationsize = (SampleCount + NullSamplesCount) * this->FrameSize;
795 SetPos(0); // reset read position to begin of sample
796 RAMCache.pStart = new int8_t[allocationsize];
797 RAMCache.Size = Read(RAMCache.pStart, SampleCount) * this->FrameSize;
798 RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
799 // fill the remaining buffer space with silence samples
800 memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
801 return GetCache();
802 }
803
804 /**
805 * Returns current cached sample points. A buffer_t structure will be
806 * returned which contains address pointer to the begin of the cache and
807 * the size of the cached sample data in bytes. Use
808 * <i>LoadSampleData()</i> to cache a specific amount of sample points in
809 * RAM.
810 *
811 * @returns buffer_t structure with current cached sample points
812 * @see LoadSampleData();
813 */
814 buffer_t Sample::GetCache() {
815 // return a copy of the buffer_t structure
816 buffer_t result;
817 result.Size = this->RAMCache.Size;
818 result.pStart = this->RAMCache.pStart;
819 result.NullExtensionSize = this->RAMCache.NullExtensionSize;
820 return result;
821 }
822
823 /**
824 * Frees the cached sample from RAM if loaded with
825 * <i>LoadSampleData()</i> previously.
826 *
827 * @see LoadSampleData();
828 */
829 void Sample::ReleaseSampleData() {
830 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
831 RAMCache.pStart = NULL;
832 RAMCache.Size = 0;
833 RAMCache.NullExtensionSize = 0;
834 }
835
836 /** @brief Resize sample.
837 *
838 * Resizes the sample's wave form data, that is the actual size of
839 * sample wave data possible to be written for this sample. This call
840 * will return immediately and just schedule the resize operation. You
841 * should call File::Save() to actually perform the resize operation(s)
842 * "physically" to the file. As this can take a while on large files, it
843 * is recommended to call Resize() first on all samples which have to be
844 * resized and finally to call File::Save() to perform all those resize
845 * operations in one rush.
846 *
847 * The actual size (in bytes) is dependant to the current FrameSize
848 * value. You may want to set FrameSize before calling Resize().
849 *
850 * <b>Caution:</b> You cannot directly write (i.e. with Write()) to
851 * enlarged samples before calling File::Save() as this might exceed the
852 * current sample's boundary!
853 *
854 * Also note: only DLS_WAVE_FORMAT_PCM is currently supported, that is
855 * FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to resize samples with
856 * other formats will fail!
857 *
858 * @param NewSize - new sample wave data size in sample points (must be
859 * greater than zero)
860 * @throws DLS::Excecption if FormatTag != DLS_WAVE_FORMAT_PCM
861 * @throws DLS::Exception if \a NewSize is less than 1 or unrealistic large
862 * @throws gig::Exception if existing sample is compressed
863 * @see DLS::Sample::GetSize(), DLS::Sample::FrameSize,
864 * DLS::Sample::FormatTag, File::Save()
865 */
866 void Sample::Resize(file_offset_t NewSize) {
867 if (Compressed) throw gig::Exception("There is no support for modifying compressed samples (yet)");
868 DLS::Sample::Resize(NewSize);
869 }
870
871 /**
872 * Sets the position within the sample (in sample points, not in
873 * bytes). Use this method and <i>Read()</i> if you don't want to load
874 * the sample into RAM, thus for disk streaming.
875 *
876 * Although the original Gigasampler engine doesn't allow positioning
877 * within compressed samples, I decided to implement it. Even though
878 * the Gigasampler format doesn't allow to define loops for compressed
879 * samples at the moment, positioning within compressed samples might be
880 * interesting for some sampler engines though. The only drawback about
881 * my decision is that it takes longer to load compressed gig Files on
882 * startup, because it's neccessary to scan the samples for some
883 * mandatory informations. But I think as it doesn't affect the runtime
884 * efficiency, nobody will have a problem with that.
885 *
886 * @param SampleCount number of sample points to jump
887 * @param Whence optional: to which relation \a SampleCount refers
888 * to, if omited <i>RIFF::stream_start</i> is assumed
889 * @returns the new sample position
890 * @see Read()
891 */
892 file_offset_t Sample::SetPos(file_offset_t SampleCount, RIFF::stream_whence_t Whence) {
893 if (Compressed) {
894 switch (Whence) {
895 case RIFF::stream_curpos:
896 this->SamplePos += SampleCount;
897 break;
898 case RIFF::stream_end:
899 this->SamplePos = this->SamplesTotal - 1 - SampleCount;
900 break;
901 case RIFF::stream_backward:
902 this->SamplePos -= SampleCount;
903 break;
904 case RIFF::stream_start: default:
905 this->SamplePos = SampleCount;
906 break;
907 }
908 if (this->SamplePos > this->SamplesTotal) this->SamplePos = this->SamplesTotal;
909
910 file_offset_t frame = this->SamplePos / 2048; // to which frame to jump
911 this->FrameOffset = this->SamplePos % 2048; // offset (in sample points) within that frame
912 pCkData->SetPos(FrameTable[frame]); // set chunk pointer to the start of sought frame
913 return this->SamplePos;
914 }
915 else { // not compressed
916 file_offset_t orderedBytes = SampleCount * this->FrameSize;
917 file_offset_t result = pCkData->SetPos(orderedBytes, Whence);
918 return (result == orderedBytes) ? SampleCount
919 : result / this->FrameSize;
920 }
921 }
922
923 /**
924 * Returns the current position in the sample (in sample points).
925 */
926 file_offset_t Sample::GetPos() const {
927 if (Compressed) return SamplePos;
928 else return pCkData->GetPos() / FrameSize;
929 }
930
931 /**
932 * Reads \a SampleCount number of sample points from the position stored
933 * in \a pPlaybackState into the buffer pointed by \a pBuffer and moves
934 * the position within the sample respectively, this method honors the
935 * looping informations of the sample (if any). The sample wave stream
936 * will be decompressed on the fly if using a compressed sample. Use this
937 * method if you don't want to load the sample into RAM, thus for disk
938 * streaming. All this methods needs to know to proceed with streaming
939 * for the next time you call this method is stored in \a pPlaybackState.
940 * You have to allocate and initialize the playback_state_t structure by
941 * yourself before you use it to stream a sample:
942 * @code
943 * gig::playback_state_t playbackstate;
944 * playbackstate.position = 0;
945 * playbackstate.reverse = false;
946 * playbackstate.loop_cycles_left = pSample->LoopPlayCount;
947 * @endcode
948 * You don't have to take care of things like if there is actually a loop
949 * defined or if the current read position is located within a loop area.
950 * The method already handles such cases by itself.
951 *
952 * <b>Caution:</b> If you are using more than one streaming thread, you
953 * have to use an external decompression buffer for <b>EACH</b>
954 * streaming thread to avoid race conditions and crashes!
955 *
956 * @param pBuffer destination buffer
957 * @param SampleCount number of sample points to read
958 * @param pPlaybackState will be used to store and reload the playback
959 * state for the next ReadAndLoop() call
960 * @param pDimRgn dimension region with looping information
961 * @param pExternalDecompressionBuffer (optional) external buffer to use for decompression
962 * @returns number of successfully read sample points
963 * @see CreateDecompressionBuffer()
964 */
965 file_offset_t Sample::ReadAndLoop(void* pBuffer, file_offset_t SampleCount, playback_state_t* pPlaybackState,
966 DimensionRegion* pDimRgn, buffer_t* pExternalDecompressionBuffer) {
967 file_offset_t samplestoread = SampleCount, totalreadsamples = 0, readsamples, samplestoloopend;
968 uint8_t* pDst = (uint8_t*) pBuffer;
969
970 SetPos(pPlaybackState->position); // recover position from the last time
971
972 if (pDimRgn->SampleLoops) { // honor looping if there are loop points defined
973
974 const DLS::sample_loop_t& loop = pDimRgn->pSampleLoops[0];
975 const uint32_t loopEnd = loop.LoopStart + loop.LoopLength;
976
977 if (GetPos() <= loopEnd) {
978 switch (loop.LoopType) {
979
980 case loop_type_bidirectional: { //TODO: not tested yet!
981 do {
982 // if not endless loop check if max. number of loop cycles have been passed
983 if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break;
984
985 if (!pPlaybackState->reverse) { // forward playback
986 do {
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;
993 break;
994 }
995 } while (samplestoread && readsamples);
996 }
997 else { // backward playback
998
999 // as we can only read forward from disk, we have to
1000 // determine the end position within the loop first,
1001 // read forward from that 'end' and finally after
1002 // reading, swap all sample frames so it reflects
1003 // backward playback
1004
1005 file_offset_t swapareastart = totalreadsamples;
1006 file_offset_t loopoffset = GetPos() - loop.LoopStart;
1007 file_offset_t samplestoreadinloop = Min(samplestoread, loopoffset);
1008 file_offset_t reverseplaybackend = GetPos() - samplestoreadinloop;
1009
1010 SetPos(reverseplaybackend);
1011
1012 // read samples for backward playback
1013 do {
1014 readsamples = Read(&pDst[totalreadsamples * this->FrameSize], samplestoreadinloop, pExternalDecompressionBuffer);
1015 samplestoreadinloop -= readsamples;
1016 samplestoread -= readsamples;
1017 totalreadsamples += readsamples;
1018 } while (samplestoreadinloop && readsamples);
1019
1020 SetPos(reverseplaybackend); // pretend we really read backwards
1021
1022 if (reverseplaybackend == loop.LoopStart) {
1023 pPlaybackState->loop_cycles_left--;
1024 pPlaybackState->reverse = false;
1025 }
1026
1027 // reverse the sample frames for backward playback
1028 if (totalreadsamples > swapareastart) //FIXME: this if() is just a crash workaround for now (#102), but totalreadsamples <= swapareastart should never be the case, so there's probably still a bug above!
1029 SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize);
1030 }
1031 } while (samplestoread && readsamples);
1032 break;
1033 }
1034
1035 case loop_type_backward: { // TODO: not tested yet!
1036 // forward playback (not entered the loop yet)
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;
1044 break;
1045 }
1046 } while (samplestoread && readsamples);
1047
1048 if (!samplestoread) break;
1049
1050 // as we can only read forward from disk, we have to
1051 // determine the end position within the loop first,
1052 // read forward from that 'end' and finally after
1053 // reading, swap all sample frames so it reflects
1054 // backward playback
1055
1056 file_offset_t swapareastart = totalreadsamples;
1057 file_offset_t loopoffset = GetPos() - loop.LoopStart;
1058 file_offset_t samplestoreadinloop = (this->LoopPlayCount) ? Min(samplestoread, pPlaybackState->loop_cycles_left * loop.LoopLength - loopoffset)
1059 : samplestoread;
1060 file_offset_t reverseplaybackend = loop.LoopStart + Abs((loopoffset - samplestoreadinloop) % loop.LoopLength);
1061
1062 SetPos(reverseplaybackend);
1063
1064 // read samples for backward playback
1065 do {
1066 // if not endless loop check if max. number of loop cycles have been passed
1067 if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break;
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) {
1074 pPlaybackState->loop_cycles_left--;
1075 SetPos(loop.LoopStart);
1076 }
1077 } while (samplestoreadinloop && readsamples);
1078
1079 SetPos(reverseplaybackend); // pretend we really read backwards
1080
1081 // reverse the sample frames for backward playback
1082 SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize);
1083 break;
1084 }
1085
1086 default: case loop_type_normal: {
1087 do {
1088 // if not endless loop check if max. number of loop cycles have been passed
1089 if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break;
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) {
1095 pPlaybackState->loop_cycles_left--;
1096 SetPos(loop.LoopStart);
1097 }
1098 } while (samplestoread && readsamples);
1099 break;
1100 }
1101 }
1102 }
1103 }
1104
1105 // read on without looping
1106 if (samplestoread) do {
1107 readsamples = Read(&pDst[totalreadsamples * this->FrameSize], samplestoread, pExternalDecompressionBuffer);
1108 samplestoread -= readsamples;
1109 totalreadsamples += readsamples;
1110 } while (readsamples && samplestoread);
1111
1112 // store current position
1113 pPlaybackState->position = GetPos();
1114
1115 return totalreadsamples;
1116 }
1117
1118 /**
1119 * Reads \a SampleCount number of sample points from the current
1120 * position into the buffer pointed by \a pBuffer and increments the
1121 * position within the sample. The sample wave stream will be
1122 * decompressed on the fly if using a compressed sample. Use this method
1123 * and <i>SetPos()</i> if you don't want to load the sample into RAM,
1124 * thus for disk streaming.
1125 *
1126 * <b>Caution:</b> If you are using more than one streaming thread, you
1127 * have to use an external decompression buffer for <b>EACH</b>
1128 * streaming thread to avoid race conditions and crashes!
1129 *
1130 * For 16 bit samples, the data in the buffer will be int16_t
1131 * (using native endianness). For 24 bit, the buffer will
1132 * contain three bytes per sample, little-endian.
1133 *
1134 * @param pBuffer destination buffer
1135 * @param SampleCount number of sample points to read
1136 * @param pExternalDecompressionBuffer (optional) external buffer to use for decompression
1137 * @returns number of successfully read sample points
1138 * @see SetPos(), CreateDecompressionBuffer()
1139 */
1140 file_offset_t Sample::Read(void* pBuffer, file_offset_t SampleCount, buffer_t* pExternalDecompressionBuffer) {
1141 if (SampleCount == 0) return 0;
1142 if (!Compressed) {
1143 if (BitDepth == 24) {
1144 return pCkData->Read(pBuffer, SampleCount * FrameSize, 1) / FrameSize;
1145 }
1146 else { // 16 bit
1147 // (pCkData->Read does endian correction)
1148 return Channels == 2 ? pCkData->Read(pBuffer, SampleCount << 1, 2) >> 1
1149 : pCkData->Read(pBuffer, SampleCount, 2);
1150 }
1151 }
1152 else {
1153 if (this->SamplePos >= this->SamplesTotal) return 0;
1154 //TODO: efficiency: maybe we should test for an average compression rate
1155 file_offset_t assumedsize = GuessSize(SampleCount),
1156 remainingbytes = 0, // remaining bytes in the local buffer
1157 remainingsamples = SampleCount,
1158 copysamples, skipsamples,
1159 currentframeoffset = this->FrameOffset; // offset in current sample frame since last Read()
1160 this->FrameOffset = 0;
1161
1162 buffer_t* pDecompressionBuffer = (pExternalDecompressionBuffer) ? pExternalDecompressionBuffer : &InternalDecompressionBuffer;
1163
1164 // if decompression buffer too small, then reduce amount of samples to read
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);
1170 }
1171
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);
1176
1177 while (remainingsamples && remainingbytes) {
1178 file_offset_t framesamples = SamplesPerFrame;
1179 file_offset_t framebytes, rightChannelOffset = 0, nextFrameOffset;
1180
1181 int mode_l = *pSrc++, mode_r = 0;
1182
1183 if (Channels == 2) {
1184 mode_r = *pSrc++;
1185 framebytes = bytesPerFrame[mode_l] + bytesPerFrame[mode_r] + 2;
1186 rightChannelOffset = bytesPerFrameNoHdr[mode_l];
1187 nextFrameOffset = rightChannelOffset + bytesPerFrameNoHdr[mode_r];
1188 if (remainingbytes < framebytes) { // last frame in sample
1189 framesamples = SamplesInLastFrame;
1190 if (mode_l == 4 && (framesamples & 1)) {
1191 rightChannelOffset = ((framesamples + 1) * bitsPerSample[mode_l]) >> 3;
1192 }
1193 else {
1194 rightChannelOffset = (framesamples * bitsPerSample[mode_l]) >> 3;
1195 }
1196 }
1197 }
1198 else {
1199 framebytes = bytesPerFrame[mode_l] + 1;
1200 nextFrameOffset = bytesPerFrameNoHdr[mode_l];
1201 if (remainingbytes < framebytes) {
1202 framesamples = SamplesInLastFrame;
1203 }
1204 }
1205
1206 // determine how many samples in this frame to skip and read
1207 if (currentframeoffset + remainingsamples >= framesamples) {
1208 if (currentframeoffset <= framesamples) {
1209 copysamples = framesamples - currentframeoffset;
1210 skipsamples = currentframeoffset;
1211 }
1212 else {
1213 copysamples = 0;
1214 skipsamples = framesamples;
1215 }
1216 }
1217 else {
1218 // This frame has enough data for pBuffer, but not
1219 // all of the frame is needed. Set file position
1220 // to start of this frame for next call to Read.
1221 copysamples = remainingsamples;
1222 skipsamples = currentframeoffset;
1223 pCkData->SetPos(remainingbytes, RIFF::stream_backward);
1224 this->FrameOffset = currentframeoffset + copysamples;
1225 }
1226 remainingsamples -= copysamples;
1227
1228 if (remainingbytes > framebytes) {
1229 remainingbytes -= framebytes;
1230 if (remainingsamples == 0 &&
1231 currentframeoffset + copysamples == framesamples) {
1232 // This frame has enough data for pBuffer, and
1233 // all of the frame is needed. Set file
1234 // position to start of next frame for next
1235 // call to Read. FrameOffset is 0.
1236 pCkData->SetPos(remainingbytes, RIFF::stream_backward);
1237 }
1238 }
1239 else remainingbytes = 0;
1240
1241 currentframeoffset -= skipsamples;
1242
1243 if (copysamples == 0) {
1244 // skip this frame
1245 pSrc += framebytes - Channels;
1246 }
1247 else {
1248 const unsigned char* const param_l = pSrc;
1249 if (BitDepth == 24) {
1250 if (mode_l != 2) pSrc += 12;
1251
1252 if (Channels == 2) { // Stereo
1253 const unsigned char* const param_r = pSrc;
1254 if (mode_r != 2) pSrc += 12;
1255
1256 Decompress24(mode_l, param_l, 6, pSrc, pDst24,
1257 skipsamples, copysamples, TruncatedBits);
1258 Decompress24(mode_r, param_r, 6, pSrc + rightChannelOffset, pDst24 + 3,
1259 skipsamples, copysamples, TruncatedBits);
1260 pDst24 += copysamples * 6;
1261 }
1262 else { // Mono
1263 Decompress24(mode_l, param_l, 3, pSrc, pDst24,
1264 skipsamples, copysamples, TruncatedBits);
1265 pDst24 += copysamples * 3;
1266 }
1267 }
1268 else { // 16 bit
1269 if (mode_l) pSrc += 4;
1270
1271 int step;
1272 if (Channels == 2) { // Stereo
1273 const unsigned char* const param_r = pSrc;
1274 if (mode_r) pSrc += 4;
1275
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;
1281 }
1282 else { // Mono
1283 step = 2 - mode_l;
1284 Decompress16(mode_l, param_l, step, 1, pSrc, pDst, skipsamples, copysamples);
1285 pDst += copysamples;
1286 }
1287 }
1288 pSrc += nextFrameOffset;
1289 }
1290
1291 // reload from disk to local buffer if needed
1292 if (remainingsamples && remainingbytes < WorstCaseFrameSize && pCkData->GetState() == RIFF::stream_ready) {
1293 assumedsize = GuessSize(remainingsamples);
1294 pCkData->SetPos(remainingbytes, RIFF::stream_backward);
1295 if (pCkData->RemainingBytes() < assumedsize) assumedsize = pCkData->RemainingBytes();
1296 remainingbytes = pCkData->Read(pDecompressionBuffer->pStart, assumedsize, 1);
1297 pSrc = (unsigned char*) pDecompressionBuffer->pStart;
1298 }
1299 } // while
1300
1301 this->SamplePos += (SampleCount - remainingsamples);
1302 if (this->SamplePos > this->SamplesTotal) this->SamplePos = this->SamplesTotal;
1303 return (SampleCount - remainingsamples);
1304 }
1305 }
1306
1307 /** @brief Write sample wave data.
1308 *
1309 * Writes \a SampleCount number of sample points from the buffer pointed
1310 * by \a pBuffer and increments the position within the sample. Use this
1311 * method to directly write the sample data to disk, i.e. if you don't
1312 * want or cannot load the whole sample data into RAM.
1313 *
1314 * You have to Resize() the sample to the desired size and call
1315 * File::Save() <b>before</b> using Write().
1316 *
1317 * Note: there is currently no support for writing compressed samples.
1318 *
1319 * For 16 bit samples, the data in the source buffer should be
1320 * int16_t (using native endianness). For 24 bit, the buffer
1321 * should contain three bytes per sample, little-endian.
1322 *
1323 * @param pBuffer - source buffer
1324 * @param SampleCount - number of sample points to write
1325 * @throws DLS::Exception if current sample size is too small
1326 * @throws gig::Exception if sample is compressed
1327 * @see DLS::LoadSampleData()
1328 */
1329 file_offset_t Sample::Write(void* pBuffer, file_offset_t SampleCount) {
1330 if (Compressed) throw gig::Exception("There is no support for writing compressed gig samples (yet)");
1331
1332 // if this is the first write in this sample, reset the
1333 // checksum calculator
1334 if (pCkData->GetPos() == 0) {
1335 __resetCRC(crc);
1336 }
1337 if (GetSize() < SampleCount) throw Exception("Could not write sample data, current sample size to small");
1338 file_offset_t res;
1339 if (BitDepth == 24) {
1340 res = pCkData->Write(pBuffer, SampleCount * FrameSize, 1) / FrameSize;
1341 } else { // 16 bit
1342 res = Channels == 2 ? pCkData->Write(pBuffer, SampleCount << 1, 2) >> 1
1343 : pCkData->Write(pBuffer, SampleCount, 2);
1344 }
1345 __calculateCRC((unsigned char *)pBuffer, SampleCount * FrameSize, crc);
1346
1347 // if this is the last write, update the checksum chunk in the
1348 // file
1349 if (pCkData->GetPos() == pCkData->GetSize()) {
1350 __finalizeCRC(crc);
1351 File* pFile = static_cast<File*>(GetParent());
1352 pFile->SetSampleChecksum(this, crc);
1353 }
1354 return res;
1355 }
1356
1357 /**
1358 * Allocates a decompression buffer for streaming (compressed) samples
1359 * with Sample::Read(). If you are using more than one streaming thread
1360 * in your application you <b>HAVE</b> to create a decompression buffer
1361 * for <b>EACH</b> of your streaming threads and provide it with the
1362 * Sample::Read() call in order to avoid race conditions and crashes.
1363 *
1364 * You should free the memory occupied by the allocated buffer(s) once
1365 * you don't need one of your streaming threads anymore by calling
1366 * DestroyDecompressionBuffer().
1367 *
1368 * @param MaxReadSize - the maximum size (in sample points) you ever
1369 * expect to read with one Read() call
1370 * @returns allocated decompression buffer
1371 * @see DestroyDecompressionBuffer()
1372 */
1373 buffer_t Sample::CreateDecompressionBuffer(file_offset_t MaxReadSize) {
1374 buffer_t result;
1375 const double worstCaseHeaderOverhead =
1376 (256.0 /*frame size*/ + 12.0 /*header*/ + 2.0 /*compression type flag (stereo)*/) / 256.0;
1377 result.Size = (file_offset_t) (double(MaxReadSize) * 3.0 /*(24 Bit)*/ * 2.0 /*stereo*/ * worstCaseHeaderOverhead);
1378 result.pStart = new int8_t[result.Size];
1379 result.NullExtensionSize = 0;
1380 return result;
1381 }
1382
1383 /**
1384 * Free decompression buffer, previously created with
1385 * CreateDecompressionBuffer().
1386 *
1387 * @param DecompressionBuffer - previously allocated decompression
1388 * buffer to free
1389 */
1390 void Sample::DestroyDecompressionBuffer(buffer_t& DecompressionBuffer) {
1391 if (DecompressionBuffer.Size && DecompressionBuffer.pStart) {
1392 delete[] (int8_t*) DecompressionBuffer.pStart;
1393 DecompressionBuffer.pStart = NULL;
1394 DecompressionBuffer.Size = 0;
1395 DecompressionBuffer.NullExtensionSize = 0;
1396 }
1397 }
1398
1399 /**
1400 * Returns pointer to the Group this Sample belongs to. In the .gig
1401 * format a sample always belongs to one group. If it wasn't explicitly
1402 * assigned to a certain group, it will be automatically assigned to a
1403 * default group.
1404 *
1405 * @returns Sample's Group (never NULL)
1406 */
1407 Group* Sample::GetGroup() const {
1408 return pGroup;
1409 }
1410
1411 /**
1412 * Returns the CRC-32 checksum of the sample's raw wave form data at the
1413 * time when this sample's wave form data was modified for the last time
1414 * by calling Write(). This checksum only covers the raw wave form data,
1415 * not any meta informations like i.e. bit depth or loop points. Since
1416 * this method just returns the checksum stored for this sample i.e. when
1417 * the gig file was loaded, this method returns immediately. So it does no
1418 * recalcuation of the checksum with the currently available sample wave
1419 * form data.
1420 *
1421 * @see VerifyWaveData()
1422 */
1423 uint32_t Sample::GetWaveDataCRC32Checksum() {
1424 return crc;
1425 }
1426
1427 /**
1428 * Checks the integrity of this sample's raw audio wave data. Whenever a
1429 * Sample's raw wave data is intentionally modified (i.e. by calling
1430 * Write() and supplying the new raw audio wave form data) a CRC32 checksum
1431 * is calculated and stored/updated for this sample, along to the sample's
1432 * meta informations.
1433 *
1434 * Now by calling this method the current raw audio wave data is checked
1435 * against the already stored CRC32 check sum in order to check whether the
1436 * sample data had been damaged unintentionally for some reason. Since by
1437 * calling this method always the entire raw audio wave data has to be
1438 * read, verifying all samples this way may take a long time accordingly.
1439 * And that's also the reason why the sample integrity is not checked by
1440 * default whenever a gig file is loaded. So this method must be called
1441 * explicitly to fulfill this task.
1442 *
1443 * @param pActually - (optional) if provided, will be set to the actually
1444 * calculated checksum of the current raw wave form data,
1445 * you can get the expected checksum instead by calling
1446 * GetWaveDataCRC32Checksum()
1447 * @returns true if sample is OK or false if the sample is damaged
1448 * @throws Exception if no checksum had been stored to disk for this
1449 * sample yet, or on I/O issues
1450 * @see GetWaveDataCRC32Checksum()
1451 */
1452 bool Sample::VerifyWaveData(uint32_t* pActually) {
1453 //File* pFile = static_cast<File*>(GetParent());
1454 uint32_t crc = CalculateWaveDataChecksum();
1455 if (pActually) *pActually = crc;
1456 return crc == this->crc;
1457 }
1458
1459 uint32_t Sample::CalculateWaveDataChecksum() {
1460 const size_t sz = 20*1024; // 20kB buffer size
1461 std::vector<uint8_t> buffer(sz);
1462 buffer.resize(sz);
1463
1464 const size_t n = sz / FrameSize;
1465 SetPos(0);
1466 uint32_t crc = 0;
1467 __resetCRC(crc);
1468 while (true) {
1469 file_offset_t nRead = Read(&buffer[0], n);
1470 if (nRead <= 0) break;
1471 __calculateCRC(&buffer[0], nRead * FrameSize, crc);
1472 }
1473 __finalizeCRC(crc);
1474 return crc;
1475 }
1476
1477 Sample::~Sample() {
1478 Instances--;
1479 if (!Instances && InternalDecompressionBuffer.Size) {
1480 delete[] (unsigned char*) InternalDecompressionBuffer.pStart;
1481 InternalDecompressionBuffer.pStart = NULL;
1482 InternalDecompressionBuffer.Size = 0;
1483 }
1484 if (FrameTable) delete[] FrameTable;
1485 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
1486 }
1487
1488
1489
1490 // *************** DimensionRegion ***************
1491 // *
1492
1493 size_t DimensionRegion::Instances = 0;
1494 DimensionRegion::VelocityTableMap* DimensionRegion::pVelocityTables = NULL;
1495
1496 DimensionRegion::DimensionRegion(Region* pParent, RIFF::List* _3ewl) : DLS::Sampler(_3ewl) {
1497 Instances++;
1498
1499 pSample = NULL;
1500 pRegion = pParent;
1501
1502 if (_3ewl->GetSubChunk(CHUNK_ID_WSMP)) memcpy(&Crossfade, &SamplerOptions, 4);
1503 else memset(&Crossfade, 0, 4);
1504
1505 if (!pVelocityTables) pVelocityTables = new VelocityTableMap;
1506
1507 RIFF::Chunk* _3ewa = _3ewl->GetSubChunk(CHUNK_ID_3EWA);
1508 if (_3ewa) { // if '3ewa' chunk exists
1509 _3ewa->SetPos(0);
1510
1511 _3ewa->ReadInt32(); // unknown, always == chunk size ?
1512 LFO3Frequency = (double) GIG_EXP_DECODE(_3ewa->ReadInt32());
1513 EG3Attack = (double) GIG_EXP_DECODE(_3ewa->ReadInt32());
1514 _3ewa->ReadInt16(); // unknown
1515 LFO1InternalDepth = _3ewa->ReadUint16();
1516 _3ewa->ReadInt16(); // unknown
1517 LFO3InternalDepth = _3ewa->ReadInt16();
1518 _3ewa->ReadInt16(); // unknown
1519 LFO1ControlDepth = _3ewa->ReadUint16();
1520 _3ewa->ReadInt16(); // unknown
1521 LFO3ControlDepth = _3ewa->ReadInt16();
1522 EG1Attack = (double) GIG_EXP_DECODE(_3ewa->ReadInt32());
1523 EG1Decay1 = (double) GIG_EXP_DECODE(_3ewa->ReadInt32());
1524 _3ewa->ReadInt16(); // unknown
1525 EG1Sustain = _3ewa->ReadUint16();
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());
1542 _3ewa->ReadInt16(); // unknown
1543 EG2Sustain = _3ewa->ReadUint16();
1544 EG2Release = (double) GIG_EXP_DECODE(_3ewa->ReadInt32());
1545 _3ewa->ReadInt16(); // unknown
1546 LFO2ControlDepth = _3ewa->ReadUint16();
1547 LFO2Frequency = (double) GIG_EXP_DECODE(_3ewa->ReadInt32());
1548 _3ewa->ReadInt16(); // unknown
1549 LFO2InternalDepth = _3ewa->ReadUint16();
1550 int32_t eg1decay2 = _3ewa->ReadInt32();
1551 EG1Decay2 = (double) GIG_EXP_DECODE(eg1decay2);
1552 EG1InfiniteSustain = (eg1decay2 == 0x7fffffff);
1553 _3ewa->ReadInt16(); // unknown
1554 EG1PreAttack = _3ewa->ReadUint16();
1555 int32_t eg2decay2 = _3ewa->ReadInt32();
1556 EG2Decay2 = (double) GIG_EXP_DECODE(eg2decay2);
1557 EG2InfiniteSustain = (eg2decay2 == 0x7fffffff);
1558 _3ewa->ReadInt16(); // unknown
1559 EG2PreAttack = _3ewa->ReadUint16();
1560 uint8_t velocityresponse = _3ewa->ReadUint8();
1561 if (velocityresponse < 5) {
1562 VelocityResponseCurve = curve_type_nonlinear;
1563 VelocityResponseDepth = velocityresponse;
1564 } else if (velocityresponse < 10) {
1565 VelocityResponseCurve = curve_type_linear;
1566 VelocityResponseDepth = velocityresponse - 5;
1567 } else if (velocityresponse < 15) {
1568 VelocityResponseCurve = curve_type_special;
1569 VelocityResponseDepth = velocityresponse - 10;
1570 } else {
1571 VelocityResponseCurve = curve_type_unknown;
1572 VelocityResponseDepth = 0;
1573 }
1574 uint8_t releasevelocityresponse = _3ewa->ReadUint8();
1575 if (releasevelocityresponse < 5) {
1576 ReleaseVelocityResponseCurve = curve_type_nonlinear;
1577 ReleaseVelocityResponseDepth = releasevelocityresponse;
1578 } else if (releasevelocityresponse < 10) {
1579 ReleaseVelocityResponseCurve = curve_type_linear;
1580 ReleaseVelocityResponseDepth = releasevelocityresponse - 5;
1581 } else if (releasevelocityresponse < 15) {
1582 ReleaseVelocityResponseCurve = curve_type_special;
1583 ReleaseVelocityResponseDepth = releasevelocityresponse - 10;
1584 } else {
1585 ReleaseVelocityResponseCurve = curve_type_unknown;
1586 ReleaseVelocityResponseDepth = 0;
1587 }
1588 VelocityResponseCurveScaling = _3ewa->ReadUint8();
1589 AttenuationControllerThreshold = _3ewa->ReadInt8();
1590 _3ewa->ReadInt32(); // unknown
1591 SampleStartOffset = (uint16_t) _3ewa->ReadInt16();
1592 _3ewa->ReadInt16(); // unknown
1593 uint8_t pitchTrackDimensionBypass = _3ewa->ReadInt8();
1594 PitchTrack = GIG_PITCH_TRACK_EXTRACT(pitchTrackDimensionBypass);
1595 if (pitchTrackDimensionBypass & 0x10) DimensionBypass = dim_bypass_ctrl_94;
1596 else if (pitchTrackDimensionBypass & 0x20) DimensionBypass = dim_bypass_ctrl_95;
1597 else DimensionBypass = dim_bypass_ctrl_none;
1598 uint8_t pan = _3ewa->ReadUint8();
1599 Pan = (pan < 64) ? pan : -((int)pan - 63); // signed 7 bit -> signed 8 bit
1600 SelfMask = _3ewa->ReadInt8() & 0x01;
1601 _3ewa->ReadInt8(); // unknown
1602 uint8_t lfo3ctrl = _3ewa->ReadUint8();
1603 LFO3Controller = static_cast<lfo3_ctrl_t>(lfo3ctrl & 0x07); // lower 3 bits
1604 LFO3Sync = lfo3ctrl & 0x20; // bit 5
1605 InvertAttenuationController = lfo3ctrl & 0x80; // bit 7
1606 AttenuationController = DecodeLeverageController(static_cast<_lev_ctrl_t>(_3ewa->ReadUint8()));
1607 uint8_t lfo2ctrl = _3ewa->ReadUint8();
1608 LFO2Controller = static_cast<lfo2_ctrl_t>(lfo2ctrl & 0x07); // lower 3 bits
1609 LFO2FlipPhase = lfo2ctrl & 0x80; // bit 7
1610 LFO2Sync = lfo2ctrl & 0x20; // bit 5
1611 bool extResonanceCtrl = lfo2ctrl & 0x40; // bit 6
1612 uint8_t lfo1ctrl = _3ewa->ReadUint8();
1613 LFO1Controller = static_cast<lfo1_ctrl_t>(lfo1ctrl & 0x07); // lower 3 bits
1614 LFO1FlipPhase = lfo1ctrl & 0x80; // bit 7
1615 LFO1Sync = lfo1ctrl & 0x40; // bit 6
1616 VCFResonanceController = (extResonanceCtrl) ? static_cast<vcf_res_ctrl_t>(GIG_VCF_RESONANCE_CTRL_EXTRACT(lfo1ctrl))
1617 : vcf_res_ctrl_none;
1618 uint16_t eg3depth = _3ewa->ReadUint16();
1619 EG3Depth = (eg3depth <= 1200) ? eg3depth /* positives */
1620 : (-1) * (int16_t) ((eg3depth ^ 0xfff) + 1); /* binary complementary for negatives */
1621 _3ewa->ReadInt16(); // unknown
1622 ChannelOffset = _3ewa->ReadUint8() / 4;
1623 uint8_t regoptions = _3ewa->ReadUint8();
1624 MSDecode = regoptions & 0x01; // bit 0
1625 SustainDefeat = regoptions & 0x02; // bit 1
1626 _3ewa->ReadInt16(); // unknown
1627 VelocityUpperLimit = _3ewa->ReadInt8();
1628 _3ewa->ReadInt8(); // unknown
1629 _3ewa->ReadInt16(); // unknown
1630 ReleaseTriggerDecay = _3ewa->ReadUint8(); // release trigger decay
1631 _3ewa->ReadInt8(); // unknown
1632 _3ewa->ReadInt8(); // unknown
1633 EG1Hold = _3ewa->ReadUint8() & 0x80; // bit 7
1634 uint8_t vcfcutoff = _3ewa->ReadUint8();
1635 VCFEnabled = vcfcutoff & 0x80; // bit 7
1636 VCFCutoff = vcfcutoff & 0x7f; // lower 7 bits
1637 VCFCutoffController = static_cast<vcf_cutoff_ctrl_t>(_3ewa->ReadUint8());
1638 uint8_t vcfvelscale = _3ewa->ReadUint8();
1639 VCFCutoffControllerInvert = vcfvelscale & 0x80; // bit 7
1640 VCFVelocityScale = vcfvelscale & 0x7f; // lower 7 bits
1641 _3ewa->ReadInt8(); // unknown
1642 uint8_t vcfresonance = _3ewa->ReadUint8();
1643 VCFResonance = vcfresonance & 0x7f; // lower 7 bits
1644 VCFResonanceDynamic = !(vcfresonance & 0x80); // bit 7
1645 uint8_t vcfbreakpoint = _3ewa->ReadUint8();
1646 VCFKeyboardTracking = vcfbreakpoint & 0x80; // bit 7
1647 VCFKeyboardTrackingBreakpoint = vcfbreakpoint & 0x7f; // lower 7 bits
1648 uint8_t vcfvelocity = _3ewa->ReadUint8();
1649 VCFVelocityDynamicRange = vcfvelocity % 5;
1650 VCFVelocityCurve = static_cast<curve_type_t>(vcfvelocity / 5);
1651 VCFType = static_cast<vcf_type_t>(_3ewa->ReadUint8());
1652 if (VCFType == vcf_type_lowpass) {
1653 if (lfo3ctrl & 0x40) // bit 6
1654 VCFType = vcf_type_lowpassturbo;
1655 }
1656 if (_3ewa->RemainingBytes() >= 8) {
1657 _3ewa->Read(DimensionUpperLimits, 1, 8);
1658 } else {
1659 memset(DimensionUpperLimits, 0, 8);
1660 }
1661 } else { // '3ewa' chunk does not exist yet
1662 // use default values
1663 LFO3Frequency = 1.0;
1664 EG3Attack = 0.0;
1665 LFO1InternalDepth = 0;
1666 LFO3InternalDepth = 0;
1667 LFO1ControlDepth = 0;
1668 LFO3ControlDepth = 0;
1669 EG1Attack = 0.0;
1670 EG1Decay1 = 0.005;
1671 EG1Sustain = 1000;
1672 EG1Release = 0.3;
1673 EG1Controller.type = eg1_ctrl_t::type_none;
1674 EG1Controller.controller_number = 0;
1675 EG1ControllerInvert = false;
1676 EG1ControllerAttackInfluence = 0;
1677 EG1ControllerDecayInfluence = 0;
1678 EG1ControllerReleaseInfluence = 0;
1679 EG2Controller.type = eg2_ctrl_t::type_none;
1680 EG2Controller.controller_number = 0;
1681 EG2ControllerInvert = false;
1682 EG2ControllerAttackInfluence = 0;
1683 EG2ControllerDecayInfluence = 0;
1684 EG2ControllerReleaseInfluence = 0;
1685 LFO1Frequency = 1.0;
1686 EG2Attack = 0.0;
1687 EG2Decay1 = 0.005;
1688 EG2Sustain = 1000;
1689 EG2Release = 60;
1690 LFO2ControlDepth = 0;
1691 LFO2Frequency = 1.0;
1692 LFO2InternalDepth = 0;
1693 EG1Decay2 = 0.0;
1694 EG1InfiniteSustain = true;
1695 EG1PreAttack = 0;
1696 EG2Decay2 = 0.0;
1697 EG2InfiniteSustain = true;
1698 EG2PreAttack = 0;
1699 VelocityResponseCurve = curve_type_nonlinear;
1700 VelocityResponseDepth = 3;
1701 ReleaseVelocityResponseCurve = curve_type_nonlinear;
1702 ReleaseVelocityResponseDepth = 3;
1703 VelocityResponseCurveScaling = 32;
1704 AttenuationControllerThreshold = 0;
1705 SampleStartOffset = 0;
1706 PitchTrack = true;
1707 DimensionBypass = dim_bypass_ctrl_none;
1708 Pan = 0;
1709 SelfMask = true;
1710 LFO3Controller = lfo3_ctrl_modwheel;
1711 LFO3Sync = false;
1712 InvertAttenuationController = false;
1713 AttenuationController.type = attenuation_ctrl_t::type_none;
1714 AttenuationController.controller_number = 0;
1715 LFO2Controller = lfo2_ctrl_internal;
1716 LFO2FlipPhase = false;
1717 LFO2Sync = false;
1718 LFO1Controller = lfo1_ctrl_internal;
1719 LFO1FlipPhase = false;
1720 LFO1Sync = false;
1721 VCFResonanceController = vcf_res_ctrl_none;
1722 EG3Depth = 0;
1723 ChannelOffset = 0;
1724 MSDecode = false;
1725 SustainDefeat = false;
1726 VelocityUpperLimit = 0;
1727 ReleaseTriggerDecay = 0;
1728 EG1Hold = false;
1729 VCFEnabled = false;
1730 VCFCutoff = 0;
1731 VCFCutoffController = vcf_cutoff_ctrl_none;
1732 VCFCutoffControllerInvert = false;
1733 VCFVelocityScale = 0;
1734 VCFResonance = 0;
1735 VCFResonanceDynamic = false;
1736 VCFKeyboardTracking = false;
1737 VCFKeyboardTrackingBreakpoint = 0;
1738 VCFVelocityDynamicRange = 0x04;
1739 VCFVelocityCurve = curve_type_linear;
1740 VCFType = vcf_type_lowpass;
1741 memset(DimensionUpperLimits, 127, 8);
1742 }
1743
1744 // chunk for own format extensions, these will *NOT* work with Gigasampler/GigaStudio !
1745 RIFF::Chunk* lsde = _3ewl->GetSubChunk(CHUNK_ID_LSDE);
1746 if (lsde) { // format extension for EG behavior options
1747 lsde->SetPos(0);
1748
1749 eg_opt_t* pEGOpts[2] = { &EG1Options, &EG2Options };
1750 for (int i = 0; i < 2; ++i) { // NOTE: we reserved a 3rd byte for a potential future EG3 option
1751 unsigned char byte = lsde->ReadUint8();
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);
1757 }
1758 }
1759 // format extension for sustain pedal up effect on release trigger samples
1760 if (lsde && lsde->GetSize() > 3) { // NOTE: we reserved the 3rd byte for a potential future EG3 option
1761 lsde->SetPos(3);
1762 uint8_t byte = lsde->ReadUint8();
1763 SustainReleaseTrigger = static_cast<sust_rel_trg_t>(byte & 0x03);
1764 NoNoteOffReleaseTrigger = byte >> 7;
1765 } else {
1766 SustainReleaseTrigger = sust_rel_trg_none;
1767 NoNoteOffReleaseTrigger = false;
1768 }
1769 // format extension for LFOs' wave form, phase displacement and for
1770 // LFO3's flip phase
1771 if (lsde && lsde->GetSize() > 4) {
1772 lsde->SetPos(4);
1773 LFO1WaveForm = static_cast<lfo_wave_t>( lsde->ReadUint16() );
1774 LFO2WaveForm = static_cast<lfo_wave_t>( lsde->ReadUint16() );
1775 LFO3WaveForm = static_cast<lfo_wave_t>( lsde->ReadUint16() );
1776 lsde->ReadUint16(); // unused 16 bits, reserved for potential future use
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;
1782 } else {
1783 LFO1WaveForm = lfo_wave_sine;
1784 LFO2WaveForm = lfo_wave_sine;
1785 LFO3WaveForm = lfo_wave_sine;
1786 LFO1Phase = 0.0;
1787 LFO2Phase = 0.0;
1788 LFO3Phase = 0.0;
1789 LFO3FlipPhase = false;
1790 }
1791
1792 pVelocityAttenuationTable = GetVelocityTable(VelocityResponseCurve,
1793 VelocityResponseDepth,
1794 VelocityResponseCurveScaling);
1795
1796 pVelocityReleaseTable = GetReleaseVelocityTable(
1797 ReleaseVelocityResponseCurve,
1798 ReleaseVelocityResponseDepth
1799 );
1800
1801 pVelocityCutoffTable = GetCutoffVelocityTable(VCFVelocityCurve,
1802 VCFVelocityDynamicRange,
1803 VCFVelocityScale,
1804 VCFCutoffController);
1805
1806 SampleAttenuation = pow(10.0, -Gain / (20.0 * 655360));
1807 VelocityTable = 0;
1808 }
1809
1810 /*
1811 * Constructs a DimensionRegion by copying all parameters from
1812 * another DimensionRegion
1813 */
1814 DimensionRegion::DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src) : DLS::Sampler(_3ewl) {
1815 Instances++;
1816 //NOTE: I think we cannot call CopyAssign() here (in a constructor) as long as its a virtual method
1817 *this = src; // default memberwise shallow copy of all parameters
1818 pParentList = _3ewl; // restore the chunk pointer
1819
1820 // deep copy of owned structures
1821 if (src.VelocityTable) {
1822 VelocityTable = new uint8_t[128];
1823 for (int k = 0 ; k < 128 ; k++)
1824 VelocityTable[k] = src.VelocityTable[k];
1825 }
1826 if (src.pSampleLoops) {
1827 pSampleLoops = new DLS::sample_loop_t[src.SampleLoops];
1828 for (int k = 0 ; k < src.SampleLoops ; k++)
1829 pSampleLoops[k] = src.pSampleLoops[k];
1830 }
1831 }
1832
1833 /**
1834 * Make a (semi) deep copy of the DimensionRegion object given by @a orig
1835 * and assign it to this object.
1836 *
1837 * Note that all sample pointers referenced by @a orig are simply copied as
1838 * memory address. Thus the respective samples are shared, not duplicated!
1839 *
1840 * @param orig - original DimensionRegion object to be copied from
1841 */
1842 void DimensionRegion::CopyAssign(const DimensionRegion* orig) {
1843 CopyAssign(orig, NULL);
1844 }
1845
1846 /**
1847 * Make a (semi) deep copy of the DimensionRegion object given by @a orig
1848 * and assign it to this object.
1849 *
1850 * @param orig - original DimensionRegion object to be copied from
1851 * @param mSamples - crosslink map between the foreign file's samples and
1852 * this file's samples
1853 */
1854 void DimensionRegion::CopyAssign(const DimensionRegion* orig, const std::map<Sample*,Sample*>* mSamples) {
1855 // delete all allocated data first
1856 if (VelocityTable) delete [] VelocityTable;
1857 if (pSampleLoops) delete [] pSampleLoops;
1858
1859 // backup parent list pointer
1860 RIFF::List* p = pParentList;
1861
1862 gig::Sample* pOriginalSample = pSample;
1863 gig::Region* pOriginalRegion = pRegion;
1864
1865 //NOTE: copy code copied from assignment constructor above, see comment there as well
1866
1867 *this = *orig; // default memberwise shallow copy of all parameters
1868
1869 // restore members that shall not be altered
1870 pParentList = p; // restore the chunk pointer
1871 pRegion = pOriginalRegion;
1872
1873 // only take the raw sample reference reference if the
1874 // two DimensionRegion objects are part of the same file
1875 if (pOriginalRegion->GetParent()->GetParent() != orig->pRegion->GetParent()->GetParent()) {
1876 pSample = pOriginalSample;
1877 }
1878
1879 if (mSamples && mSamples->count(orig->pSample)) {
1880 pSample = mSamples->find(orig->pSample)->second;
1881 }
1882
1883 // deep copy of owned structures
1884 if (orig->VelocityTable) {
1885 VelocityTable = new uint8_t[128];
1886 for (int k = 0 ; k < 128 ; k++)
1887 VelocityTable[k] = orig->VelocityTable[k];
1888 }
1889 if (orig->pSampleLoops) {
1890 pSampleLoops = new DLS::sample_loop_t[orig->SampleLoops];
1891 for (int k = 0 ; k < orig->SampleLoops ; k++)
1892 pSampleLoops[k] = orig->pSampleLoops[k];
1893 }
1894 }
1895
1896 void DimensionRegion::serialize(Serialization::Archive* archive) {
1897 // in case this class will become backward incompatible one day,
1898 // then set a version and minimum version for this class like:
1899 //archive->setVersion(*this, 2);
1900 //archive->setMinVersion(*this, 1);
1901
1902 SRLZ(VelocityUpperLimit);
1903 SRLZ(EG1PreAttack);
1904 SRLZ(EG1Attack);
1905 SRLZ(EG1Decay1);
1906 SRLZ(EG1Decay2);
1907 SRLZ(EG1InfiniteSustain);
1908 SRLZ(EG1Sustain);
1909 SRLZ(EG1Release);
1910 SRLZ(EG1Hold);
1911 SRLZ(EG1Controller);
1912 SRLZ(EG1ControllerInvert);
1913 SRLZ(EG1ControllerAttackInfluence);
1914 SRLZ(EG1ControllerDecayInfluence);
1915 SRLZ(EG1ControllerReleaseInfluence);
1916 SRLZ(LFO1WaveForm);
1917 SRLZ(LFO1Frequency);
1918 SRLZ(LFO1Phase);
1919 SRLZ(LFO1InternalDepth);
1920 SRLZ(LFO1ControlDepth);
1921 SRLZ(LFO1Controller);
1922 SRLZ(LFO1FlipPhase);
1923 SRLZ(LFO1Sync);
1924 SRLZ(EG2PreAttack);
1925 SRLZ(EG2Attack);
1926 SRLZ(EG2Decay1);
1927 SRLZ(EG2Decay2);
1928 SRLZ(EG2InfiniteSustain);
1929 SRLZ(EG2Sustain);
1930 SRLZ(EG2Release);
1931 SRLZ(EG2Controller);
1932 SRLZ(EG2ControllerInvert);
1933 SRLZ(EG2ControllerAttackInfluence);
1934 SRLZ(EG2ControllerDecayInfluence);
1935 SRLZ(EG2ControllerReleaseInfluence);
1936 SRLZ(LFO2WaveForm);
1937 SRLZ(LFO2Frequency);
1938 SRLZ(LFO2Phase);
1939 SRLZ(LFO2InternalDepth);
1940 SRLZ(LFO2ControlDepth);
1941 SRLZ(LFO2Controller);
1942 SRLZ(LFO2FlipPhase);
1943 SRLZ(LFO2Sync);
1944 SRLZ(EG3Attack);
1945 SRLZ(EG3Depth);
1946 SRLZ(LFO3WaveForm);
1947 SRLZ(LFO3Frequency);
1948 SRLZ(LFO3Phase);
1949 SRLZ(LFO3InternalDepth);
1950 SRLZ(LFO3ControlDepth);
1951 SRLZ(LFO3Controller);
1952 SRLZ(LFO3FlipPhase);
1953 SRLZ(LFO3Sync);
1954 SRLZ(VCFEnabled);
1955 SRLZ(VCFType);
1956 SRLZ(VCFCutoffController);
1957 SRLZ(VCFCutoffControllerInvert);
1958 SRLZ(VCFCutoff);
1959 SRLZ(VCFVelocityCurve);
1960 SRLZ(VCFVelocityScale);
1961 SRLZ(VCFVelocityDynamicRange);
1962 SRLZ(VCFResonance);
1963 SRLZ(VCFResonanceDynamic);
1964 SRLZ(VCFResonanceController);
1965 SRLZ(VCFKeyboardTracking);
1966 SRLZ(VCFKeyboardTrackingBreakpoint);
1967 SRLZ(VelocityResponseCurve);
1968 SRLZ(VelocityResponseDepth);
1969 SRLZ(VelocityResponseCurveScaling);
1970 SRLZ(ReleaseVelocityResponseCurve);
1971 SRLZ(ReleaseVelocityResponseDepth);
1972 SRLZ(ReleaseTriggerDecay);
1973 SRLZ(Crossfade);
1974 SRLZ(PitchTrack);
1975 SRLZ(DimensionBypass);
1976 SRLZ(Pan);
1977 SRLZ(SelfMask);
1978 SRLZ(AttenuationController);
1979 SRLZ(InvertAttenuationController);
1980 SRLZ(AttenuationControllerThreshold);
1981 SRLZ(ChannelOffset);
1982 SRLZ(SustainDefeat);
1983 SRLZ(MSDecode);
1984 //SRLZ(SampleStartOffset);
1985 SRLZ(SampleAttenuation);
1986 SRLZ(EG1Options);
1987 SRLZ(EG2Options);
1988 SRLZ(SustainReleaseTrigger);
1989 SRLZ(NoNoteOffReleaseTrigger);
1990
1991 // derived attributes from DLS::Sampler
1992 SRLZ(FineTune);
1993 SRLZ(Gain);
1994 }
1995
1996 /**
1997 * Updates the respective member variable and updates @c SampleAttenuation
1998 * which depends on this value.
1999 */
2000 void DimensionRegion::SetGain(int32_t gain) {
2001 DLS::Sampler::SetGain(gain);
2002 SampleAttenuation = pow(10.0, -Gain / (20.0 * 655360));
2003 }
2004
2005 /**
2006 * Apply dimension region settings to the respective RIFF chunks. You
2007 * have to call File::Save() to make changes persistent.
2008 *
2009 * Usually there is absolutely no need to call this method explicitly.
2010 * It will be called automatically when File::Save() was called.
2011 *
2012 * @param pProgress - callback function for progress notification
2013 */
2014 void DimensionRegion::UpdateChunks(progress_t* pProgress) {
2015 // first update base class's chunk
2016 DLS::Sampler::UpdateChunks(pProgress);
2017
2018 RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);
2019 uint8_t* pData = (uint8_t*) wsmp->LoadChunkData();
2020 pData[12] = Crossfade.in_start;
2021 pData[13] = Crossfade.in_end;
2022 pData[14] = Crossfade.out_start;
2023 pData[15] = Crossfade.out_end;
2024
2025 // make sure '3ewa' chunk exists
2026 RIFF::Chunk* _3ewa = pParentList->GetSubChunk(CHUNK_ID_3EWA);
2027 if (!_3ewa) {
2028 File* pFile = (File*) GetParent()->GetParent()->GetParent();
2029 bool versiongt2 = pFile->pVersion && pFile->pVersion->major > 2;
2030 _3ewa = pParentList->AddSubChunk(CHUNK_ID_3EWA, versiongt2 ? 148 : 140);
2031 }
2032 pData = (uint8_t*) _3ewa->LoadChunkData();
2033
2034 // update '3ewa' chunk with DimensionRegion's current settings
2035
2036 const uint32_t chunksize = (uint32_t) _3ewa->GetNewSize();
2037 store32(&pData[0], chunksize); // unknown, always chunk size?
2038
2039 const int32_t lfo3freq = (int32_t) GIG_EXP_ENCODE(LFO3Frequency);
2040 store32(&pData[4], lfo3freq);
2041
2042 const int32_t eg3attack = (int32_t) GIG_EXP_ENCODE(EG3Attack);
2043 store32(&pData[8], eg3attack);
2044
2045 // next 2 bytes unknown
2046
2047 store16(&pData[14], LFO1InternalDepth);
2048
2049 // next 2 bytes unknown
2050
2051 store16(&pData[18], LFO3InternalDepth);
2052
2053 // next 2 bytes unknown
2054
2055 store16(&pData[22], LFO1ControlDepth);
2056
2057 // next 2 bytes unknown
2058
2059 store16(&pData[26], LFO3ControlDepth);
2060
2061 const int32_t eg1attack = (int32_t) GIG_EXP_ENCODE(EG1Attack);
2062 store32(&pData[28], eg1attack);
2063
2064 const int32_t eg1decay1 = (int32_t) GIG_EXP_ENCODE(EG1Decay1);
2065 store32(&pData[32], eg1decay1);
2066
2067 // next 2 bytes unknown
2068
2069 store16(&pData[38], EG1Sustain);
2070
2071 const int32_t eg1release = (int32_t) GIG_EXP_ENCODE(EG1Release);
2072 store32(&pData[40], eg1release);
2073
2074 const uint8_t eg1ctl = (uint8_t) EncodeLeverageController(EG1Controller);
2075 pData[44] = eg1ctl;
2076
2077 const uint8_t eg1ctrloptions =
2078 (EG1ControllerInvert ? 0x01 : 0x00) |
2079 GIG_EG_CTR_ATTACK_INFLUENCE_ENCODE(EG1ControllerAttackInfluence) |
2080 GIG_EG_CTR_DECAY_INFLUENCE_ENCODE(EG1ControllerDecayInfluence) |
2081 GIG_EG_CTR_RELEASE_INFLUENCE_ENCODE(EG1ControllerReleaseInfluence);
2082 pData[45] = eg1ctrloptions;
2083
2084 const uint8_t eg2ctl = (uint8_t) EncodeLeverageController(EG2Controller);
2085 pData[46] = eg2ctl;
2086
2087 const uint8_t eg2ctrloptions =
2088 (EG2ControllerInvert ? 0x01 : 0x00) |
2089 GIG_EG_CTR_ATTACK_INFLUENCE_ENCODE(EG2ControllerAttackInfluence) |
2090 GIG_EG_CTR_DECAY_INFLUENCE_ENCODE(EG2ControllerDecayInfluence) |
2091 GIG_EG_CTR_RELEASE_INFLUENCE_ENCODE(EG2ControllerReleaseInfluence);
2092 pData[47] = eg2ctrloptions;
2093
2094 const int32_t lfo1freq = (int32_t) GIG_EXP_ENCODE(LFO1Frequency);
2095 store32(&pData[48], lfo1freq);
2096
2097 const int32_t eg2attack = (int32_t) GIG_EXP_ENCODE(EG2Attack);
2098 store32(&pData[52], eg2attack);
2099
2100 const int32_t eg2decay1 = (int32_t) GIG_EXP_ENCODE(EG2Decay1);
2101 store32(&pData[56], eg2decay1);
2102
2103 // next 2 bytes unknown
2104
2105 store16(&pData[62], EG2Sustain);
2106
2107 const int32_t eg2release = (int32_t) GIG_EXP_ENCODE(EG2Release);
2108 store32(&pData[64], eg2release);
2109
2110 // next 2 bytes unknown
2111
2112 store16(&pData[70], LFO2ControlDepth);
2113
2114 const int32_t lfo2freq = (int32_t) GIG_EXP_ENCODE(LFO2Frequency);
2115 store32(&pData[72], lfo2freq);
2116
2117 // next 2 bytes unknown
2118
2119 store16(&pData[78], LFO2InternalDepth);
2120
2121 const int32_t eg1decay2 = (int32_t) (EG1InfiniteSustain) ? 0x7fffffff : (int32_t) GIG_EXP_ENCODE(EG1Decay2);
2122 store32(&pData[80], eg1decay2);
2123
2124 // next 2 bytes unknown
2125
2126 store16(&pData[86], EG1PreAttack);
2127
2128 const int32_t eg2decay2 = (int32_t) (EG2InfiniteSustain) ? 0x7fffffff : (int32_t) GIG_EXP_ENCODE(EG2Decay2);
2129 store32(&pData[88], eg2decay2);
2130
2131 // next 2 bytes unknown
2132
2133 store16(&pData[94], EG2PreAttack);
2134
2135 {
2136 if (VelocityResponseDepth > 4) throw Exception("VelocityResponseDepth must be between 0 and 4");
2137 uint8_t velocityresponse = VelocityResponseDepth;
2138 switch (VelocityResponseCurve) {
2139 case curve_type_nonlinear:
2140 break;
2141 case curve_type_linear:
2142 velocityresponse += 5;
2143 break;
2144 case curve_type_special:
2145 velocityresponse += 10;
2146 break;
2147 case curve_type_unknown:
2148 default:
2149 throw Exception("Could not update DimensionRegion's chunk, unknown VelocityResponseCurve selected");
2150 }
2151 pData[96] = velocityresponse;
2152 }
2153
2154 {
2155 if (ReleaseVelocityResponseDepth > 4) throw Exception("ReleaseVelocityResponseDepth must be between 0 and 4");
2156 uint8_t releasevelocityresponse = ReleaseVelocityResponseDepth;
2157 switch (ReleaseVelocityResponseCurve) {
2158 case curve_type_nonlinear:
2159 break;
2160 case curve_type_linear:
2161 releasevelocityresponse += 5;
2162 break;
2163 case curve_type_special:
2164 releasevelocityresponse += 10;
2165 break;
2166 case curve_type_unknown:
2167 default:
2168 throw Exception("Could not update DimensionRegion's chunk, unknown ReleaseVelocityResponseCurve selected");
2169 }
2170 pData[97] = releasevelocityresponse;
2171 }
2172
2173 pData[98] = VelocityResponseCurveScaling;
2174
2175 pData[99] = AttenuationControllerThreshold;
2176
2177 // next 4 bytes unknown
2178
2179 store16(&pData[104], SampleStartOffset);
2180
2181 // next 2 bytes unknown
2182
2183 {
2184 uint8_t pitchTrackDimensionBypass = GIG_PITCH_TRACK_ENCODE(PitchTrack);
2185 switch (DimensionBypass) {
2186 case dim_bypass_ctrl_94:
2187 pitchTrackDimensionBypass |= 0x10;
2188 break;
2189 case dim_bypass_ctrl_95:
2190 pitchTrackDimensionBypass |= 0x20;
2191 break;
2192 case dim_bypass_ctrl_none:
2193 //FIXME: should we set anything here?
2194 break;
2195 default:
2196 throw Exception("Could not update DimensionRegion's chunk, unknown DimensionBypass selected");
2197 }
2198 pData[108] = pitchTrackDimensionBypass;
2199 }
2200
2201 const uint8_t pan = (Pan >= 0) ? Pan : ((-Pan) + 63); // signed 8 bit -> signed 7 bit
2202 pData[109] = pan;
2203
2204 const uint8_t selfmask = (SelfMask) ? 0x01 : 0x00;
2205 pData[110] = selfmask;
2206
2207 // next byte unknown
2208
2209 {
2210 uint8_t lfo3ctrl = LFO3Controller & 0x07; // lower 3 bits
2211 if (LFO3Sync) lfo3ctrl |= 0x20; // bit 5
2212 if (InvertAttenuationController) lfo3ctrl |= 0x80; // bit 7
2213 if (VCFType == vcf_type_lowpassturbo) lfo3ctrl |= 0x40; // bit 6
2214 pData[112] = lfo3ctrl;
2215 }
2216
2217 const uint8_t attenctl = EncodeLeverageController(AttenuationController);
2218 pData[113] = attenctl;
2219
2220 {
2221 uint8_t lfo2ctrl = LFO2Controller & 0x07; // lower 3 bits
2222 if (LFO2FlipPhase) lfo2ctrl |= 0x80; // bit 7
2223 if (LFO2Sync) lfo2ctrl |= 0x20; // bit 5
2224 if (VCFResonanceController != vcf_res_ctrl_none) lfo2ctrl |= 0x40; // bit 6
2225 pData[114] = lfo2ctrl;
2226 }
2227
2228 {
2229 uint8_t lfo1ctrl = LFO1Controller & 0x07; // lower 3 bits
2230 if (LFO1FlipPhase) lfo1ctrl |= 0x80; // bit 7
2231 if (LFO1Sync) lfo1ctrl |= 0x40; // bit 6
2232 if (VCFResonanceController != vcf_res_ctrl_none)
2233 lfo1ctrl |= GIG_VCF_RESONANCE_CTRL_ENCODE(VCFResonanceController);
2234 pData[115] = lfo1ctrl;
2235 }
2236
2237 const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth
2238 : uint16_t(((-EG3Depth) - 1) ^ 0xfff); /* binary complementary for negatives */
2239 store16(&pData[116], eg3depth);
2240
2241 // next 2 bytes unknown
2242
2243 const uint8_t channeloffset = ChannelOffset * 4;
2244 pData[120] = channeloffset;
2245
2246 {
2247 uint8_t regoptions = 0;
2248 if (MSDecode) regoptions |= 0x01; // bit 0
2249 if (SustainDefeat) regoptions |= 0x02; // bit 1
2250 pData[121] = regoptions;
2251 }
2252
2253 // next 2 bytes unknown
2254
2255 pData[124] = VelocityUpperLimit;
2256
2257 // next 3 bytes unknown
2258
2259 pData[128] = ReleaseTriggerDecay;
2260
2261 // next 2 bytes unknown
2262
2263 const uint8_t eg1hold = (EG1Hold) ? 0x80 : 0x00; // bit 7
2264 pData[131] = eg1hold;
2265
2266 const uint8_t vcfcutoff = (VCFEnabled ? 0x80 : 0x00) | /* bit 7 */
2267 (VCFCutoff & 0x7f); /* lower 7 bits */
2268 pData[132] = vcfcutoff;
2269
2270 pData[133] = VCFCutoffController;
2271
2272 const uint8_t vcfvelscale = (VCFCutoffControllerInvert ? 0x80 : 0x00) | /* bit 7 */
2273 (VCFVelocityScale & 0x7f); /* lower 7 bits */
2274 pData[134] = vcfvelscale;
2275
2276 // next byte unknown
2277
2278 const uint8_t vcfresonance = (VCFResonanceDynamic ? 0x00 : 0x80) | /* bit 7 */
2279 (VCFResonance & 0x7f); /* lower 7 bits */
2280 pData[136] = vcfresonance;
2281
2282 const uint8_t vcfbreakpoint = (VCFKeyboardTracking ? 0x80 : 0x00) | /* bit 7 */
2283 (VCFKeyboardTrackingBreakpoint & 0x7f); /* lower 7 bits */
2284 pData[137] = vcfbreakpoint;
2285
2286 const uint8_t vcfvelocity = VCFVelocityDynamicRange % 5 +
2287 VCFVelocityCurve * 5;
2288 pData[138] = vcfvelocity;
2289
2290 const uint8_t vcftype = (VCFType == vcf_type_lowpassturbo) ? vcf_type_lowpass : VCFType;
2291 pData[139] = vcftype;
2292
2293 if (chunksize >= 148) {
2294 memcpy(&pData[140], DimensionUpperLimits, 8);
2295 }
2296
2297 // chunk for own format extensions, these will *NOT* work with
2298 // Gigasampler/GigaStudio !
2299 RIFF::Chunk* lsde = pParentList->GetSubChunk(CHUNK_ID_LSDE);
2300 const int lsdeSize =
2301 3 /* EG cancel options */ +
2302 1 /* sustain pedal up on release trigger option */ +
2303 8 /* LFOs' wave forms */ + 12 /* LFOs' phase */ + 4 /* flags (LFO3FlipPhase) */;
2304 if (!lsde && UsesAnyGigFormatExtension()) {
2305 // only add this "LSDE" chunk if there is some (format extension)
2306 // setting effective that would require our "LSDE" format extension
2307 // chunk to be stored
2308 lsde = pParentList->AddSubChunk(CHUNK_ID_LSDE, lsdeSize);
2309 // move LSDE chunk to the end of parent list
2310 pParentList->MoveSubChunk(lsde, (RIFF::Chunk*)NULL);
2311 }
2312 if (lsde) {
2313 if (lsde->GetNewSize() < lsdeSize)
2314 lsde->Resize(lsdeSize);
2315 // format extension for EG behavior options
2316 unsigned char* pData = (unsigned char*) lsde->LoadChunkData();
2317 eg_opt_t* pEGOpts[2] = { &EG1Options, &EG2Options };
2318 for (int i = 0; i < 2; ++i) { // NOTE: we reserved the 3rd byte for a potential future EG3 option
2319 pData[i] =
2320 (pEGOpts[i]->AttackCancel ? 1 : 0) |
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);
2325 }
2326 // format extension for release trigger options
2327 pData[3] = static_cast<uint8_t>(SustainReleaseTrigger) | (NoNoteOffReleaseTrigger ? (1<<7) : 0);
2328 // format extension for LFOs' wave form, phase displacement and for
2329 // LFO3's flip phase
2330 store16(&pData[4], LFO1WaveForm);
2331 store16(&pData[6], LFO2WaveForm);
2332 store16(&pData[8], LFO3WaveForm);
2333 //NOTE: 16 bits reserved here for potential future use !
2334 const int32_t lfo1Phase = (int32_t) GIG_EXP_ENCODE(LFO1Phase);
2335 const int32_t lfo2Phase = (int32_t) GIG_EXP_ENCODE(LFO2Phase);
2336 const int32_t lfo3Phase = (int32_t) GIG_EXP_ENCODE(LFO3Phase);
2337 store32(&pData[12], lfo1Phase);
2338 store32(&pData[16], lfo2Phase);
2339 store32(&pData[20], lfo3Phase);
2340 const int32_t flags = LFO3FlipPhase ? 1 : 0;
2341 store32(&pData[24], flags);
2342
2343 // compile time sanity check: is our last store access here
2344 // consistent with the initial lsdeSize value assignment?
2345 static_assert(lsdeSize == 28, "Inconsistency in assumed 'LSDE' RIFF chunk size");
2346 }
2347 }
2348
2349 /**
2350 * Returns @c true in case this DimensionRegion object uses any gig format
2351 * extension, that is whether this DimensionRegion object currently has any
2352 * setting effective that would require our "LSDE" RIFF chunk to be stored
2353 * to the gig file.
2354 *
2355 * Right now this is a private method. It is considerable though this method
2356 * to become (in slightly modified form) a public API method in future, i.e.
2357 * to allow instrument editors to visualize and/or warn the user of any
2358 * format extension being used. Right now this method really just serves to
2359 * answer the question whether an LSDE chunk is required, for the public API
2360 * purpose this method would also need to check whether any other setting
2361 * stored to the regular value '3ewa' chunk, is actually a format extension
2362 * as well.
2363 */
2364 bool DimensionRegion::UsesAnyGigFormatExtension() const {
2365 eg_opt_t defaultOpt;
2366 return memcmp(&EG1Options, &defaultOpt, sizeof(eg_opt_t)) ||
2367 memcmp(&EG2Options, &defaultOpt, sizeof(eg_opt_t)) ||
2368 SustainReleaseTrigger || NoNoteOffReleaseTrigger ||
2369 LFO1WaveForm || LFO2WaveForm || LFO3WaveForm ||
2370 LFO1Phase || LFO2Phase || LFO3Phase ||
2371 LFO3FlipPhase;
2372 }
2373
2374 double* DimensionRegion::GetReleaseVelocityTable(curve_type_t releaseVelocityResponseCurve, uint8_t releaseVelocityResponseDepth) {
2375 curve_type_t curveType = releaseVelocityResponseCurve;
2376 uint8_t depth = releaseVelocityResponseDepth;
2377 // this models a strange behaviour or bug in GSt: two of the
2378 // velocity response curves for release time are not used even
2379 // if specified, instead another curve is chosen.
2380 if ((curveType == curve_type_nonlinear && depth == 0) ||
2381 (curveType == curve_type_special && depth == 4)) {
2382 curveType = curve_type_nonlinear;
2383 depth = 3;
2384 }
2385 return GetVelocityTable(curveType, depth, 0);
2386 }
2387
2388 double* DimensionRegion::GetCutoffVelocityTable(curve_type_t vcfVelocityCurve,
2389 uint8_t vcfVelocityDynamicRange,
2390 uint8_t vcfVelocityScale,
2391 vcf_cutoff_ctrl_t vcfCutoffController)
2392 {
2393 curve_type_t curveType = vcfVelocityCurve;
2394 uint8_t depth = vcfVelocityDynamicRange;
2395 // even stranger GSt: two of the velocity response curves for
2396 // filter cutoff are not used, instead another special curve
2397 // is chosen. This curve is not used anywhere else.
2398 if ((curveType == curve_type_nonlinear && depth == 0) ||
2399 (curveType == curve_type_special && depth == 4)) {
2400 curveType = curve_type_special;
2401 depth = 5;
2402 }
2403 return GetVelocityTable(curveType, depth,
2404 (vcfCutoffController <= vcf_cutoff_ctrl_none2)
2405 ? vcfVelocityScale : 0);
2406 }
2407
2408 // get the corresponding velocity table from the table map or create & calculate that table if it doesn't exist yet
2409 double* DimensionRegion::GetVelocityTable(curve_type_t curveType, uint8_t depth, uint8_t scaling)
2410 {
2411 // sanity check input parameters
2412 // (fallback to some default parameters on ill input)
2413 switch (curveType) {
2414 case curve_type_nonlinear:
2415 case curve_type_linear:
2416 if (depth > 4) {
2417 printf("Warning: Invalid depth (0x%x) for velocity curve type (0x%x).\n", depth, curveType);
2418 depth = 0;
2419 scaling = 0;
2420 }
2421 break;
2422 case curve_type_special:
2423 if (depth > 5) {
2424 printf("Warning: Invalid depth (0x%x) for velocity curve type 'special'.\n", depth);
2425 depth = 0;
2426 scaling = 0;
2427 }
2428 break;
2429 case curve_type_unknown:
2430 default:
2431 printf("Warning: Unknown velocity curve type (0x%x).\n", curveType);
2432 curveType = curve_type_linear;
2433 depth = 0;
2434 scaling = 0;
2435 break;
2436 }
2437
2438 double* table;
2439 uint32_t tableKey = (curveType<<16) | (depth<<8) | scaling;
2440 if (pVelocityTables->count(tableKey)) { // if key exists
2441 table = (*pVelocityTables)[tableKey];
2442 }
2443 else {
2444 table = CreateVelocityTable(curveType, depth, scaling);
2445 (*pVelocityTables)[tableKey] = table; // put the new table into the tables map
2446 }
2447 return table;
2448 }
2449
2450 Region* DimensionRegion::GetParent() const {
2451 return pRegion;
2452 }
2453
2454 // show error if some _lev_ctrl_* enum entry is not listed in the following function
2455 // (commented out for now, because "diagnostic push" not supported prior GCC 4.6)
2456 // TODO: uncomment and add a GCC version check (see also commented "#pragma GCC diagnostic pop" below)
2457 //#pragma GCC diagnostic push
2458 //#pragma GCC diagnostic error "-Wswitch"
2459
2460 leverage_ctrl_t DimensionRegion::DecodeLeverageController(_lev_ctrl_t EncodedController) {
2461 leverage_ctrl_t decodedcontroller;
2462 switch (EncodedController) {
2463 // special controller
2464 case _lev_ctrl_none:
2465 decodedcontroller.type = leverage_ctrl_t::type_none;
2466 decodedcontroller.controller_number = 0;
2467 break;
2468 case _lev_ctrl_velocity:
2469 decodedcontroller.type = leverage_ctrl_t::type_velocity;
2470 decodedcontroller.controller_number = 0;
2471 break;
2472 case _lev_ctrl_channelaftertouch:
2473 decodedcontroller.type = leverage_ctrl_t::type_channelaftertouch;
2474 decodedcontroller.controller_number = 0;
2475 break;
2476
2477 // ordinary MIDI control change controller
2478 case _lev_ctrl_modwheel:
2479 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2480 decodedcontroller.controller_number = 1;
2481 break;
2482 case _lev_ctrl_breath:
2483 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2484 decodedcontroller.controller_number = 2;
2485 break;
2486 case _lev_ctrl_foot:
2487 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2488 decodedcontroller.controller_number = 4;
2489 break;
2490 case _lev_ctrl_effect1:
2491 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2492 decodedcontroller.controller_number = 12;
2493 break;
2494 case _lev_ctrl_effect2:
2495 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2496 decodedcontroller.controller_number = 13;
2497 break;
2498 case _lev_ctrl_genpurpose1:
2499 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2500 decodedcontroller.controller_number = 16;
2501 break;
2502 case _lev_ctrl_genpurpose2:
2503 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2504 decodedcontroller.controller_number = 17;
2505 break;
2506 case _lev_ctrl_genpurpose3:
2507 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2508 decodedcontroller.controller_number = 18;
2509 break;
2510 case _lev_ctrl_genpurpose4:
2511 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2512 decodedcontroller.controller_number = 19;
2513 break;
2514 case _lev_ctrl_portamentotime:
2515 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2516 decodedcontroller.controller_number = 5;
2517 break;
2518 case _lev_ctrl_sustainpedal:
2519 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2520 decodedcontroller.controller_number = 64;
2521 break;
2522 case _lev_ctrl_portamento:
2523 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2524 decodedcontroller.controller_number = 65;
2525 break;
2526 case _lev_ctrl_sostenutopedal:
2527 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2528 decodedcontroller.controller_number = 66;
2529 break;
2530 case _lev_ctrl_softpedal:
2531 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2532 decodedcontroller.controller_number = 67;
2533 break;
2534 case _lev_ctrl_genpurpose5:
2535 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2536 decodedcontroller.controller_number = 80;
2537 break;
2538 case _lev_ctrl_genpurpose6:
2539 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2540 decodedcontroller.controller_number = 81;
2541 break;
2542 case _lev_ctrl_genpurpose7:
2543 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2544 decodedcontroller.controller_number = 82;
2545 break;
2546 case _lev_ctrl_genpurpose8:
2547 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2548 decodedcontroller.controller_number = 83;
2549 break;
2550 case _lev_ctrl_effect1depth:
2551 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2552 decodedcontroller.controller_number = 91;
2553 break;
2554 case _lev_ctrl_effect2depth:
2555 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2556 decodedcontroller.controller_number = 92;
2557 break;
2558 case _lev_ctrl_effect3depth:
2559 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2560 decodedcontroller.controller_number = 93;
2561 break;
2562 case _lev_ctrl_effect4depth:
2563 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2564 decodedcontroller.controller_number = 94;
2565 break;
2566 case _lev_ctrl_effect5depth:
2567 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2568 decodedcontroller.controller_number = 95;
2569 break;
2570
2571 // format extension (these controllers are so far only supported by
2572 // LinuxSampler & gigedit) they will *NOT* work with
2573 // Gigasampler/GigaStudio !
2574 case _lev_ctrl_CC3_EXT:
2575 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2576 decodedcontroller.controller_number = 3;
2577 break;
2578 case _lev_ctrl_CC6_EXT:
2579 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2580 decodedcontroller.controller_number = 6;
2581 break;
2582 case _lev_ctrl_CC7_EXT:
2583 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2584 decodedcontroller.controller_number = 7;
2585 break;
2586 case _lev_ctrl_CC8_EXT:
2587 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2588 decodedcontroller.controller_number = 8;
2589 break;
2590 case _lev_ctrl_CC9_EXT:
2591 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2592 decodedcontroller.controller_number = 9;
2593 break;
2594 case _lev_ctrl_CC10_EXT:
2595 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2596 decodedcontroller.controller_number = 10;
2597 break;
2598 case _lev_ctrl_CC11_EXT:
2599 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2600 decodedcontroller.controller_number = 11;
2601 break;
2602 case _lev_ctrl_CC14_EXT:
2603 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2604 decodedcontroller.controller_number = 14;
2605 break;
2606 case _lev_ctrl_CC15_EXT:
2607 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2608 decodedcontroller.controller_number = 15;
2609 break;
2610 case _lev_ctrl_CC20_EXT:
2611 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2612 decodedcontroller.controller_number = 20;
2613 break;
2614 case _lev_ctrl_CC21_EXT:
2615 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2616 decodedcontroller.controller_number = 21;
2617 break;
2618 case _lev_ctrl_CC22_EXT:
2619 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2620 decodedcontroller.controller_number = 22;
2621 break;
2622 case _lev_ctrl_CC23_EXT:
2623 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2624 decodedcontroller.controller_number = 23;
2625 break;
2626 case _lev_ctrl_CC24_EXT:
2627 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2628 decodedcontroller.controller_number = 24;
2629 break;
2630 case _lev_ctrl_CC25_EXT:
2631 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2632 decodedcontroller.controller_number = 25;
2633 break;
2634 case _lev_ctrl_CC26_EXT:
2635 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2636 decodedcontroller.controller_number = 26;
2637 break;
2638 case _lev_ctrl_CC27_EXT:
2639 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2640 decodedcontroller.controller_number = 27;
2641 break;
2642 case _lev_ctrl_CC28_EXT:
2643 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2644 decodedcontroller.controller_number = 28;
2645 break;
2646 case _lev_ctrl_CC29_EXT:
2647 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2648 decodedcontroller.controller_number = 29;
2649 break;
2650 case _lev_ctrl_CC30_EXT:
2651 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2652 decodedcontroller.controller_number = 30;
2653 break;
2654 case _lev_ctrl_CC31_EXT:
2655 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2656 decodedcontroller.controller_number = 31;
2657 break;
2658 case _lev_ctrl_CC68_EXT:
2659 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2660 decodedcontroller.controller_number = 68;
2661 break;
2662 case _lev_ctrl_CC69_EXT:
2663 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2664 decodedcontroller.controller_number = 69;
2665 break;
2666 case _lev_ctrl_CC70_EXT:
2667 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2668 decodedcontroller.controller_number = 70;
2669 break;
2670 case _lev_ctrl_CC71_EXT:
2671 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2672 decodedcontroller.controller_number = 71;
2673 break;
2674 case _lev_ctrl_CC72_EXT:
2675 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2676 decodedcontroller.controller_number = 72;
2677 break;
2678 case _lev_ctrl_CC73_EXT:
2679 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2680 decodedcontroller.controller_number = 73;
2681 break;
2682 case _lev_ctrl_CC74_EXT:
2683 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2684 decodedcontroller.controller_number = 74;
2685 break;
2686 case _lev_ctrl_CC75_EXT:
2687 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2688 decodedcontroller.controller_number = 75;
2689 break;
2690 case _lev_ctrl_CC76_EXT:
2691 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2692 decodedcontroller.controller_number = 76;
2693 break;
2694 case _lev_ctrl_CC77_EXT:
2695 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2696 decodedcontroller.controller_number = 77;
2697 break;
2698 case _lev_ctrl_CC78_EXT:
2699 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2700 decodedcontroller.controller_number = 78;
2701 break;
2702 case _lev_ctrl_CC79_EXT:
2703 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2704 decodedcontroller.controller_number = 79;
2705 break;
2706 case _lev_ctrl_CC84_EXT:
2707 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2708 decodedcontroller.controller_number = 84;
2709 break;
2710 case _lev_ctrl_CC85_EXT:
2711 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2712 decodedcontroller.controller_number = 85;
2713 break;
2714 case _lev_ctrl_CC86_EXT:
2715 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2716 decodedcontroller.controller_number = 86;
2717 break;
2718 case _lev_ctrl_CC87_EXT:
2719 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2720 decodedcontroller.controller_number = 87;
2721 break;
2722 case _lev_ctrl_CC89_EXT:
2723 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2724 decodedcontroller.controller_number = 89;
2725 break;
2726 case _lev_ctrl_CC90_EXT:
2727 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2728 decodedcontroller.controller_number = 90;
2729 break;
2730 case _lev_ctrl_CC96_EXT:
2731 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2732 decodedcontroller.controller_number = 96;
2733 break;
2734 case _lev_ctrl_CC97_EXT:
2735 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2736 decodedcontroller.controller_number = 97;
2737 break;
2738 case _lev_ctrl_CC102_EXT:
2739 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2740 decodedcontroller.controller_number = 102;
2741 break;
2742 case _lev_ctrl_CC103_EXT:
2743 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2744 decodedcontroller.controller_number = 103;
2745 break;
2746 case _lev_ctrl_CC104_EXT:
2747 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2748 decodedcontroller.controller_number = 104;
2749 break;
2750 case _lev_ctrl_CC105_EXT:
2751 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2752 decodedcontroller.controller_number = 105;
2753 break;
2754 case _lev_ctrl_CC106_EXT:
2755 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2756 decodedcontroller.controller_number = 106;
2757 break;
2758 case _lev_ctrl_CC107_EXT:
2759 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2760 decodedcontroller.controller_number = 107;
2761 break;
2762 case _lev_ctrl_CC108_EXT:
2763 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2764 decodedcontroller.controller_number = 108;
2765 break;
2766 case _lev_ctrl_CC109_EXT:
2767 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2768 decodedcontroller.controller_number = 109;
2769 break;
2770 case _lev_ctrl_CC110_EXT:
2771 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2772 decodedcontroller.controller_number = 110;
2773 break;
2774 case _lev_ctrl_CC111_EXT:
2775 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2776 decodedcontroller.controller_number = 111;
2777 break;
2778 case _lev_ctrl_CC112_EXT:
2779 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2780 decodedcontroller.controller_number = 112;
2781 break;
2782 case _lev_ctrl_CC113_EXT:
2783 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2784 decodedcontroller.controller_number = 113;
2785 break;
2786 case _lev_ctrl_CC114_EXT:
2787 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2788 decodedcontroller.controller_number = 114;
2789 break;
2790 case _lev_ctrl_CC115_EXT:
2791 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2792 decodedcontroller.controller_number = 115;
2793 break;
2794 case _lev_ctrl_CC116_EXT:
2795 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2796 decodedcontroller.controller_number = 116;
2797 break;
2798 case _lev_ctrl_CC117_EXT:
2799 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2800 decodedcontroller.controller_number = 117;
2801 break;
2802 case _lev_ctrl_CC118_EXT:
2803 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2804 decodedcontroller.controller_number = 118;
2805 break;
2806 case _lev_ctrl_CC119_EXT:
2807 decodedcontroller.type = leverage_ctrl_t::type_controlchange;
2808 decodedcontroller.controller_number = 119;
2809 break;
2810
2811 // unknown controller type
2812 default:
2813 decodedcontroller.type = leverage_ctrl_t::type_none;
2814 decodedcontroller.controller_number = 0;
2815 printf("Warning: Unknown leverage controller type (0x%x).\n", EncodedController);
2816 break;
2817 }
2818 return decodedcontroller;
2819 }
2820
2821 // see above (diagnostic push not supported prior GCC 4.6)
2822 //#pragma GCC diagnostic pop
2823
2824 DimensionRegion::_lev_ctrl_t DimensionRegion::EncodeLeverageController(leverage_ctrl_t DecodedController) {
2825 _lev_ctrl_t encodedcontroller;
2826 switch (DecodedController.type) {
2827 // special controller
2828 case leverage_ctrl_t::type_none:
2829 encodedcontroller = _lev_ctrl_none;
2830 break;
2831 case leverage_ctrl_t::type_velocity:
2832 encodedcontroller = _lev_ctrl_velocity;
2833 break;
2834 case leverage_ctrl_t::type_channelaftertouch:
2835 encodedcontroller = _lev_ctrl_channelaftertouch;
2836 break;
2837
2838 // ordinary MIDI control change controller
2839 case leverage_ctrl_t::type_controlchange:
2840 switch (DecodedController.controller_number) {
2841 case 1:
2842 encodedcontroller = _lev_ctrl_modwheel;
2843 break;
2844 case 2:
2845 encodedcontroller = _lev_ctrl_breath;
2846 break;
2847 case 4:
2848 encodedcontroller = _lev_ctrl_foot;
2849 break;
2850 case 12:
2851 encodedcontroller = _lev_ctrl_effect1;
2852 break;
2853 case 13:
2854 encodedcontroller = _lev_ctrl_effect2;
2855 break;
2856 case 16:
2857 encodedcontroller = _lev_ctrl_genpurpose1;
2858 break;
2859 case 17:
2860 encodedcontroller = _lev_ctrl_genpurpose2;
2861 break;
2862 case 18:
2863 encodedcontroller = _lev_ctrl_genpurpose3;
2864 break;
2865 case 19:
2866 encodedcontroller = _lev_ctrl_genpurpose4;
2867 break;
2868 case 5:
2869 encodedcontroller = _lev_ctrl_portamentotime;
2870 break;
2871 case 64:
2872 encodedcontroller = _lev_ctrl_sustainpedal;
2873 break;
2874 case 65:
2875 encodedcontroller = _lev_ctrl_portamento;
2876 break;
2877 case 66:
2878 encodedcontroller = _lev_ctrl_sostenutopedal;
2879 break;
2880 case 67:
2881 encodedcontroller = _lev_ctrl_softpedal;
2882 break;
2883 case 80:
2884 encodedcontroller = _lev_ctrl_genpurpose5;
2885 break;
2886 case 81:
2887 encodedcontroller = _lev_ctrl_genpurpose6;
2888 break;
2889 case 82:
2890 encodedcontroller = _lev_ctrl_genpurpose7;
2891 break;
2892 case 83:
2893 encodedcontroller = _lev_ctrl_genpurpose8;
2894 break;
2895 case 91:
2896 encodedcontroller = _lev_ctrl_effect1depth;
2897 break;
2898 case 92:
2899 encodedcontroller = _lev_ctrl_effect2depth;
2900 break;
2901 case 93:
2902 encodedcontroller = _lev_ctrl_effect3depth;
2903 break;
2904 case 94:
2905 encodedcontroller = _lev_ctrl_effect4depth;
2906 break;
2907 case 95:
2908 encodedcontroller = _lev_ctrl_effect5depth;
2909 break;
2910
2911 // format extension (these controllers are so far only
2912 // supported by LinuxSampler & gigedit) they will *NOT*
2913 // work with Gigasampler/GigaStudio !
2914 case 3:
2915 encodedcontroller = _lev_ctrl_CC3_EXT;
2916 break;
2917 case 6:
2918 encodedcontroller = _lev_ctrl_CC6_EXT;
2919 break;
2920 case 7:
2921 encodedcontroller = _lev_ctrl_CC7_EXT;
2922 break;
2923 case 8:
2924 encodedcontroller = _lev_ctrl_CC8_EXT;
2925 break;
2926 case 9:
2927 encodedcontroller = _lev_ctrl_CC9_EXT;
2928 break;
2929 case 10:
2930 encodedcontroller = _lev_ctrl_CC10_EXT;
2931 break;
2932 case 11:
2933 encodedcontroller = _lev_ctrl_CC11_EXT;
2934 break;
2935 case 14:
2936 encodedcontroller = _lev_ctrl_CC14_EXT;
2937 break;
2938 case 15:
2939 encodedcontroller = _lev_ctrl_CC15_EXT;
2940 break;
2941 case 20:
2942 encodedcontroller = _lev_ctrl_CC20_EXT;
2943 break;
2944 case 21:
2945 encodedcontroller = _lev_ctrl_CC21_EXT;
2946 break;
2947 case 22:
2948 encodedcontroller = _lev_ctrl_CC22_EXT;
2949 break;
2950 case 23:
2951 encodedcontroller = _lev_ctrl_CC23_EXT;
2952 break;
2953 case 24:
2954 encodedcontroller = _lev_ctrl_CC24_EXT;
2955 break;
2956 case 25:
2957 encodedcontroller = _lev_ctrl_CC25_EXT;
2958 break;
2959 case 26:
2960 encodedcontroller = _lev_ctrl_CC26_EXT;
2961 break;
2962 case 27:
2963 encodedcontroller = _lev_ctrl_CC27_EXT;
2964 break;
2965 case 28:
2966 encodedcontroller = _lev_ctrl_CC28_EXT;
2967 break;
2968 case 29:
2969 encodedcontroller = _lev_ctrl_CC29_EXT;
2970 break;
2971 case 30:
2972 encodedcontroller = _lev_ctrl_CC30_EXT;
2973 break;
2974 case 31:
2975 encodedcontroller = _lev_ctrl_CC31_EXT;
2976 break;
2977 case 68:
2978 encodedcontroller = _lev_ctrl_CC68_EXT;
2979 break;
2980 case 69:
2981 encodedcontroller = _lev_ctrl_CC69_EXT;
2982 break;
2983 case 70:
2984 encodedcontroller = _lev_ctrl_CC70_EXT;
2985 break;
2986 case 71:
2987 encodedcontroller = _lev_ctrl_CC71_EXT;
2988 break;
2989 case 72:
2990 encodedcontroller = _lev_ctrl_CC72_EXT;
2991 break;
2992 case 73:
2993 encodedcontroller = _lev_ctrl_CC73_EXT;
2994 break;
2995 case 74:
2996 encodedcontroller = _lev_ctrl_CC74_EXT;
2997 break;
2998 case 75:
2999 encodedcontroller = _lev_ctrl_CC75_EXT;
3000 break;
3001 case 76:
3002 encodedcontroller = _lev_ctrl_CC76_EXT;
3003 break;
3004 case 77:
3005 encodedcontroller = _lev_ctrl_CC77_EXT;
3006 break;
3007 case 78:
3008 encodedcontroller = _lev_ctrl_CC78_EXT;
3009 break;
3010 case 79:
3011 encodedcontroller = _lev_ctrl_CC79_EXT;
3012 break;
3013 case 84:
3014 encodedcontroller = _lev_ctrl_CC84_EXT;
3015 break;
3016 case 85:
3017 encodedcontroller = _lev_ctrl_CC85_EXT;
3018 break;
3019 case 86:
3020 encodedcontroller = _lev_ctrl_CC86_EXT;
3021 break;
3022 case 87:
3023 encodedcontroller = _lev_ctrl_CC87_EXT;
3024 break;
3025 case 89:
3026 encodedcontroller = _lev_ctrl_CC89_EXT;
3027 break;
3028 case 90:
3029 encodedcontroller = _lev_ctrl_CC90_EXT;
3030 break;
3031 case 96:
3032 encodedcontroller = _lev_ctrl_CC96_EXT;
3033 break;
3034 case 97:
3035 encodedcontroller = _lev_ctrl_CC97_EXT;
3036 break;
3037 case 102:
3038 encodedcontroller = _lev_ctrl_CC102_EXT;
3039 break;
3040 case 103:
3041 encodedcontroller = _lev_ctrl_CC103_EXT;
3042 break;
3043 case 104:
3044 encodedcontroller = _lev_ctrl_CC104_EXT;
3045 break;
3046 case 105:
3047 encodedcontroller = _lev_ctrl_CC105_EXT;
3048 break;
3049 case 106:
3050 encodedcontroller = _lev_ctrl_CC106_EXT;
3051 break;
3052 case 107:
3053 encodedcontroller = _lev_ctrl_CC107_EXT;
3054 break;
3055 case 108:
3056 encodedcontroller = _lev_ctrl_CC108_EXT;
3057 break;
3058 case 109:
3059 encodedcontroller = _lev_ctrl_CC109_EXT;
3060 break;
3061 case 110:
3062 encodedcontroller = _lev_ctrl_CC110_EXT;
3063 break;
3064 case 111:
3065 encodedcontroller = _lev_ctrl_CC111_EXT;
3066 break;
3067 case 112:
3068 encodedcontroller = _lev_ctrl_CC112_EXT;
3069 break;
3070 case 113:
3071 encodedcontroller = _lev_ctrl_CC113_EXT;
3072 break;
3073 case 114:
3074 encodedcontroller = _lev_ctrl_CC114_EXT;
3075 break;
3076 case 115:
3077 encodedcontroller = _lev_ctrl_CC115_EXT;
3078 break;
3079 case 116:
3080 encodedcontroller = _lev_ctrl_CC116_EXT;
3081 break;
3082 case 117:
3083 encodedcontroller = _lev_ctrl_CC117_EXT;
3084 break;
3085 case 118:
3086 encodedcontroller = _lev_ctrl_CC118_EXT;
3087 break;
3088 case 119:
3089 encodedcontroller = _lev_ctrl_CC119_EXT;
3090 break;
3091
3092 default:
3093 throw gig::Exception("leverage controller number is not supported by the gig format");
3094 }
3095 break;
3096 default:
3097 throw gig::Exception("Unknown leverage controller type.");
3098 }
3099 return encodedcontroller;
3100 }
3101
3102 DimensionRegion::~DimensionRegion() {
3103 Instances--;
3104 if (!Instances) {
3105 // delete the velocity->volume tables
3106 VelocityTableMap::iterator iter;
3107 for (iter = pVelocityTables->begin(); iter != pVelocityTables->end(); iter++) {
3108 double* pTable = iter->second;
3109 if (pTable) delete[] pTable;
3110 }
3111 pVelocityTables->clear();
3112 delete pVelocityTables;
3113 pVelocityTables = NULL;
3114 }
3115 if (VelocityTable) delete[] VelocityTable;
3116 }
3117
3118 /**
3119 * Returns the correct amplitude factor for the given \a MIDIKeyVelocity.
3120 * All involved parameters (VelocityResponseCurve, VelocityResponseDepth
3121 * and VelocityResponseCurveScaling) involved are taken into account to
3122 * calculate the amplitude factor. Use this method when a key was
3123 * triggered to get the volume with which the sample should be played
3124 * back.
3125 *
3126 * @param MIDIKeyVelocity MIDI velocity value of the triggered key (between 0 and 127)
3127 * @returns amplitude factor (between 0.0 and 1.0)
3128 */
3129 double DimensionRegion::GetVelocityAttenuation(uint8_t MIDIKeyVelocity) {
3130 return pVelocityAttenuationTable[MIDIKeyVelocity];
3131 }
3132
3133 double DimensionRegion::GetVelocityRelease(uint8_t MIDIKeyVelocity) {
3134 return pVelocityReleaseTable[MIDIKeyVelocity];
3135 }
3136
3137 double DimensionRegion::GetVelocityCutoff(uint8_t MIDIKeyVelocity) {
3138 return pVelocityCutoffTable[MIDIKeyVelocity];
3139 }
3140
3141 /**
3142 * Updates the respective member variable and the lookup table / cache
3143 * that depends on this value.
3144 */
3145 void DimensionRegion::SetVelocityResponseCurve(curve_type_t curve) {
3146 pVelocityAttenuationTable =
3147 GetVelocityTable(
3148 curve, VelocityResponseDepth, VelocityResponseCurveScaling
3149 );
3150 VelocityResponseCurve = curve;
3151 }
3152
3153 /**
3154 * Updates the respective member variable and the lookup table / cache
3155 * that depends on this value.
3156 */
3157 void DimensionRegion::SetVelocityResponseDepth(uint8_t depth) {
3158 pVelocityAttenuationTable =
3159 GetVelocityTable(
3160 VelocityResponseCurve, depth, VelocityResponseCurveScaling
3161 );
3162 VelocityResponseDepth = depth;
3163 }
3164
3165 /**
3166 * Updates the respective member variable and the lookup table / cache
3167 * that depends on this value.
3168 */
3169 void DimensionRegion::SetVelocityResponseCurveScaling(uint8_t scaling) {
3170 pVelocityAttenuationTable =
3171 GetVelocityTable(
3172 VelocityResponseCurve, VelocityResponseDepth, scaling
3173 );
3174 VelocityResponseCurveScaling = scaling;
3175 }
3176
3177 /**
3178 * Updates the respective member variable and the lookup table / cache
3179 * that depends on this value.
3180 */
3181 void DimensionRegion::SetReleaseVelocityResponseCurve(curve_type_t curve) {
3182 pVelocityReleaseTable = GetReleaseVelocityTable(curve, ReleaseVelocityResponseDepth);
3183 ReleaseVelocityResponseCurve = curve;
3184 }
3185
3186 /**
3187 * Updates the respective member variable and the lookup table / cache
3188 * that depends on this value.
3189 */
3190 void DimensionRegion::SetReleaseVelocityResponseDepth(uint8_t depth) {
3191 pVelocityReleaseTable = GetReleaseVelocityTable(ReleaseVelocityResponseCurve, depth);
3192 ReleaseVelocityResponseDepth = depth;
3193 }
3194
3195 /**
3196 * Updates the respective member variable and the lookup table / cache
3197 * that depends on this value.
3198 */
3199 void DimensionRegion::SetVCFCutoffController(vcf_cutoff_ctrl_t controller) {
3200 pVelocityCutoffTable = GetCutoffVelocityTable(VCFVelocityCurve, VCFVelocityDynamicRange, VCFVelocityScale, controller);
3201 VCFCutoffController = controller;
3202 }
3203
3204 /**
3205 * Updates the respective member variable and the lookup table / cache
3206 * that depends on this value.
3207 */
3208 void DimensionRegion::SetVCFVelocityCurve(curve_type_t curve) {
3209 pVelocityCutoffTable = GetCutoffVelocityTable(curve, VCFVelocityDynamicRange, VCFVelocityScale, VCFCutoffController);
3210 VCFVelocityCurve = curve;
3211 }
3212
3213 /**
3214 * Updates the respective member variable and the lookup table / cache
3215 * that depends on this value.
3216 */
3217 void DimensionRegion::SetVCFVelocityDynamicRange(uint8_t range) {
3218 pVelocityCutoffTable = GetCutoffVelocityTable(VCFVelocityCurve, range, VCFVelocityScale, VCFCutoffController);
3219 VCFVelocityDynamicRange = range;
3220 }
3221
3222 /**
3223 * Updates the respective member variable and the lookup table / cache
3224 * that depends on this value.
3225 */
3226 void DimensionRegion::SetVCFVelocityScale(uint8_t scaling) {
3227 pVelocityCutoffTable = GetCutoffVelocityTable(VCFVelocityCurve, VCFVelocityDynamicRange, scaling, VCFCutoffController);
3228 VCFVelocityScale = scaling;
3229 }
3230
3231 double* DimensionRegion::CreateVelocityTable(curve_type_t curveType, uint8_t depth, uint8_t scaling) {
3232
3233 // line-segment approximations of the 15 velocity curves
3234
3235 // linear
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 };
3241
3242 // non-linear
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,
3245 127, 127 };
3246 const int non2[] = { 1, 4, 46, 9, 57, 20, 102, 107, 107, 127,
3247 127, 127 };
3248 const int non3[] = { 1, 15, 10, 19, 67, 73, 80, 80, 90, 98, 98, 127,
3249 127, 127 };
3250 const int non4[] = { 1, 25, 33, 57, 82, 81, 92, 127, 127, 127 };
3251
3252 // special
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,
3262 127, 127 };
3263
3264 // this is only used by the VCF velocity curve
3265 const int spe5[] = { 1, 2, 30, 5, 60, 19, 77, 70, 83, 85, 88, 106,
3266 91, 127, 127, 127 };
3267
3268 const int* const curves[] = { non0, non1, non2, non3, non4,
3269 lin0, lin1, lin2, lin3, lin4,
3270 spe0, spe1, spe2, spe3, spe4, spe5 };
3271
3272 double* const table = new double[128];
3273
3274 const int* curve = curves[curveType * 5 + depth];
3275 const int s = scaling == 0 ? 20 : scaling; // 0 or 20 means no scaling
3276
3277 table[0] = 0;
3278 for (int x = 1 ; x < 128 ; x++) {
3279
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]));
3283 y = y / 127;
3284
3285 // Scale up for s > 20, down for s < 20. When
3286 // down-scaling, the curve still ends at 1.0.
3287 if (s < 20 && y >= 0.5)
3288 y = y / ((2 - 40.0 / s) * y + 40.0 / s - 1);
3289 else
3290 y = y * (s / 20.0);
3291 if (y > 1) y = 1;
3292
3293 table[x] = y;
3294 }
3295 return table;
3296 }
3297
3298
3299 // *************** Region ***************
3300 // *
3301
3302 Region::Region(Instrument* pInstrument, RIFF::List* rgnList) : DLS::Region((DLS::Instrument*) pInstrument, rgnList) {
3303 // Initialization
3304 Dimensions = 0;
3305 for (int i = 0; i < 256; i++) {
3306 pDimensionRegions[i] = NULL;
3307 }
3308 Layers = 1;
3309 File* file = (File*) GetParent()->GetParent();
3310 int dimensionBits = (file->pVersion && file->pVersion->major > 2) ? 8 : 5;
3311
3312 // Actual Loading
3313
3314 if (!file->GetAutoLoad()) return;
3315
3316 LoadDimensionRegions(rgnList);
3317
3318 RIFF::Chunk* _3lnk = rgnList->GetSubChunk(CHUNK_ID_3LNK);
3319 if (_3lnk) {
3320 _3lnk->SetPos(0);
3321
3322 DimensionRegions = _3lnk->ReadUint32();
3323 for (int i = 0; i < dimensionBits; i++) {
3324 dimension_t dimension = static_cast<dimension_t>(_3lnk->ReadUint8());
3325 uint8_t bits = _3lnk->ReadUint8();
3326 _3lnk->ReadUint8(); // bit position of the dimension (bits[0] + bits[1] + ... + bits[i-1])
3327 _3lnk->ReadUint8(); // (1 << bit position of next dimension) - (1 << bit position of this dimension)
3328 uint8_t zones = _3lnk->ReadUint8(); // new for v3: number of zones doesn't have to be == pow(2,bits)
3329 if (dimension == dimension_none) { // inactive dimension
3330 pDimensionDefinitions[i].dimension = dimension_none;
3331 pDimensionDefinitions[i].bits = 0;
3332 pDimensionDefinitions[i].zones = 0;
3333 pDimensionDefinitions[i].split_type = split_type_bit;
3334 pDimensionDefinitions[i].zone_size = 0;
3335 }
3336 else { // active dimension
3337 pDimensionDefinitions[i].dimension = dimension;
3338 pDimensionDefinitions[i].bits = bits;
3339 pDimensionDefinitions[i].zones = zones ? zones : 0x01 << bits; // = pow(2,bits)
3340 pDimensionDefinitions[i].split_type = __resolveSplitType(dimension);
3341 pDimensionDefinitions[i].zone_size = __resolveZoneSize(pDimensionDefinitions[i]);
3342 Dimensions++;
3343
3344 // if this is a layer dimension, remember the amount of layers
3345 if (dimension == dimension_layer) Layers = pDimensionDefinitions[i].zones;
3346 }
3347 _3lnk->SetPos(3, RIFF::stream_curpos); // jump forward to next dimension definition
3348 }
3349 for (int i = dimensionBits ; i < 8 ; i++) pDimensionDefinitions[i].bits = 0;
3350
3351 // if there's a velocity dimension and custom velocity zone splits are used,
3352 // update the VelocityTables in the dimension regions
3353 UpdateVelocityTable();
3354
3355 // jump to start of the wave pool indices (if not already there)
3356 if (file->pVersion && file->pVersion->major > 2)
3357 _3lnk->SetPos(68); // version 3 has a different 3lnk structure
3358 else
3359 _3lnk->SetPos(44);
3360
3361 // load sample references (if auto loading is enabled)
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);
3367 }
3368 GetSample(); // load global region sample reference
3369 }
3370 } else {
3371 DimensionRegions = 0;
3372 for (int i = 0 ; i < 8 ; i++) {
3373 pDimensionDefinitions[i].dimension = dimension_none;
3374 pDimensionDefinitions[i].bits = 0;
3375 pDimensionDefinitions[i].zones = 0;
3376 }
3377 }
3378
3379 // make sure there is at least one dimension region
3380 if (!DimensionRegions) {
3381 RIFF::List* _3prg = rgnList->GetSubList(LIST_TYPE_3PRG);
3382 if (!_3prg) _3prg = rgnList->AddSubList(LIST_TYPE_3PRG);
3383 RIFF::List* _3ewl = _3prg->AddSubList(LIST_TYPE_3EWL);
3384 pDimensionRegions[0] = new DimensionRegion(this, _3ewl);
3385 DimensionRegions = 1;
3386 }
3387 }
3388
3389 /**
3390 * Apply Region settings and all its DimensionRegions to the respective
3391 * RIFF chunks. You have to call File::Save() to make changes persistent.
3392 *
3393 * Usually there is absolutely no need to call this method explicitly.
3394 * It will be called automatically when File::Save() was called.
3395 *
3396 * @param pProgress - callback function for progress notification
3397 * @throws gig::Exception if samples cannot be dereferenced
3398 */
3399 void Region::UpdateChunks(progress_t* pProgress) {
3400 // in the gig format we don't care about the Region's sample reference
3401 // but we still have to provide some existing one to not corrupt the
3402 // file, so to avoid the latter we simply always assign the sample of
3403 // the first dimension region of this region
3404 pSample = pDimensionRegions[0]->pSample;
3405
3406 // first update base class's chunks
3407 DLS::Region::UpdateChunks(pProgress);
3408
3409 // update dimension region's chunks
3410 for (int i = 0; i < DimensionRegions; i++) {
3411 pDimensionRegions[i]->UpdateChunks(pProgress);
3412 }
3413
3414 File* pFile = (File*) GetParent()->GetParent();
3415 const bool versiongt2 = pFile->pVersion && pFile->pVersion->major > 2;
3416 const int iMaxDimensions = versiongt2 ? 8 : 5;
3417 const int iMaxDimensionRegions = versiongt2 ? 256 : 32;
3418
3419 // make sure '3lnk' chunk exists
3420 RIFF::Chunk* _3lnk = pCkRegion->GetSubChunk(CHUNK_ID_3LNK);
3421 if (!_3lnk) {
3422 const int _3lnkChunkSize = versiongt2 ? 1092 : 172;
3423 _3lnk = pCkRegion->AddSubChunk(CHUNK_ID_3LNK, _3lnkChunkSize);
3424 memset(_3lnk->LoadChunkData(), 0, _3lnkChunkSize);
3425
3426 // move 3prg to last position
3427 pCkRegion->MoveSubChunk(pCkRegion->GetSubList(LIST_TYPE_3PRG), (RIFF::Chunk*)NULL);
3428 }
3429
3430 // update dimension definitions in '3lnk' chunk
3431 uint8_t* pData = (uint8_t*) _3lnk->LoadChunkData();
3432 store32(&pData[0], DimensionRegions);
3433 int shift = 0;
3434 for (int i = 0; i < iMaxDimensions; i++) {
3435 pData[4 + i * 8] = (uint8_t) pDimensionDefinitions[i].dimension;
3436 pData[5 + i * 8] = pDimensionDefinitions[i].bits;
3437 pData[6 + i * 8] = pDimensionDefinitions[i].dimension == dimension_none ? 0 : shift;
3438 pData[7 + i * 8] = (1 << (shift + pDimensionDefinitions[i].bits)) - (1 << shift);
3439 pData[8 + i * 8] = pDimensionDefinitions[i].zones;
3440 // next 3 bytes unknown, always zero?
3441
3442 shift += pDimensionDefinitions[i].bits;
3443 }
3444
3445 // update wave pool table in '3lnk' chunk
3446 const int iWavePoolOffset = versiongt2 ? 68 : 44;
3447 for (uint i = 0; i < iMaxDimensionRegions; i++) {
3448 int iWaveIndex = -1;
3449 if (i < DimensionRegions) {
3450 if (!pFile->pSamples || !pFile->pSamples->size()) throw gig::Exception("Could not update gig::Region, there are no samples");
3451 File::SampleList::iterator iter = pFile->pSamples->begin();
3452 File::SampleList::iterator end = pFile->pSamples->end();
3453 for (int index = 0; iter != end; ++iter, ++index) {
3454 if (*iter == pDimensionRegions[i]->pSample) {
3455 iWaveIndex = index;
3456 break;
3457 }
3458 }
3459 }
3460 store32(&pData[iWavePoolOffset + i * 4], iWaveIndex);
3461 }
3462
3463 // The following chunks are just added for compatibility with the
3464 // GigaStudio software, which would show a warning if these were
3465 // missing. However currently these chunks don't cover any useful
3466 // data. So if this gig file uses any of our own gig format
3467 // extensions which would cause this gig file to be unloadable
3468 // with GSt software anyway, then just skip these GSt compatibility
3469 // chunks here as well.
3470 if (versiongt2 && !UsesAnyGigFormatExtension()) {
3471 // add 3dnm list which always seems to be empty
3472 RIFF::List* _3dnm = pCkRegion->GetSubList(LIST_TYPE_3DNM);
3473 if (!_3dnm) _3dnm = pCkRegion->AddSubList(LIST_TYPE_3DNM);
3474
3475 // add 3ddp chunk which always seems to have 16 bytes of 0xFF
3476 RIFF::Chunk* _3ddp = pCkRegion->GetSubChunk(CHUNK_ID_3DDP);
3477 if (!_3ddp) _3ddp = pCkRegion->AddSubChunk(CHUNK_ID_3DDP, 16);
3478 uint8_t* pData = (uint8_t*) _3ddp->LoadChunkData();
3479 for (int i = 0; i < 16; i += 4) {
3480 store32(&pData[i], 0xFFFFFFFF);
3481 }
3482
3483 // move 3dnm and 3ddp to the end of the region list
3484 pCkRegion->MoveSubChunk(pCkRegion->GetSubList(LIST_TYPE_3DNM), (RIFF::Chunk*)NULL);
3485 pCkRegion->MoveSubChunk(pCkRegion->GetSubChunk(CHUNK_ID_3DDP), (RIFF::Chunk*)NULL);
3486 } else {
3487 // this is intended for the user switching from GSt >= 3 version
3488 // back to an older format version, delete GSt3 chunks ...
3489 RIFF::List* _3dnm = pCkRegion->GetSubList(LIST_TYPE_3DNM);
3490 if (_3dnm) pCkRegion->DeleteSubChunk(_3dnm);
3491
3492 RIFF::Chunk* _3ddp = pCkRegion->GetSubChunk(CHUNK_ID_3DDP);
3493 if (_3ddp) pCkRegion->DeleteSubChunk(_3ddp);
3494 }
3495 }
3496
3497 void Region::LoadDimensionRegions(RIFF::List* rgn) {
3498 RIFF::List* _3prg = rgn->GetSubList(LIST_TYPE_3PRG);
3499 if (_3prg) {
3500 int dimensionRegionNr = 0;
3501 RIFF::List* _3ewl = _3prg->GetFirstSubList();
3502 while (_3ewl) {
3503 if (_3ewl->GetListType() == LIST_TYPE_3EWL) {
3504 pDimensionRegions[dimensionRegionNr] = new DimensionRegion(this, _3ewl);
3505 dimensionRegionNr++;
3506 }
3507 _3ewl = _3prg->GetNextSubList();
3508 }
3509 if (dimensionRegionNr == 0) throw gig::Exception("No dimension region found.");
3510 }
3511 }
3512
3513 void Region::SetKeyRange(uint16_t Low, uint16_t High) {
3514 // update KeyRange struct and make sure regions are in correct order
3515 DLS::Region::SetKeyRange(Low, High);
3516 // update Region key table for fast lookup
3517 ((gig::Instrument*)GetParent())->UpdateRegionKeyTable();
3518 }
3519
3520 void Region::UpdateVelocityTable() {
3521 // get velocity dimension's index
3522 int veldim = -1;
3523 for (int i = 0 ; i < Dimensions ; i++) {
3524 if (pDimensionDefinitions[i].dimension == gig::dimension_velocity) {
3525 veldim = i;
3526 break;
3527 }
3528 }
3529 if (veldim == -1) return;
3530
3531 int step = 1;
3532 for (int i = 0 ; i < veldim ; i++) step <<= pDimensionDefinitions[i].bits;
3533 int skipveldim = (step << pDimensionDefinitions[veldim].bits) - step;
3534
3535 // loop through all dimension regions for all dimensions except the velocity dimension
3536 int dim[8] = { 0 };
3537 for (int i = 0 ; i < DimensionRegions ; i++) {
3538 const int end = i + step * pDimensionDefinitions[veldim].zones;
3539
3540 // create a velocity table for all cases where the velocity zone is zero
3541 if (pDimensionRegions[i]->DimensionUpperLimits[veldim] ||
3542 pDimensionRegions[i]->VelocityUpperLimit) {
3543 // create the velocity table
3544 uint8_t* table = pDimensionRegions[i]->VelocityTable;
3545 if (!table) {
3546 table = new uint8_t[128];
3547 pDimensionRegions[i]->VelocityTable = table;
3548 }
3549 int tableidx = 0;
3550 int velocityZone = 0;
3551 if (pDimensionRegions[i]->DimensionUpperLimits[veldim]) { // gig3
3552 for (int k = i ; k < end ; k += step) {
3553 DimensionRegion *d = pDimensionRegions[k];
3554 for (; tableidx <= d->DimensionUpperLimits[veldim] ; tableidx++) table[tableidx] = velocityZone;
3555 velocityZone++;
3556 }
3557 } else { // gig2
3558 for (int k = i ; k < end ; k += step) {
3559 DimensionRegion *d = pDimensionRegions[k];
3560 for (; tableidx <= d->VelocityUpperLimit ; tableidx++) table[tableidx] = velocityZone;
3561 velocityZone++;
3562 }
3563 }
3564 } else {
3565 if (pDimensionRegions[i]->VelocityTable) {
3566 delete[] pDimensionRegions[i]->VelocityTable;
3567 pDimensionRegions[i]->VelocityTable = 0;
3568 }
3569 }
3570
3571 // jump to the next case where the velocity zone is zero
3572 int j;
3573 int shift = 0;
3574 for (j = 0 ; j < Dimensions ; j++) {
3575 if (j == veldim) i += skipveldim; // skip velocity dimension
3576 else {
3577 dim[j]++;
3578 if (dim[j] < pDimensionDefinitions[j].zones) break;
3579 else {
3580 // skip unused dimension regions
3581 dim[j] = 0;
3582 i += ((1 << pDimensionDefinitions[j].bits) -
3583 pDimensionDefinitions[j].zones) << shift;
3584 }
3585 }
3586 shift += pDimensionDefinitions[j].bits;
3587 }
3588 if (j == Dimensions) break;
3589 }
3590 }
3591
3592 /** @brief Einstein would have dreamed of it - create a new dimension.
3593 *
3594 * Creates a new dimension with the dimension definition given by
3595 * \a pDimDef. The appropriate amount of DimensionRegions will be created.
3596 * There is a hard limit of dimensions and total amount of "bits" all
3597 * dimensions can have. This limit is dependant to what gig file format
3598 * version this file refers to. The gig v2 (and lower) format has a
3599 * dimension limit and total amount of bits limit of 5, whereas the gig v3
3600 * format has a limit of 8.
3601 *
3602 * @param pDimDef - defintion of the new dimension
3603 * @throws gig::Exception if dimension of the same type exists already
3604 * @throws gig::Exception if amount of dimensions or total amount of
3605 * dimension bits limit is violated
3606 */
3607 void Region::AddDimension(dimension_def_t* pDimDef) {
3608 // some initial sanity checks of the given dimension definition
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");
3613 if (pDimDef->dimension == dimension_samplechannel) {
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");
3618 }
3619
3620 // check if max. amount of dimensions reached
3621 File* file = (File*) GetParent()->GetParent();
3622 const int iMaxDimensions = (file->pVersion && file->pVersion->major > 2) ? 8 : 5;
3623 if (Dimensions >= iMaxDimensions)
3624 throw gig::Exception("Could not add new dimension, max. amount of " + ToString(iMaxDimensions) + " dimensions already reached");
3625 // check if max. amount of dimension bits reached
3626 int iCurrentBits = 0;
3627 for (int i = 0; i < Dimensions; i++)
3628 iCurrentBits += pDimensionDefinitions[i].bits;
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");
3634 // check if there's already a dimensions of the same type
3635 for (int i = 0; i < Dimensions; i++)
3636 if (pDimensionDefinitions[i].dimension == pDimDef->dimension)
3637 throw gig::Exception("Could not add new dimension, there is already a dimension of the same type");
3638
3639 // pos is where the new dimension should be placed, normally
3640 // last in list, except for the samplechannel dimension which
3641 // has to be first in list
3642 int pos = pDimDef->dimension == dimension_samplechannel ? 0 : Dimensions;
3643 int bitpos = 0;
3644 for (int i = 0 ; i < pos ; i++)
3645 bitpos += pDimensionDefinitions[i].bits;
3646
3647 // make room for the new dimension
3648 for (int i = Dimensions ; i > pos ; i--) pDimensionDefinitions[i] = pDimensionDefinitions[i - 1];
3649 for (int i = 0 ; i < (1 << iCurrentBits) ; i++) {
3650 for (int j = Dimensions ; j > pos ; j--) {
3651 pDimensionRegions[i]->DimensionUpperLimits[j] =
3652 pDimensionRegions[i]->DimensionUpperLimits[j - 1];
3653 }
3654 }
3655
3656 // assign definition of new dimension
3657 pDimensionDefinitions[pos] = *pDimDef;
3658
3659 // auto correct certain dimension definition fields (where possible)
3660 pDimensionDefinitions[pos].split_type =
3661 __resolveSplitType(pDimensionDefinitions[pos].dimension);
3662 pDimensionDefinitions[pos].zone_size =
3663 __resolveZoneSize(pDimensionDefinitions[pos]);
3664
3665 // create new dimension region(s) for this new dimension, and make
3666 // sure that the dimension regions are placed correctly in both the
3667 // RIFF list and the pDimensionRegions array
3668 RIFF::Chunk* moveTo = NULL;
3669 RIFF::List* _3prg = pCkRegion->GetSubList(LIST_TYPE_3PRG);
3670 for (int i = (1 << iCurrentBits) - (1 << bitpos) ; i >= 0 ; i -= (1 << bitpos)) {
3671 for (int k = 0 ; k < (1 << bitpos) ; k++) {
3672 pDimensionRegions[(i << pDimDef->bits) + k] = pDimensionRegions[i + k];
3673 }
3674 for (int j = 1 ; j < (1 << pDimDef->bits) ; j++) {
3675 for (int k = 0 ; k < (1 << bitpos) ; k++) {
3676 RIFF::List* pNewDimRgnListChunk = _3prg->AddSubList(LIST_TYPE_3EWL);
3677 if (moveTo) _3prg->MoveSubChunk(pNewDimRgnListChunk, moveTo);
3678 // create a new dimension region and copy all parameter values from
3679 // an existing dimension region
3680 pDimensionRegions[(i << pDimDef->bits) + (j << bitpos) + k] =
3681 new DimensionRegion(pNewDimRgnListChunk, *pDimensionRegions[i + k]);
3682
3683 DimensionRegions++;
3684 }
3685 }
3686 moveTo = pDimensionRegions[i]->pParentList;
3687 }
3688
3689 // initialize the upper limits for this dimension
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++) {
3694 pDimensionRegions[((i & ~mask) << pDimDef->bits) |
3695 (z << bitpos) |
3696 (i & mask)]->DimensionUpperLimits[pos] = upperLimit;
3697 }
3698 }
3699
3700 Dimensions++;
3701
3702 // if this is a layer dimension, update 'Layers' attribute
3703 if (pDimDef->dimension == dimension_layer) Layers = pDimDef->zones;
3704
3705 UpdateVelocityTable();
3706 }
3707
3708 /** @brief Delete an existing dimension.
3709 *
3710 * Deletes the dimension given by \a pDimDef and deletes all respective
3711 * dimension regions, that is all dimension regions where the dimension's
3712 * bit(s) part is greater than 0. In case of a 'sustain pedal' dimension
3713 * for example this would delete all dimension regions for the case(s)
3714 * where the sustain pedal is pressed down.
3715 *
3716 * @param pDimDef - dimension to delete
3717 * @throws gig::Exception if given dimension cannot be found
3718 */
3719 void Region::DeleteDimension(dimension_def_t* pDimDef) {
3720 // get dimension's index
3721 int iDimensionNr = -1;
3722 for (int i = 0; i < Dimensions; i++) {
3723 if (&pDimensionDefinitions[i] == pDimDef) {
3724 iDimensionNr = i;
3725 break;
3726 }
3727 }
3728 if (iDimensionNr < 0) throw gig::Exception("Invalid dimension_def_t pointer");
3729
3730 // get amount of bits below the dimension to delete
3731 int iLowerBits = 0;
3732 for (int i = 0; i < iDimensionNr; i++)
3733 iLowerBits += pDimensionDefinitions[i].bits;
3734
3735 // get amount ot bits above the dimension to delete
3736 int iUpperBits = 0;
3737 for (int i = iDimensionNr + 1; i < Dimensions; i++)
3738 iUpperBits += pDimensionDefinitions[i].bits;
3739
3740 RIFF::List* _3prg = pCkRegion->GetSubList(LIST_TYPE_3PRG);
3741
3742 // delete dimension regions which belong to the given dimension
3743 // (that is where the dimension's bit > 0)
3744 for (int iUpperBit = 0; iUpperBit < 1 << iUpperBits; iUpperBit++) {
3745 for (int iObsoleteBit = 1; iObsoleteBit < 1 << pDimensionDefinitions[iDimensionNr].bits; iObsoleteBit++) {
3746 for (int iLowerBit = 0; iLowerBit < 1 << iLowerBits; iLowerBit++) {
3747 int iToDelete = iUpperBit << (pDimensionDefinitions[iDimensionNr].bits + iLowerBits) |
3748 iObsoleteBit << iLowerBits |
3749 iLowerBit;
3750
3751 _3prg->DeleteSubChunk(pDimensionRegions[iToDelete]->pParentList);
3752 delete pDimensionRegions[iToDelete];
3753 pDimensionRegions[iToDelete] = NULL;
3754 DimensionRegions--;
3755 }
3756 }
3757 }
3758
3759 // defrag pDimensionRegions array
3760 // (that is remove the NULL spaces within the pDimensionRegions array)
3761 for (int iFrom = 2, iTo = 1; iFrom < 256 && iTo < 256 - 1; iTo++) {
3762 if (!pDimensionRegions[iTo]) {
3763 if (iFrom <= iTo) iFrom = iTo + 1;
3764 while (!pDimensionRegions[iFrom] && iFrom < 256) iFrom++;
3765 if (iFrom < 256 && pDimensionRegions[iFrom]) {
3766 pDimensionRegions[iTo] = pDimensionRegions[iFrom];
3767 pDimensionRegions[iFrom] = NULL;
3768 }
3769 }
3770 }
3771
3772 // remove the this dimension from the upper limits arrays
3773 for (int j = 0 ; j < 256 && pDimensionRegions[j] ; j++) {
3774 DimensionRegion* d = pDimensionRegions[j];
3775 for (int i = iDimensionNr + 1; i < Dimensions; i++) {
3776 d->DimensionUpperLimits[i - 1] = d->DimensionUpperLimits[i];
3777 }
3778 d->DimensionUpperLimits[Dimensions - 1] = 127;
3779 }
3780
3781 // 'remove' dimension definition
3782 for (int i = iDimensionNr + 1; i < Dimensions; i++) {
3783 pDimensionDefinitions[i - 1] = pDimensionDefinitions[i];
3784 }
3785 pDimensionDefinitions[Dimensions - 1].dimension = dimension_none;
3786 pDimensionDefinitions[Dimensions - 1].bits = 0;
3787 pDimensionDefinitions[Dimensions - 1].zones = 0;
3788
3789 Dimensions--;
3790
3791 // if this was a layer dimension, update 'Layers' attribute
3792 if (pDimDef->dimension == dimension_layer) Layers = 1;
3793 }
3794
3795 /** @brief Delete one split zone of a dimension (decrement zone amount).
3796 *
3797 * Instead of deleting an entire dimensions, this method will only delete
3798 * one particular split zone given by @a zone of the Region's dimension
3799 * given by @a type. So this method will simply decrement the amount of
3800 * zones by one of the dimension in question. To be able to do that, the
3801 * respective dimension must exist on this Region and it must have at least
3802 * 3 zones. All DimensionRegion objects associated with the zone will be
3803 * deleted.
3804 *
3805 * @param type - identifies the dimension where a zone shall be deleted
3806 * @param zone - index of the dimension split zone that shall be deleted
3807 * @throws gig::Exception if requested zone could not be deleted
3808 */
3809 void Region::DeleteDimensionZone(dimension_t type, int zone) {
3810 dimension_def_t* oldDef = GetDimensionDefinition(type);
3811 if (!oldDef)
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.");
3817
3818 const int newZoneSize = oldDef->zones - 1;
3819
3820 // create a temporary Region which just acts as a temporary copy
3821 // container and will be deleted at the end of this function and will
3822 // also not be visible through the API during this process
3823 gig::Region* tempRgn = NULL;
3824 {
3825 // adding these temporary chunks is probably not even necessary
3826 Instrument* instr = static_cast<Instrument*>(GetParent());
3827 RIFF::List* pCkInstrument = instr->pCkInstrument;
3828 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
3829 if (!lrgn) lrgn = pCkInstrument->AddSubList(LIST_TYPE_LRGN);
3830 RIFF::List* rgn = lrgn->AddSubList(LIST_TYPE_RGN);
3831 tempRgn = new Region(instr, rgn);
3832 }
3833
3834 // copy this region's dimensions (with already the dimension split size
3835 // requested by the arguments of this method call) to the temporary
3836 // region, and don't use Region::CopyAssign() here for this task, since
3837 // it would also alter fast lookup helper variables here and there
3838 dimension_def_t newDef;
3839 for (int i = 0; i < Dimensions; ++i) {
3840 dimension_def_t def = pDimensionDefinitions[i]; // copy, don't reference
3841 // is this the dimension requested by the method arguments? ...
3842 if (def.dimension == type) { // ... if yes, decrement zone amount by one
3843 def.zones = newZoneSize;
3844 if ((1 << (def.bits - 1)) == def.zones) def.bits--;
3845 newDef = def;
3846 }
3847 tempRgn->AddDimension(&def);
3848 }
3849
3850 // find the dimension index in the tempRegion which is the dimension
3851 // type passed to this method (paranoidly expecting different order)
3852 int tempReducedDimensionIndex = -1;
3853 for (int d = 0; d < tempRgn->Dimensions; ++d) {
3854 if (tempRgn->pDimensionDefinitions[d].dimension == type) {
3855 tempReducedDimensionIndex = d;
3856 break;
3857 }
3858 }
3859
3860 // copy dimension regions from this region to the temporary region
3861 for (int iDst = 0; iDst < 256; ++iDst) {
3862 DimensionRegion* dstDimRgn = tempRgn->pDimensionRegions[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) {
3867 const int dstBits = tempRgn->pDimensionDefinitions[d].bits;
3868 dimCase[tempRgn->pDimensionDefinitions[d].dimension] =
3869 (iDst >> baseBits) & ((1 << dstBits) - 1);
3870 baseBits += dstBits;
3871 // there are also DimensionRegion objects of unused zones, skip them
3872 if (dimCase[tempRgn->pDimensionDefinitions[d].dimension] >= tempRgn->pDimensionDefinitions[d].zones) {
3873 isValidZone = false;
3874 break;
3875 }
3876 }
3877 if (!isValidZone) continue;
3878 // a bit paranoid: cope with the chance that the dimensions would
3879 // have different order in source and destination regions
3880 const bool isLastZone = (dimCase[type] == newZoneSize - 1);
3881 if (dimCase[type] >= zone) dimCase[type]++;
3882 DimensionRegion* srcDimRgn = GetDimensionRegionByBit(dimCase);
3883 dstDimRgn->CopyAssign(srcDimRgn);
3884 // if this is the upper most zone of the dimension passed to this
3885 // method, then correct (raise) its upper limit to 127
3886 if (newDef.split_type == split_type_normal && isLastZone)
3887 dstDimRgn->DimensionUpperLimits[tempReducedDimensionIndex] = 127;
3888 }
3889
3890 // now tempRegion's dimensions and DimensionRegions basically reflect
3891 // what we wanted to get for this actual Region here, so we now just
3892 // delete and recreate the dimension in question with the new amount
3893 // zones and then copy back from tempRegion. we're actually deleting and
3894 // recreating all dimensions here, to avoid altering the precise order
3895 // of the dimensions (which would not be an error per se, but it would
3896 // cause usability issues with instrument editors)
3897 {
3898 std::vector<dimension_def_t> oldDefs;
3899 for (int i = 0; i < Dimensions; ++i)
3900 oldDefs.push_back(pDimensionDefinitions[i]); // copy, don't reference
3901 for (int i = Dimensions - 1; i >= 0; --i)
3902 DeleteDimension(&pDimensionDefinitions[i]);
3903 for (int i = 0; i < oldDefs.size(); ++i) {
3904 dimension_def_t& def = oldDefs[i];
3905 AddDimension(
3906 (def.dimension == newDef.dimension) ? &newDef : &def
3907 );
3908 }
3909 }
3910 for (int iSrc = 0; iSrc < 256; ++iSrc) {
3911 DimensionRegion* srcDimRgn = tempRgn->pDimensionRegions[iSrc];
3912 if (!srcDimRgn) continue;
3913 std::map<dimension_t,int> dimCase;
3914 for (int d = 0, baseBits = 0; d < tempRgn->Dimensions; ++d) {
3915 const int srcBits = tempRgn->pDimensionDefinitions[d].bits;
3916 dimCase[tempRgn->pDimensionDefinitions[d].dimension] =
3917 (iSrc >> baseBits) & ((1 << srcBits) - 1);
3918 baseBits += srcBits;
3919 }
3920 // a bit paranoid: cope with the chance that the dimensions would
3921 // have different order in source and destination regions
3922 DimensionRegion* dstDimRgn = GetDimensionRegionByBit(dimCase);
3923 if (!dstDimRgn) continue;
3924 dstDimRgn->CopyAssign(srcDimRgn);
3925 }
3926
3927 // delete temporary region
3928 tempRgn->DeleteChunks();
3929 delete tempRgn;
3930
3931 UpdateVelocityTable();
3932 }
3933
3934 /** @brief Divide split zone of a dimension in two (increment zone amount).
3935 *
3936 * This will increment the amount of zones for the dimension (given by
3937 * @a type) by one. It will do so by dividing the zone (given by @a zone)
3938 * in the middle of its zone range in two. So the two zones resulting from
3939 * the zone being splitted, will be an equivalent copy regarding all their
3940 * articulation informations and sample reference. The two zones will only
3941 * differ in their zone's upper limit
3942 * (DimensionRegion::DimensionUpperLimits).
3943 *
3944 * @param type - identifies the dimension where a zone shall be splitted
3945 * @param zone - index of the dimension split zone that shall be splitted
3946 * @throws gig::Exception if requested zone could not be splitted
3947 */
3948 void Region::SplitDimensionZone(dimension_t type, int zone) {
3949 dimension_def_t* oldDef = GetDimensionDefinition(type);
3950 if (!oldDef)
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.");
3954
3955 const int newZoneSize = oldDef->zones + 1;
3956
3957 // create a temporary Region which just acts as a temporary copy
3958 // container and will be deleted at the end of this function and will
3959 // also not be visible through the API during this process
3960 gig::Region* tempRgn = NULL;
3961 {
3962 // adding these temporary chunks is probably not even necessary
3963 Instrument* instr = static_cast<Instrument*>(GetParent());
3964 RIFF::List* pCkInstrument = instr->pCkInstrument;
3965 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
3966 if (!lrgn) lrgn = pCkInstrument->AddSubList(LIST_TYPE_LRGN);
3967 RIFF::List* rgn = lrgn->AddSubList(LIST_TYPE_RGN);
3968 tempRgn = new Region(instr, rgn);
3969 }
3970
3971 // copy this region's dimensions (with already the dimension split size
3972 // requested by the arguments of this method call) to the temporary
3973 // region, and don't use Region::CopyAssign() here for this task, since
3974 // it would also alter fast lookup helper variables here and there
3975 dimension_def_t newDef;
3976 for (int i = 0; i < Dimensions; ++i) {
3977 dimension_def_t def = pDimensionDefinitions[i]; // copy, don't reference
3978 // is this the dimension requested by the method arguments? ...
3979 if (def.dimension == type) { // ... if yes, increment zone amount by one
3980 def.zones = newZoneSize;
3981 if ((1 << oldDef->bits) < newZoneSize) def.bits++;
3982 newDef = def;
3983 }
3984 tempRgn->AddDimension(&def);
3985 }
3986
3987 // find the dimension index in the tempRegion which is the dimension
3988 // type passed to this method (paranoidly expecting different order)
3989 int tempIncreasedDimensionIndex = -1;
3990 for (int d = 0; d < tempRgn->Dimensions; ++d) {
3991 if (tempRgn->pDimensionDefinitions[d].dimension == type) {
3992 tempIncreasedDimensionIndex = d;
3993 break;
3994 }
3995 }
3996
3997 // copy dimension regions from this region to the temporary region
3998 for (int iSrc = 0; iSrc < 256; ++iSrc) {
3999 DimensionRegion* srcDimRgn = pDimensionRegions[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) {
4004 const int srcBits = pDimensionDefinitions[d].bits;
4005 dimCase[pDimensionDefinitions[d].dimension] =
4006 (iSrc >> baseBits) & ((1 << srcBits) - 1);
4007 // there are also DimensionRegion objects for unused zones, skip them
4008 if (dimCase[pDimensionDefinitions[d].dimension] >= pDimensionDefinitions[d].zones) {
4009 isValidZone = false;
4010 break;
4011 }
4012 baseBits += srcBits;
4013 }
4014 if (!isValidZone) continue;
4015 // a bit paranoid: cope with the chance that the dimensions would
4016 // have different order in source and destination regions
4017 if (dimCase[type] > zone) dimCase[type]++;
4018 DimensionRegion* dstDimRgn = tempRgn->GetDimensionRegionByBit(dimCase);
4019 dstDimRgn->CopyAssign(srcDimRgn);
4020 // if this is the requested zone to be splitted, then also copy
4021 // the source DimensionRegion to the newly created target zone
4022 // and set the old zones upper limit lower
4023 if (dimCase[type] == zone) {
4024 // lower old zones upper limit
4025 if (newDef.split_type == split_type_normal) {
4026 const int high =
4027 dstDimRgn->DimensionUpperLimits[tempIncreasedDimensionIndex];
4028 int low = 0;
4029 if (zone > 0) {
4030 std::map<dimension_t,int> lowerCase = dimCase;
4031 lowerCase[type]--;
4032 DimensionRegion* dstDimRgnLow = tempRgn->GetDimensionRegionByBit(lowerCase);
4033 low = dstDimRgnLow->DimensionUpperLimits[tempIncreasedDimensionIndex];
4034 }
4035 dstDimRgn->DimensionUpperLimits[tempIncreasedDimensionIndex] = low + (high - low) / 2;
4036 }
4037 // fill the newly created zone of the divided zone as well
4038 dimCase[type]++;
4039 dstDimRgn = tempRgn->GetDimensionRegionByBit(dimCase);
4040 dstDimRgn->CopyAssign(srcDimRgn);
4041 }
4042 }
4043
4044 // now tempRegion's dimensions and DimensionRegions basically reflect
4045 // what we wanted to get for this actual Region here, so we now just
4046 // delete and recreate the dimension in question with the new amount
4047 // zones and then copy back from tempRegion. we're actually deleting and
4048 // recreating all dimensions here, to avoid altering the precise order
4049 // of the dimensions (which would not be an error per se, but it would
4050 // cause usability issues with instrument editors)
4051 {
4052 std::vector<dimension_def_t> oldDefs;
4053 for (int i = 0; i < Dimensions; ++i)
4054 oldDefs.push_back(pDimensionDefinitions[i]); // copy, don't reference
4055 for (int i = Dimensions - 1; i >= 0; --i)
4056 DeleteDimension(&pDimensionDefinitions[i]);
4057 for (int i = 0; i < oldDefs.size(); ++i) {
4058 dimension_def_t& def = oldDefs[i];
4059 AddDimension(
4060 (def.dimension == newDef.dimension) ? &newDef : &def
4061 );
4062 }
4063 }
4064 for (int iSrc = 0; iSrc < 256; ++iSrc) {
4065 DimensionRegion* srcDimRgn = tempRgn->pDimensionRegions[iSrc];
4066 if (!srcDimRgn) continue;
4067 std::map<dimension_t,int> dimCase;
4068 for (int d = 0, baseBits = 0; d < tempRgn->Dimensions; ++d) {
4069 const int srcBits = tempRgn->pDimensionDefinitions[d].bits;
4070 dimCase[tempRgn->pDimensionDefinitions[d].dimension] =
4071 (iSrc >> baseBits) & ((1 << srcBits) - 1);
4072 baseBits += srcBits;
4073 }
4074 // a bit paranoid: cope with the chance that the dimensions would
4075 // have different order in source and destination regions
4076 DimensionRegion* dstDimRgn = GetDimensionRegionByBit(dimCase);
4077 if (!dstDimRgn) continue;
4078 dstDimRgn->CopyAssign(srcDimRgn);
4079 }
4080
4081 // delete temporary region
4082 tempRgn->DeleteChunks();
4083 delete tempRgn;
4084
4085 UpdateVelocityTable();
4086 }
4087
4088 /** @brief Change type of an existing dimension.
4089 *
4090 * Alters the dimension type of a dimension already existing on this
4091 * region. If there is currently no dimension on this Region with type
4092 * @a oldType, then this call with throw an Exception. Likewise there are
4093 * cases where the requested dimension type cannot be performed. For example
4094 * if the new dimension type shall be gig::dimension_samplechannel, and the
4095 * current dimension has more than 2 zones. In such cases an Exception is
4096 * thrown as well.
4097 *
4098 * @param oldType - identifies the existing dimension to be changed
4099 * @param newType - to which dimension type it should be changed to
4100 * @throws gig::Exception if requested change cannot be performed
4101 */
4102 void Region::SetDimensionType(dimension_t oldType, dimension_t newType) {
4103 if (oldType == newType) return;
4104 dimension_def_t* def = GetDimensionDefinition(oldType);
4105 if (!def)
4106 throw gig::Exception("No dimension with provided old dimension type exists on this region");
4107 if (newType == dimension_samplechannel && def->zones != 2)
4108 throw gig::Exception("Cannot change to dimension type 'sample channel', because existing dimension does not have 2 zones");
4109 if (GetDimensionDefinition(newType))
4110 throw gig::Exception("There is already a dimension with requested new dimension type on this region");
4111 def->dimension = newType;
4112 def->split_type = __resolveSplitType(newType);
4113 }
4114
4115 DimensionRegion* Region::GetDimensionRegionByBit(const std::map<dimension_t,int>& DimCase) {
4116 uint8_t bits[8] = {};
4117 for (std::map<dimension_t,int>::const_iterator it = DimCase.begin();
4118 it != DimCase.end(); ++it)
4119 {
4120 for (int d = 0; d < Dimensions; ++d) {
4121 if (pDimensionDefinitions[d].dimension == it->first) {
4122 bits[d] = it->second;
4123 goto nextDimCaseSlice;
4124 }
4125 }
4126 assert(false); // do crash ... too harsh maybe ? ignore it instead ?
4127 nextDimCaseSlice:
4128 ; // noop
4129 }
4130 return GetDimensionRegionByBit(bits);
4131 }
4132
4133 /**
4134 * Searches in the current Region for a dimension of the given dimension
4135 * type and returns the precise configuration of that dimension in this
4136 * Region.
4137 *
4138 * @param type - dimension type of the sought dimension
4139 * @returns dimension definition or NULL if there is no dimension with
4140 * sought type in this Region.
4141 */
4142 dimension_def_t* Region::GetDimensionDefinition(dimension_t type) {
4143 for (int i = 0; i < Dimensions; ++i)
4144 if (pDimensionDefinitions[i].dimension == type)
4145 return &pDimensionDefinitions[i];
4146 return NULL;
4147 }
4148
4149 Region::~Region() {
4150 for (int i = 0; i < 256; i++) {
4151 if (pDimensionRegions[i]) delete pDimensionRegions[i];
4152 }
4153 }
4154
4155 /**
4156 * Use this method in your audio engine to get the appropriate dimension
4157 * region with it's articulation data for the current situation. Just
4158 * call the method with the current MIDI controller values and you'll get
4159 * the DimensionRegion with the appropriate articulation data for the
4160 * current situation (for this Region of course only). To do that you'll
4161 * first have to look which dimensions with which controllers and in
4162 * which order are defined for this Region when you load the .gig file.
4163 * Special cases are e.g. layer or channel dimensions where you just put
4164 * in the index numbers instead of a MIDI controller value (means 0 for
4165 * left channel, 1 for right channel or 0 for layer 0, 1 for layer 1,
4166 * etc.).
4167 *
4168 * @param DimValues MIDI controller values (0-127) for dimension 0 to 7
4169 * @returns adress to the DimensionRegion for the given situation
4170 * @see pDimensionDefinitions
4171 * @see Dimensions
4172 */
4173 DimensionRegion* Region::GetDimensionRegionByValue(const uint DimValues[8]) {
4174 uint8_t bits;
4175 int veldim = -1;
4176 int velbitpos = 0;
4177 int bitpos = 0;
4178 int dimregidx = 0;
4179 for (uint i = 0; i < Dimensions; i++) {
4180 if (pDimensionDefinitions[i].dimension == dimension_velocity) {
4181 // the velocity dimension must be handled after the other dimensions
4182 veldim = i;
4183 velbitpos = bitpos;
4184 } else {
4185 switch (pDimensionDefinitions[i].split_type) {
4186 case split_type_normal:
4187 if (pDimensionRegions[0]->DimensionUpperLimits[i]) {
4188 // gig3: all normal dimensions (not just the velocity dimension) have custom zone ranges
4189 for (bits = 0 ; bits < pDimensionDefinitions[i].zones ; bits++) {
4190 if (DimValues[i] <= pDimensionRegions[bits << bitpos]->DimensionUpperLimits[i]) break;
4191 }
4192 } else {
4193 // gig2: evenly sized zones
4194 bits = uint8_t(DimValues[i] / pDimensionDefinitions[i].zone_size);
4195 }
4196 break;
4197 case split_type_bit: // the value is already the sought dimension bit number
4198 const uint8_t limiter_mask = (0xff << pDimensionDefinitions[i].bits) ^ 0xff;
4199 bits = DimValues[i] & limiter_mask; // just make sure the value doesn't use more bits than allowed
4200 break;
4201 }
4202 dimregidx |= bits << bitpos;
4203 }
4204 bitpos += pDimensionDefinitions[i].bits;
4205 }
4206 DimensionRegion* dimreg = pDimensionRegions[dimregidx & 255];
4207 if (!dimreg) return NULL;
4208 if (veldim != -1) {
4209 // (dimreg is now the dimension region for the lowest velocity)
4210 if (dimreg->VelocityTable) // custom defined zone ranges
4211 bits = dimreg->VelocityTable[DimValues[veldim] & 127];
4212 else // normal split type
4213 bits = uint8_t((DimValues[veldim] & 127) / pDimensionDefinitions[veldim].zone_size);
4214
4215 const uint8_t limiter_mask = (1 << pDimensionDefinitions[veldim].bits) - 1;
4216 dimregidx |= (bits & limiter_mask) << velbitpos;
4217 dimreg = pDimensionRegions[dimregidx & 255];
4218 }
4219 return dimreg;
4220 }
4221
4222 int Region::GetDimensionRegionIndexByValue(const uint DimValues[8]) {
4223 uint8_t bits;
4224 int veldim = -1;
4225 int velbitpos = 0;
4226 int bitpos = 0;
4227 int dimregidx = 0;
4228 for (uint i = 0; i < Dimensions; i++) {
4229 if (pDimensionDefinitions[i].dimension == dimension_velocity) {
4230 // the velocity dimension must be handled after the other dimensions
4231 veldim = i;
4232 velbitpos = bitpos;
4233 } else {
4234 switch (pDimensionDefinitions[i].split_type) {
4235 case split_type_normal:
4236 if (pDimensionRegions[0]->DimensionUpperLimits[i]) {
4237 // gig3: all normal dimensions (not just the velocity dimension) have custom zone ranges
4238 for (bits = 0 ; bits < pDimensionDefinitions[i].zones ; bits++) {
4239 if (DimValues[i] <= pDimensionRegions[bits << bitpos]->DimensionUpperLimits[i]) break;
4240 }
4241 } else {
4242 // gig2: evenly sized zones
4243 bits = uint8_t(DimValues[i] / pDimensionDefinitions[i].zone_size);
4244 }
4245 break;
4246 case split_type_bit: // the value is already the sought dimension bit number
4247 const uint8_t limiter_mask = (0xff << pDimensionDefinitions[i].bits) ^ 0xff;
4248 bits = DimValues[i] & limiter_mask; // just make sure the value doesn't use more bits than allowed
4249 break;
4250 }
4251 dimregidx |= bits << bitpos;
4252 }
4253 bitpos += pDimensionDefinitions[i].bits;
4254 }
4255 dimregidx &= 255;
4256 DimensionRegion* dimreg = pDimensionRegions[dimregidx];
4257 if (!dimreg) return -1;
4258 if (veldim != -1) {
4259 // (dimreg is now the dimension region for the lowest velocity)
4260 if (dimreg->VelocityTable) // custom defined zone ranges
4261 bits = dimreg->VelocityTable[DimValues[veldim] & 127];
4262 else // normal split type
4263 bits = uint8_t((DimValues[veldim] & 127) / pDimensionDefinitions[veldim].zone_size);
4264
4265 const uint8_t limiter_mask = (1 << pDimensionDefinitions[veldim].bits) - 1;
4266 dimregidx |= (bits & limiter_mask) << velbitpos;
4267 dimregidx &= 255;
4268 }
4269 return dimregidx;
4270 }
4271
4272 /**
4273 * Returns the appropriate DimensionRegion for the given dimension bit
4274 * numbers (zone index). You usually use <i>GetDimensionRegionByValue</i>
4275 * instead of calling this method directly!
4276 *
4277 * @param DimBits Bit numbers for dimension 0 to 7
4278 * @returns adress to the DimensionRegion for the given dimension
4279 * bit numbers
4280 * @see GetDimensionRegionByValue()
4281 */
4282 DimensionRegion* Region::GetDimensionRegionByBit(const uint8_t DimBits[8]) {
4283 return pDimensionRegions[((((((DimBits[7] << pDimensionDefinitions[6].bits | DimBits[6])
4284 << pDimensionDefinitions[5].bits | DimBits[5])
4285 << pDimensionDefinitions[4].bits | DimBits[4])
4286 << pDimensionDefinitions[3].bits | DimBits[3])
4287 << pDimensionDefinitions[2].bits | DimBits[2])
4288 << pDimensionDefinitions[1].bits | DimBits[1])
4289 << pDimensionDefinitions[0].bits | DimBits[0]];
4290 }
4291
4292 /**
4293 * Returns pointer address to the Sample referenced with this region.
4294 * This is the global Sample for the entire Region (not sure if this is
4295 * actually used by the Gigasampler engine - I would only use the Sample
4296 * referenced by the appropriate DimensionRegion instead of this sample).
4297 *
4298 * @returns address to Sample or NULL if there is no reference to a
4299 * sample saved in the .gig file
4300 */
4301 Sample* Region::GetSample() {
4302 if (pSample) return static_cast<gig::Sample*>(pSample);
4303 else return static_cast<gig::Sample*>(pSample = GetSampleFromWavePool(WavePoolTableIndex));
4304 }
4305
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;
4311 // for new files or files >= 2 GB use 64 bit wave pool offsets
4312 if (file->pRIFF->IsNew() || (file->pRIFF->GetCurrentFileSize() >> 31)) {
4313 // use 64 bit wave pool offsets (treating this as large file)
4314 uint64_t soughtoffset =
4315 uint64_t(file->pWavePoolTable[WavePoolTableIndex]) |
4316 uint64_t(file->pWavePoolTableHi[WavePoolTableIndex]) << 32;
4317 Sample* sample = file->GetFirstSample(pProgress);
4318 while (sample) {
4319 if (sample->ullWavePoolOffset == soughtoffset)
4320 return static_cast<gig::Sample*>(sample);
4321 sample = file->GetNextSample();
4322 }
4323 } else {
4324 // use extension files and 32 bit wave pool offsets
4325 file_offset_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
4326 file_offset_t soughtfileno = file->pWavePoolTableHi[WavePoolTableIndex];
4327 Sample* sample = file->GetFirstSample(pProgress);
4328 while (sample) {
4329 if (sample->ullWavePoolOffset == soughtoffset &&
4330 sample->FileNo == soughtfileno) return static_cast<gig::Sample*>(sample);
4331 sample = file->GetNextSample();
4332 }
4333 }
4334 return NULL;
4335 }
4336
4337 /**
4338 * Make a (semi) deep copy of the Region object given by @a orig
4339 * and assign it to this object.
4340 *
4341 * Note that all sample pointers referenced by @a orig are simply copied as
4342 * memory address. Thus the respective samples are shared, not duplicated!
4343 *
4344 * @param orig - original Region object to be copied from
4345 */
4346 void Region::CopyAssign(const Region* orig) {
4347 CopyAssign(orig, NULL);
4348 }
4349
4350 /**
4351 * Make a (semi) deep copy of the Region object given by @a orig and
4352 * assign it to this object
4353 *
4354 * @param mSamples - crosslink map between the foreign file's samples and
4355 * this file's samples
4356 */
4357 void Region::CopyAssign(const Region* orig, const std::map<Sample*,Sample*>* mSamples) {
4358 // handle base classes
4359 DLS::Region::CopyAssign(orig);
4360
4361 if (mSamples && mSamples->count((gig::Sample*)orig->pSample)) {
4362 pSample = mSamples->find((gig::Sample*)orig->pSample)->second;
4363 }
4364
4365 // handle own member variables
4366 for (int i = Dimensions - 1; i >= 0; --i) {
4367 DeleteDimension(&pDimensionDefinitions[i]);
4368 }
4369 Layers = 0; // just to be sure
4370 for (int i = 0; i < orig->Dimensions; i++) {
4371 // we need to copy the dim definition here, to avoid the compiler
4372 // complaining about const-ness issue
4373 dimension_def_t def = orig->pDimensionDefinitions[i];
4374 AddDimension(&def);
4375 }
4376 for (int i = 0; i < 256; i++) {
4377 if (pDimensionRegions[i] && orig->pDimensionRegions[i]) {
4378 pDimensionRegions[i]->CopyAssign(
4379 orig->pDimensionRegions[i],
4380 mSamples
4381 );
4382 }
4383 }
4384 Layers = orig->Layers;
4385 }
4386
4387 /**
4388 * Returns @c true in case this Region object uses any gig format
4389 * extension, that is e.g. whether any DimensionRegion object currently
4390 * has any setting effective that would require our "LSDE" RIFF chunk to
4391 * be stored to the gig file.
4392 *
4393 * Right now this is a private method. It is considerable though this method
4394 * to become (in slightly modified form) a public API method in future, i.e.
4395 * to allow instrument editors to visualize and/or warn the user of any gig
4396 * format extension being used. See also comments on
4397 * DimensionRegion::UsesAnyGigFormatExtension() for details about such a
4398 * potential public API change in future.
4399 */
4400 bool Region::UsesAnyGigFormatExtension() const {
4401 for (int i = 0; i < 256; i++) {
4402 if (pDimensionRegions[i]) {
4403 if (pDimensionRegions[i]->UsesAnyGigFormatExtension())
4404 return true;
4405 }
4406 }
4407 return false;
4408 }
4409
4410
4411 // *************** MidiRule ***************
4412 // *
4413
4414 MidiRuleCtrlTrigger::MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg) {
4415 _3ewg->SetPos(36);
4416 Triggers = _3ewg->ReadUint8();
4417 _3ewg->SetPos(40);
4418 ControllerNumber = _3ewg->ReadUint8();
4419 _3ewg->SetPos(46);
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();
4424 pTriggers[i].Key = _3ewg->ReadUint8();
4425 pTriggers[i].NoteOff = _3ewg->ReadUint8();
4426 pTriggers[i].Velocity = _3ewg->ReadUint8();
4427 pTriggers[i].OverridePedal = _3ewg->ReadUint8();
4428 _3ewg->ReadUint8();
4429 }
4430 }
4431
4432 MidiRuleCtrlTrigger::MidiRuleCtrlTrigger() :
4433 ControllerNumber(0),
4434 Triggers(0) {
4435 }
4436
4437 void MidiRuleCtrlTrigger::UpdateChunks(uint8_t* pData) const {
4438 pData[32] = 4;
4439 pData[33] = 16;
4440 pData[36] = Triggers;
4441 pData[40] = ControllerNumber;
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;
4450 }
4451 }
4452
4453 MidiRuleLegato::MidiRuleLegato(RIFF::Chunk* _3ewg) {
4454 _3ewg->SetPos(36);
4455 LegatoSamples = _3ewg->ReadUint8(); // always 12
4456 _3ewg->SetPos(40);
4457 BypassUseController = _3ewg->ReadUint8();
4458 BypassKey = _3ewg->ReadUint8();
4459 BypassController = _3ewg->ReadUint8();
4460 ThresholdTime = _3ewg->ReadUint16();
4461 _3ewg->ReadInt16();
4462 ReleaseTime = _3ewg->ReadUint16();
4463 _3ewg->ReadInt16();
4464 KeyRange.low = _3ewg->ReadUint8();
4465 KeyRange.high = _3ewg->ReadUint8();
4466 _3ewg->SetPos(64);
4467 ReleaseTriggerKey = _3ewg->ReadUint8();
4468 AltSustain1Key = _3ewg->ReadUint8();
4469 AltSustain2Key = _3ewg->ReadUint8();
4470 }
4471
4472 MidiRuleLegato::MidiRuleLegato() :
4473 LegatoSamples(12),
4474 BypassUseController(false),
4475 BypassKey(0),
4476 BypassController(1),
4477 ThresholdTime(20),
4478 ReleaseTime(20),
4479 ReleaseTriggerKey(0),
4480 AltSustain1Key(0),
4481 AltSustain2Key(0)
4482 {
4483 KeyRange.low = KeyRange.high = 0;
4484 }
4485
4486 void MidiRuleLegato::UpdateChunks(uint8_t* pData) const {
4487 pData[32] = 0;
4488 pData[33] = 16;
4489 pData[36] = LegatoSamples;
4490 pData[40] = BypassUseController;
4491 pData[41] = BypassKey;
4492 pData[42] = BypassController;
4493 store16(&pData[43], ThresholdTime);
4494 store16(&pData[47], ReleaseTime);
4495 pData[51] = KeyRange.low;
4496 pData[52] = KeyRange.high;
4497 pData[64] = ReleaseTriggerKey;
4498 pData[65] = AltSustain1Key;
4499 pData[66] = AltSustain2Key;
4500 }
4501
4502 MidiRuleAlternator::MidiRuleAlternator(RIFF::Chunk* _3ewg) {
4503 _3ewg->SetPos(36);
4504 Articulations = _3ewg->ReadUint8();
4505 int flags = _3ewg->ReadUint8();
4506 Polyphonic = flags & 8;
4507 Chained = flags & 4;
4508 Selector = (flags & 2) ? selector_controller :
4509 (flags & 1) ? selector_key_switch : selector_none;
4510 Patterns = _3ewg->ReadUint8();
4511 _3ewg->ReadUint8(); // chosen row
4512 _3ewg->ReadUint8(); // unknown
4513 _3ewg->ReadUint8(); // unknown
4514 _3ewg->ReadUint8(); // unknown
4515 KeySwitchRange.low = _3ewg->ReadUint8();
4516 KeySwitchRange.high = _3ewg->ReadUint8();
4517 Controller = _3ewg->ReadUint8();
4518 PlayRange.low = _3ewg->ReadUint8();
4519 PlayRange.high = _3ewg->ReadUint8();
4520
4521 int n = std::min(int(Articulations), 32);
4522 for (int i = 0 ; i < n ; i++) {
4523 _3ewg->ReadString(pArticulations[i], 32);
4524 }
4525 _3ewg->SetPos(1072);
4526 n = std::min(int(Patterns), 32);
4527 for (int i = 0 ; i < n ; i++) {
4528 _3ewg->ReadString(pPatterns[i].Name, 16);
4529 pPatterns[i].Size = _3ewg->ReadUint8();
4530 _3ewg->Read(&pPatterns[i][0], 1, 32);
4531 }
4532 }
4533
4534 MidiRuleAlternator::MidiRuleAlternator() :
4535 Articulations(0),
4536 Patterns(0),
4537 Selector(selector_none),
4538 Controller(0),
4539 Polyphonic(false),
4540 Chained(false)
4541 {
4542 PlayRange.low = PlayRange.high = 0;
4543 KeySwitchRange.low = KeySwitchRange.high = 0;
4544 }
4545
4546 void MidiRuleAlternator::UpdateChunks(uint8_t* pData) const {
4547 pData[32] = 3;
4548 pData[33] = 16;
4549 pData[36] = Articulations;
4550 pData[37] = (Polyphonic ? 8 : 0) | (Chained ? 4 : 0) |
4551 (Selector == selector_controller ? 2 :
4552 (Selector == selector_key_switch ? 1 : 0));
4553 pData[38] = Patterns;
4554
4555 pData[43] = KeySwitchRange.low;
4556 pData[44] = KeySwitchRange.high;
4557 pData[45] = Controller;
4558 pData[46] = PlayRange.low;
4559 pData[47] = PlayRange.high;
4560
4561 char* str = reinterpret_cast<char*>(pData);
4562 int pos = 48;
4563 int n = std::min(int(Articulations), 32);
4564 for (int i = 0 ; i < n ; i++, pos += 32) {
4565 strncpy(&str[pos], pArticulations[i].c_str(), 32);
4566 }
4567
4568 pos = 1072;
4569 n = std::min(int(Patterns), 32);
4570 for (int i = 0 ; i < n ; i++, pos += 49) {
4571 strncpy(&str[pos], pPatterns[i].Name.c_str(), 16);
4572 pData[pos + 16] = pPatterns[i].Size;
4573 memcpy(&pData[pos + 16], &(pPatterns[i][0]), 32);
4574 }
4575 }
4576
4577 // *************** Script ***************
4578 // *
4579
4580 Script::Script(ScriptGroup* group, RIFF::Chunk* ckScri) {
4581 pGroup = group;
4582 pChunk = ckScri;
4583 if (ckScri) { // object is loaded from file ...
4584 ckScri->SetPos(0);
4585
4586 // read header
4587 uint32_t headerSize = ckScri->ReadUint32();
4588 Compression = (Compression_t) ckScri->ReadUint32();
4589 Encoding = (Encoding_t) ckScri->ReadUint32();
4590 Language = (Language_t) ckScri->ReadUint32();
4591 Bypass = ckScri->ReadUint32() & 1;
4592 crc = ckScri->ReadUint32();
4593 uint32_t nameSize = ckScri->ReadUint32();
4594 Name.resize(nameSize, ' ');
4595 for (int i = 0; i < nameSize; ++i)
4596 Name[i] = ckScri->ReadUint8();
4597 // check if an uuid was already stored along with this script
4598 if (headerSize >= 6*sizeof(int32_t) + nameSize + 16) { // yes ...
4599 for (uint i = 0; i < 16; ++i) {
4600 Uuid[i] = ckScri->ReadUint8();
4601 }
4602 } else { // no uuid yet, generate one now ...
4603 GenerateUuid();
4604 }
4605 // to handle potential future extensions of the header
4606 ckScri->SetPos(sizeof(int32_t) + headerSize);
4607 // read actual script data
4608 uint32_t scriptSize = uint32_t(ckScri->GetSize() - ckScri->GetPos());
4609 data.resize(scriptSize);
4610 for (int i = 0; i < scriptSize; ++i)
4611 data[i] = ckScri->ReadUint8();
4612 } else { // this is a new script object, so just initialize it as such ...
4613 Compression = COMPRESSION_NONE;
4614 Encoding = ENCODING_ASCII;
4615 Language = LANGUAGE_NKSP;
4616 Bypass = false;
4617 crc = 0;
4618 Name = "Unnamed Script";
4619 GenerateUuid();
4620 }
4621 }
4622
4623 Script::~Script() {
4624 }
4625
4626 /**
4627 * Returns the current script (i.e. as source code) in text format.
4628 */
4629 String Script::GetScriptAsText() {
4630 String s;
4631 s.resize(data.size(), ' ');
4632 memcpy(&s[0], &data[0], data.size());
4633 return s;
4634 }
4635
4636 /**
4637 * Replaces the current script with the new script source code text given
4638 * by @a text.
4639 *
4640 * @param text - new script source code
4641 */
4642 void Script::SetScriptAsText(const String& text) {
4643 data.resize(text.size());
4644 memcpy(&data[0], &text[0], text.size());
4645 }
4646
4647 /** @brief Remove all RIFF chunks associated with this Script object.
4648 *
4649 * At the moment Script::DeleteChunks() does nothing. It is
4650 * recommended to call this method explicitly though from deriving classes's
4651 * own overridden implementation of this method to avoid potential future
4652 * compatiblity issues.
4653 *
4654 * See DLS::Storage::DeleteChunks() for details.
4655 */
4656 void Script::DeleteChunks() {
4657 }
4658
4659 /**
4660 * Apply this script to the respective RIFF chunks. You have to call
4661 * File::Save() to make changes persistent.
4662 *
4663 * Usually there is absolutely no need to call this method explicitly.
4664 * It will be called automatically when File::Save() was called.
4665 *
4666 * @param pProgress - callback function for progress notification
4667 */
4668 void Script::UpdateChunks(progress_t* pProgress) {
4669 // recalculate CRC32 check sum
4670 __resetCRC(crc);
4671 __calculateCRC(&data[0], data.size(), crc);
4672 __finalizeCRC(crc);
4673 // make sure chunk exists and has the required size
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);
4678 // fill the chunk data to be written to disk
4679 uint8_t* pData = (uint8_t*) pChunk->LoadChunkData();
4680 int pos = 0;
4681 store32(&pData[pos], uint32_t(6*sizeof(int32_t) + Name.size() + 16)); // total header size
4682 pos += sizeof(int32_t);
4683 store32(&pData[pos], Compression);
4684 pos += sizeof(int32_t);
4685 store32(&pData[pos], Encoding);
4686 pos += sizeof(int32_t);
4687 store32(&pData[pos], Language);
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];
4701 }
4702
4703 /**
4704 * Generate a new Universally Unique Identifier (UUID) for this script.
4705 */
4706 void Script::GenerateUuid() {
4707 DLS::dlsid_t dlsid;
4708 DLS::Resource::GenerateDLSID(&dlsid);
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];
4725 }
4726
4727 /**
4728 * Move this script from its current ScriptGroup to another ScriptGroup
4729 * given by @a pGroup.
4730 *
4731 * @param pGroup - script's new group
4732 */
4733 void Script::SetGroup(ScriptGroup* pGroup) {
4734 if (this->pGroup == pGroup) return;
4735 if (pChunk)
4736 pChunk->GetParent()->MoveSubChunk(pChunk, pGroup->pList);
4737 this->pGroup = pGroup;
4738 }
4739
4740 /**
4741 * Returns the script group this script currently belongs to. Each script
4742 * is a member of exactly one ScriptGroup.
4743 *
4744 * @returns current script group
4745 */
4746 ScriptGroup* Script::GetGroup() const {
4747 return pGroup;
4748 }
4749
4750 /**
4751 * Make a (semi) deep copy of the Script object given by @a orig
4752 * and assign it to this object. Note: the ScriptGroup this Script
4753 * object belongs to remains untouched by this call.
4754 *
4755 * @param orig - original Script object to be copied from
4756 */
4757 void Script::CopyAssign(const Script* orig) {
4758 Name = orig->Name;
4759 Compression = orig->Compression;
4760 Encoding = orig->Encoding;
4761 Language = orig->Language;
4762 Bypass = orig->Bypass;
4763 data = orig->data;
4764 }
4765
4766 void Script::RemoveAllScriptReferences() {
4767 File* pFile = pGroup->pFile;
4768 for (int i = 0; pFile->GetInstrument(i); ++i) {
4769 Instrument* instr = pFile->GetInstrument(i);
4770 instr->RemoveScript(this);
4771 }
4772 }
4773
4774 // *************** ScriptGroup ***************
4775 // *
4776
4777 ScriptGroup::ScriptGroup(File* file, RIFF::List* lstRTIS) {
4778 pFile = file;
4779 pList = lstRTIS;
4780 pScripts = NULL;
4781 if (lstRTIS) {
4782 RIFF::Chunk* ckName = lstRTIS->GetSubChunk(CHUNK_ID_LSNM);
4783 ::LoadString(ckName, Name);
4784 } else {
4785 Name = "Default Group";
4786 }
4787 }
4788
4789 ScriptGroup::~ScriptGroup() {
4790 if (pScripts) {
4791 std::list<Script*>::iterator iter = pScripts->begin();
4792 std::list<Script*>::iterator end = pScripts->end();
4793 while (iter != end) {
4794 delete *iter;
4795 ++iter;
4796 }
4797 delete pScripts;
4798 }
4799 }
4800
4801 /** @brief Remove all RIFF chunks associated with this ScriptGroup object.
4802 *
4803 * At the moment ScriptGroup::DeleteChunks() does nothing. It is
4804 * recommended to call this method explicitly though from deriving classes's
4805 * own overridden implementation of this method to avoid potential future
4806 * compatiblity issues.
4807 *
4808 * See DLS::Storage::DeleteChunks() for details.
4809 */
4810 void ScriptGroup::DeleteChunks() {
4811 }
4812
4813 /**
4814 * Apply this script group to the respective RIFF chunks. You have to call
4815 * File::Save() to make changes persistent.
4816 *
4817 * Usually there is absolutely no need to call this method explicitly.
4818 * It will be called automatically when File::Save() was called.
4819 *
4820 * @param pProgress - callback function for progress notification
4821 */
4822 void ScriptGroup::UpdateChunks(progress_t* pProgress) {
4823 if (pScripts) {
4824 if (!pList)
4825 pList = pFile->pRIFF->GetSubList(LIST_TYPE_3LS)->AddSubList(LIST_TYPE_RTIS);
4826
4827 // now store the name of this group as <LSNM> chunk as subchunk of the <RTIS> list chunk
4828 ::SaveString(CHUNK_ID_LSNM, NULL, pList, Name, String("Unnamed Group"), true, 64);
4829
4830 for (std::list<Script*>::iterator it = pScripts->begin();
4831 it != pScripts->end(); ++it)
4832 {
4833 (*it)->UpdateChunks(pProgress);
4834 }
4835 }
4836 }
4837
4838 /** @brief Get instrument script.
4839 *
4840 * Returns the real-time instrument script with the given index.
4841 *
4842 * @param index - number of the sought script (0..n)
4843 * @returns sought script or NULL if there's no such script
4844 */
4845 Script* ScriptGroup::GetScript(uint index) {
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;
4850 return NULL;
4851 }
4852
4853 /** @brief Add new instrument script.
4854 *
4855 * Adds a new real-time instrument script to the file. The script is not
4856 * actually used / executed unless it is referenced by an instrument to be
4857 * used. This is similar to samples, which you can add to a file, without
4858 * an instrument necessarily actually using it.
4859 *
4860 * You have to call Save() to make this persistent to the file.
4861 *
4862 * @return new empty script object
4863 */
4864 Script* ScriptGroup::AddScript() {
4865 if (!pScripts) LoadScripts();
4866 Script* pScript = new Script(this, NULL);
4867 pScripts->push_back(pScript);
4868 return pScript;
4869 }
4870
4871 /** @brief Delete an instrument script.
4872 *
4873 * This will delete the given real-time instrument script. References of
4874 * instruments that are using that script will be removed accordingly.
4875 *
4876 * You have to call Save() to make this persistent to the file.
4877 *
4878 * @param pScript - script to delete
4879 * @throws gig::Exception if given script could not be found
4880 */
4881 void ScriptGroup::DeleteScript(Script* 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)
4890 pScript->pChunk->GetParent()->DeleteSubChunk(pScript->pChunk);
4891 delete pScript;
4892 }
4893
4894 void ScriptGroup::LoadScripts() {
4895 if (pScripts) return;
4896 pScripts = new std::list<Script*>;
4897 if (!pList) return;
4898
4899 for (RIFF::Chunk* ck = pList->GetFirstSubChunk(); ck;
4900 ck = pList->GetNextSubChunk())
4901 {
4902 if (ck->GetChunkID() == CHUNK_ID_SCRI) {
4903 pScripts->push_back(new Script(this, ck));
4904 }
4905 }
4906 }
4907
4908 // *************** Instrument ***************
4909 // *
4910
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 },
4915 { 0, 0 }
4916 };
4917 pInfo->SetFixedStringLengths(fixedStringLengths);
4918
4919 // Initialization
4920 for (int i = 0; i < 128; i++) RegionKeyTable[i] = NULL;
4921 EffectSend = 0;
4922 Attenuation = 0;
4923 FineTune = 0;
4924 PitchbendRange = 2;
4925 PianoReleaseMode = false;
4926 DimensionKeyRange.low = 0;
4927 DimensionKeyRange.high = 0;
4928 pMidiRules = new MidiRule*[3];
4929 pMidiRules[0] = NULL;
4930 pScriptRefs = NULL;
4931
4932 // Loading
4933 RIFF::List* lart = insList->GetSubList(LIST_TYPE_LART);
4934 if (lart) {
4935 RIFF::Chunk* _3ewg = lart->GetSubChunk(CHUNK_ID_3EWG);
4936 if (_3ewg) {
4937 _3ewg->SetPos(0);
4938
4939 EffectSend = _3ewg->ReadUint16();
4940 Attenuation = _3ewg->ReadInt32();
4941 FineTune = _3ewg->ReadInt16();
4942 PitchbendRange = _3ewg->ReadInt16();
4943 uint8_t dimkeystart = _3ewg->ReadUint8();
4944 PianoReleaseMode = dimkeystart & 0x01;
4945 DimensionKeyRange.low = dimkeystart >> 1;
4946 DimensionKeyRange.high = _3ewg->ReadUint8();
4947
4948 if (_3ewg->GetSize() > 32) {
4949 // read MIDI rules
4950 int i = 0;
4951 _3ewg->SetPos(32);
4952 uint8_t id1 = _3ewg->ReadUint8();
4953 uint8_t id2 = _3ewg->ReadUint8();
4954
4955 if (id2 == 16) {
4956 if (id1 == 4) {
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);
4962 } else {
4963 pMidiRules[i++] = new MidiRuleUnknown;
4964 }
4965 }
4966 else if (id1 != 0 || id2 != 0) {
4967 pMidiRules[i++] = new MidiRuleUnknown;
4968 }
4969 //TODO: all the other types of rules
4970
4971 pMidiRules[i] = NULL;
4972 }
4973 }
4974 }
4975
4976 if (pFile->GetAutoLoad()) {
4977 if (!pRegions) pRegions = new RegionList;
4978 RIFF::List* lrgn = insList->GetSubList(LIST_TYPE_LRGN);
4979 if (lrgn) {
4980 RIFF::List* rgn = lrgn->GetFirstSubList();
4981 while (rgn) {
4982 if (rgn->GetListType() == LIST_TYPE_RGN) {
4983 if (pProgress)
4984 __notify_progress(pProgress, (float) pRegions->size() / (float) Regions);
4985 pRegions->push_back(new Region(this, rgn));
4986 }
4987 rgn = lrgn->GetNextSubList();
4988 }
4989 // Creating Region Key Table for fast lookup
4990 UpdateRegionKeyTable();
4991 }
4992 }
4993
4994 // own gig format extensions
4995 RIFF::List* lst3LS = insList->GetSubList(LIST_TYPE_3LS);
4996 if (lst3LS) {
4997 // script slots (that is references to instrument scripts)
4998 RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL);
4999 if (ckSCSL) {
5000 ckSCSL->SetPos(0);
5001
5002 int headerSize = ckSCSL->ReadUint32();
5003 int slotCount = ckSCSL->ReadUint32();
5004 if (slotCount) {
5005 int slotSize = ckSCSL->ReadUint32();
5006 ckSCSL->SetPos(headerSize); // in case of future header extensions
5007 int unknownSpace = slotSize - 2*sizeof(uint32_t); // in case of future slot extensions
5008 for (int i = 0; i < slotCount; ++i) {
5009 _ScriptPooolEntry e;
5010 e.fileOffset = ckSCSL->ReadUint32();
5011 e.bypass = ckSCSL->ReadUint32() & 1;
5012 if (unknownSpace) ckSCSL->SetPos(unknownSpace, RIFF::stream_curpos); // in case of future extensions
5013 scriptPoolFileOffsets.push_back(e);
5014 }
5015 }
5016 }
5017
5018 // overridden script 'patch' variables
5019 RIFF::Chunk* ckSCPV = lst3LS->GetSubChunk(CHUNK_ID_SCPV);
5020 if (ckSCPV) {
5021 ckSCPV->SetPos(0);
5022
5023 int nScripts = ckSCPV->ReadUint32();
5024 for (int iScript = 0; iScript < nScripts; ++iScript) {
5025 _UUID uuid;
5026 for (int i = 0; i < 16; ++i)
5027 uuid[i] = ckSCPV->ReadUint8();
5028 uint slot = ckSCPV->ReadUint32();
5029 ckSCPV->ReadUint32(); // unused, reserved 32 bit
5030 int nVars = ckSCPV->ReadUint32();
5031 for (int iVar = 0; iVar < nVars; ++iVar) {
5032 uint8_t type = ckSCPV->ReadUint8();
5033 ckSCPV->ReadUint8(); // unused, reserved byte
5034 int blobSize = ckSCPV->ReadUint16();
5035 RIFF::file_offset_t pos = ckSCPV->GetPos();
5036 // assuming 1st bit is set in 'type', otherwise blob not
5037 // supported for decoding
5038 if (type & 1) {
5039 String name, value;
5040 int len = ckSCPV->ReadUint16();
5041 for (int i = 0; i < len; ++i)
5042 name += (char) ckSCPV->ReadUint8();
5043 len = ckSCPV->ReadUint16();
5044 for (int i = 0; i < len; ++i)
5045 value += (char) ckSCPV->ReadUint8();
5046 if (!name.empty()) // 'name' should never be empty, but just to be sure
5047 scriptVars[uuid][slot][name] = value;
5048 }
5049 // also for potential future extensions: seek forward
5050 // according to blob size
5051 ckSCPV->SetPos(pos + blobSize);
5052 }
5053 }
5054 }
5055 }
5056
5057 if (pProgress)
5058 __notify_progress(pProgress, 1.0f); // notify done
5059 }
5060
5061 void Instrument::UpdateRegionKeyTable() {
5062 for (int i = 0; i < 128; i++) RegionKeyTable[i] = NULL;
5063 RegionList::iterator iter = pRegions->begin();
5064 RegionList::iterator end = pRegions->end();
5065 for (; iter != end; ++iter) {
5066 gig::Region* pRegion = static_cast<gig::Region*>(*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++) {
5070 RegionKeyTable[iKey] = pRegion;
5071 }
5072 }
5073 }
5074
5075 Instrument::~Instrument() {
5076 for (int i = 0 ; pMidiRules[i] ; i++) {
5077 delete pMidiRules[i];
5078 }
5079 delete[] pMidiRules;
5080 if (pScriptRefs) delete pScriptRefs;
5081 }
5082
5083 /**
5084 * Apply Instrument with all its Regions to the respective RIFF chunks.
5085 * You have to call File::Save() to make changes persistent.
5086 *
5087 * Usually there is absolutely no need to call this method explicitly.
5088 * It will be called automatically when File::Save() was called.
5089 *
5090 * @param pProgress - callback function for progress notification
5091 * @throws gig::Exception if samples cannot be dereferenced
5092 */
5093 void Instrument::UpdateChunks(progress_t* pProgress) {
5094 // first update base classes' chunks
5095 DLS::Instrument::UpdateChunks(pProgress);
5096
5097 // update Regions' chunks
5098 {
5099 RegionList::iterator iter = pRegions->begin();
5100 RegionList::iterator end = pRegions->end();
5101 for (; iter != end; ++iter)
5102 (*iter)->UpdateChunks(pProgress);
5103 }
5104
5105 // make sure 'lart' RIFF list chunk exists
5106 RIFF::List* lart = pCkInstrument->GetSubList(LIST_TYPE_LART);
5107 if (!lart) lart = pCkInstrument->AddSubList(LIST_TYPE_LART);
5108 // make sure '3ewg' RIFF chunk exists
5109 RIFF::Chunk* _3ewg = lart->GetSubChunk(CHUNK_ID_3EWG);
5110 if (!_3ewg) {
5111 File* pFile = (File*) GetParent();
5112
5113 // 3ewg is bigger in gig3, as it includes the iMIDI rules
5114 int size = (pFile->pVersion && pFile->pVersion->major > 2) ? 16416 : 12;
5115 _3ewg = lart->AddSubChunk(CHUNK_ID_3EWG, size);
5116 memset(_3ewg->LoadChunkData(), 0, size);
5117 }
5118 // update '3ewg' RIFF chunk
5119 uint8_t* pData = (uint8_t*) _3ewg->LoadChunkData();
5120 store16(&pData[0], EffectSend);
5121 store32(&pData[2], Attenuation);
5122 store16(&pData[6], FineTune);
5123 store16(&pData[8], PitchbendRange);
5124 const uint8_t dimkeystart = (PianoReleaseMode ? 0x01 : 0x00) |
5125 DimensionKeyRange.low << 1;
5126 pData[10] = dimkeystart;
5127 pData[11] = DimensionKeyRange.high;
5128
5129 if (pMidiRules[0] == 0 && _3ewg->GetSize() >= 34) {
5130 pData[32] = 0;
5131 pData[33] = 0;
5132 } else {
5133 for (int i = 0 ; pMidiRules[i] ; i++) {
5134 pMidiRules[i]->UpdateChunks(pData);
5135 }
5136 }
5137
5138 // own gig format extensions
5139 if (ScriptSlotCount()) {
5140 // make sure we have converted the original loaded script file
5141 // offsets into valid Script object pointers
5142 LoadScripts();
5143
5144 RIFF::List* lst3LS = pCkInstrument->GetSubList(LIST_TYPE_3LS);
5145 if (!lst3LS) lst3LS = pCkInstrument->AddSubList(LIST_TYPE_3LS);
5146
5147 // save script slots (that is references to instrument scripts)
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;
5152 RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL);
5153 if (!ckSCSL) ckSCSL = lst3LS->AddSubChunk(CHUNK_ID_SCSL, totalChunkSize);
5154 else ckSCSL->Resize(totalChunkSize);
5155 uint8_t* pData = (uint8_t*) ckSCSL->LoadChunkData();
5156 int pos = 0;
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) {
5164 // arbitrary value, the actual file offset will be updated in
5165 // UpdateScriptFileOffsets() after the file has been resized
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);
5171 }
5172
5173 // save overridden script 'patch' variables ...
5174
5175 // the actual 'scriptVars' member variable might contain variables of
5176 // scripts which are currently no longer assigned to any script slot
5177 // of this instrument, we need to get rid of these variables here to
5178 // prevent saving those persistently, however instead of touching the
5179 // member variable 'scriptVars' directly, rather strip a separate
5180 // copy such that the overridden values are not lost during an
5181 // instrument editor session (i.e. if script might be re-assigned)
5182 _VarsByScript vars = stripScriptVars();
5183 if (!vars.empty()) {
5184 // determine total size required for 'SCPV' RIFF chunk, and the
5185 // total amount of scripts being overridden (the latter is
5186 // required because a script might be used on several script
5187 // slots, hence vars.size() could then not be used here instead)
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();
5197 }
5198 }
5199 }
5200
5201 // ensure 'SCPV' RIFF chunk exists (with required size)
5202 RIFF::Chunk* ckSCPV = lst3LS->GetSubChunk(CHUNK_ID_SCPV);
5203 if (!ckSCPV) ckSCPV = lst3LS->AddSubChunk(CHUNK_ID_SCPV, totalChunkSize);
5204 else ckSCPV->Resize(totalChunkSize);
5205
5206 // store the actual data to 'SCPV' RIFF chunk
5207 uint8_t* pData = (uint8_t*) ckSCPV->LoadChunkData();
5208 int pos = 0;
5209 store32(&pData[pos], (uint32_t) totalScriptsOverridden); // scripts count
5210 pos += 4;
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]; // uuid
5215 pos += 16;
5216 store32(&pData[pos], (uint32_t) slot.first); // slot index
5217 pos += 4;
5218 store32(&pData[pos], (uint32_t) 0); // unused, reserved 32 bit
5219 pos += 4;
5220 store32(&pData[pos], (uint32_t) slot.second.size()); // variables count
5221 pos += 4;
5222 for (const auto& var : slot.second) {
5223 pData[pos++] = 1; // type
5224 pData[pos++] = 0; // reserved byte
5225 store16(&pData[pos], 2 + var.first.size() + 2 + var.second.size()); // blob size
5226 pos += 2;
5227 store16(&pData[pos], var.first.size()); // variable name length
5228 pos += 2;
5229 for (int i = 0; i < var.first.size(); ++i)
5230 pData[pos++] = var.first[i];
5231 store16(&pData[pos], var.second.size()); // variable value length
5232 pos += 2;
5233 for (int i = 0; i < var.second.size(); ++i)
5234 pData[pos++] = var.second[i];
5235 }
5236 }
5237 }
5238 } else {
5239 // no script variable overridden by this instrument, so get rid
5240 // of 'SCPV' RIFF chunk (if any)
5241 RIFF::Chunk* ckSCPV = lst3LS->GetSubChunk(CHUNK_ID_SCPV);
5242 if (ckSCPV) lst3LS->DeleteSubChunk(ckSCPV);
5243 }
5244 } else {
5245 // no script slots, so get rid of any LS custom RIFF chunks (if any)
5246 RIFF::List* lst3LS = pCkInstrument->GetSubList(LIST_TYPE_3LS);
5247 if (lst3LS) pCkInstrument->DeleteSubChunk(lst3LS);
5248 }
5249 }
5250
5251 void Instrument::UpdateScriptFileOffsets() {
5252 // own gig format extensions
5253 if (pScriptRefs && pScriptRefs->size() > 0) {
5254 RIFF::List* lst3LS = pCkInstrument->GetSubList(LIST_TYPE_3LS);
5255 RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL);
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() -
5263 CHUNK_HEADER_SIZE(ckSCSL->GetFile()->GetFileOffsetSize())
5264 );
5265 ckSCSL->WriteUint32(&fileOffset);
5266 // jump over flags entry (containing the bypass flag)
5267 ckSCSL->SetPos(sizeof(uint32_t), RIFF::stream_curpos);
5268 }
5269 }
5270 }
5271
5272 /**
5273 * Returns the appropriate Region for a triggered note.
5274 *
5275 * @param Key MIDI Key number of triggered note / key (0 - 127)
5276 * @returns pointer adress to the appropriate Region or NULL if there
5277 * there is no Region defined for the given \a Key
5278 */
5279 Region* Instrument::GetRegion(unsigned int Key) {
5280 if (!pRegions || pRegions->empty() || Key > 127) return NULL;
5281 return RegionKeyTable[Key];
5282
5283 /*for (int i = 0; i < Regions; i++) {
5284 if (Key <= pRegions[i]->KeyRange.high &&
5285 Key >= pRegions[i]->KeyRange.low) return pRegions[i];
5286 }
5287 return NULL;*/
5288 }
5289
5290 /**
5291 * Returns the first Region of the instrument. You have to call this
5292 * method once before you use GetNextRegion().
5293 *
5294 * @returns pointer address to first region or NULL if there is none
5295 * @see GetNextRegion()
5296 */
5297 Region* Instrument::GetFirstRegion() {
5298 if (!pRegions) return NULL;
5299 RegionsIterator = pRegions->begin();
5300 return static_cast<gig::Region*>( (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL );
5301 }
5302
5303 /**
5304 * Returns the next Region of the instrument. You have to call
5305 * GetFirstRegion() once before you can use this method. By calling this
5306 * method multiple times it iterates through the available Regions.
5307 *
5308 * @returns pointer address to the next region or NULL if end reached
5309 * @see GetFirstRegion()
5310 */
5311 Region* Instrument::GetNextRegion() {
5312 if (!pRegions) return NULL;
5313 RegionsIterator++;
5314 return static_cast<gig::Region*>( (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL );
5315 }
5316
5317 Region* Instrument::AddRegion() {
5318 // create new Region object (and its RIFF chunks)
5319 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
5320 if (!lrgn) lrgn = pCkInstrument->AddSubList(LIST_TYPE_LRGN);
5321 RIFF::List* rgn = lrgn->AddSubList(LIST_TYPE_RGN);
5322 Region* pNewRegion = new Region(this, rgn);
5323 pRegions->push_back(pNewRegion);
5324 Regions = (uint32_t) pRegions->size();
5325 // update Region key table for fast lookup
5326 UpdateRegionKeyTable();
5327 // done
5328 return pNewRegion;
5329 }
5330
5331 void Instrument::DeleteRegion(Region* pRegion) {
5332 if (!pRegions) return;
5333 DLS::Instrument::DeleteRegion((DLS::Region*) pRegion);
5334 // update Region key table for fast lookup
5335 UpdateRegionKeyTable();
5336 }
5337
5338 /**
5339 * Move this instrument at the position before @arg dst.
5340 *
5341 * This method can be used to reorder the sequence of instruments in a
5342 * .gig file. This might be helpful especially on large .gig files which
5343 * contain a large number of instruments within the same .gig file. So
5344 * grouping such instruments to similar ones, can help to keep track of them
5345 * when working with such complex .gig files.
5346 *
5347 * When calling this method, this instrument will be removed from in its
5348 * current position in the instruments list and moved to the requested
5349 * target position provided by @param dst. You may also pass NULL as
5350 * argument to this method, in that case this intrument will be moved to the
5351 * very end of the .gig file's instrument list.
5352 *
5353 * You have to call Save() to make the order change persistent to the .gig
5354 * file.
5355 *
5356 * Currently this method is limited to moving the instrument within the same
5357 * .gig file. Trying to move it to another .gig file by calling this method
5358 * will throw an exception.
5359 *
5360 * @param dst - destination instrument at which this instrument will be
5361 * moved to, or pass NULL for moving to end of list
5362 * @throw gig::Exception if this instrument and target instrument are not
5363 * part of the same file
5364 */
5365 void Instrument::MoveTo(Instrument* dst) {
5366 if (dst && GetParent() != dst->GetParent())
5367 throw Exception(
5368 "gig::Instrument::MoveTo() can only be used for moving within "
5369 "the same gig file."
5370 );
5371
5372 File* pFile = (File*) GetParent();
5373
5374 // move this instrument within the instrument list
5375 {
5376 File::InstrumentList& list = *pFile->pInstruments;
5377
5378 File::InstrumentList::iterator itFrom =
5379 std::find(list.begin(), list.end(), static_cast<DLS::Instrument*>(this));
5380
5381 File::InstrumentList::iterator itTo =
5382 std::find(list.begin(), list.end(), static_cast<DLS::Instrument*>(dst));
5383
5384 list.splice(itTo, list, itFrom);
5385 }
5386
5387 // move the instrument's actual list RIFF chunk appropriately
5388 RIFF::List* lstCkInstruments = pFile->pRIFF->GetSubList(LIST_TYPE_LINS);
5389 lstCkInstruments->MoveSubChunk(
5390 this->pCkInstrument,
5391 (RIFF::Chunk*) ((dst) ? dst->pCkInstrument : NULL)
5392 );
5393 }
5394
5395 /**
5396 * Returns a MIDI rule of the instrument.
5397 *
5398 * The list of MIDI rules, at least in gig v3, always contains at
5399 * most two rules. The second rule can only be the DEF filter
5400 * (which currently isn't supported by libgig).
5401 *
5402 * @param i - MIDI rule number
5403 * @returns pointer address to MIDI rule number i or NULL if there is none
5404 */
5405 MidiRule* Instrument::GetMidiRule(int i) {
5406 return pMidiRules[i];
5407 }
5408
5409 /**
5410 * Adds the "controller trigger" MIDI rule to the instrument.
5411 *
5412 * @returns the new MIDI rule
5413 */
5414 MidiRuleCtrlTrigger* Instrument::AddMidiRuleCtrlTrigger() {
5415 delete pMidiRules[0];
5416 MidiRuleCtrlTrigger* r = new MidiRuleCtrlTrigger;
5417 pMidiRules[0] = r;
5418 pMidiRules[1] = 0;
5419 return r;
5420 }
5421
5422 /**
5423 * Adds the legato MIDI rule to the instrument.
5424 *
5425 * @returns the new MIDI rule
5426 */
5427 MidiRuleLegato* Instrument::AddMidiRuleLegato() {
5428 delete pMidiRules[0];
5429 MidiRuleLegato* r = new MidiRuleLegato;
5430 pMidiRules[0] = r;
5431 pMidiRules[1] = 0;
5432 return r;
5433 }
5434
5435 /**
5436 * Adds the alternator MIDI rule to the instrument.
5437 *
5438 * @returns the new MIDI rule
5439 */
5440 MidiRuleAlternator* Instrument::AddMidiRuleAlternator() {
5441 delete pMidiRules[0];
5442 MidiRuleAlternator* r = new MidiRuleAlternator;
5443 pMidiRules[0] = r;
5444 pMidiRules[1] = 0;
5445 return r;
5446 }
5447
5448 /**
5449 * Deletes a MIDI rule from the instrument.
5450 *
5451 * @param i - MIDI rule number
5452 */
5453 void Instrument::DeleteMidiRule(int i) {
5454 delete pMidiRules[i];
5455 pMidiRules[i] = 0;
5456 }
5457
5458 void Instrument::LoadScripts() {
5459 if (pScriptRefs) return;
5460 pScriptRefs = new std::vector<_ScriptPooolRef>;
5461 if (scriptPoolFileOffsets.empty()) return;
5462 File* pFile = (File*) GetParent();
5463 for (uint k = 0; k < scriptPoolFileOffsets.size(); ++k) {
5464 uint32_t soughtOffset = scriptPoolFileOffsets[k].fileOffset;
5465 for (uint i = 0; pFile->GetScriptGroup(i); ++i) {
5466 ScriptGroup* group = pFile->GetScriptGroup(i);
5467 for (uint s = 0; group->GetScript(s); ++s) {
5468 Script* script = group->GetScript(s);
5469 if (script->pChunk) {
5470 uint32_t offset = uint32_t(
5471 script->pChunk->GetFilePos() -
5472 script->pChunk->GetPos() -
5473 CHUNK_HEADER_SIZE(script->pChunk->GetFile()->GetFileOffsetSize())
5474 );
5475 if (offset == soughtOffset)
5476 {
5477 _ScriptPooolRef ref;
5478 ref.script = script;
5479 ref.bypass = scriptPoolFileOffsets[k].bypass;
5480 pScriptRefs->push_back(ref);
5481 break;
5482 }
5483 }
5484 }
5485 }
5486 }
5487 // we don't need that anymore
5488 scriptPoolFileOffsets.clear();
5489 }
5490
5491 /** @brief Get instrument script (gig format extension).
5492 *
5493 * Returns the real-time instrument script of instrument script slot
5494 * @a index.
5495 *
5496 * @note This is an own format extension which did not exist i.e. in the
5497 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5498 * gigedit.
5499 *
5500 * @param index - instrument script slot index
5501 * @returns script or NULL if index is out of bounds
5502 */
5503 Script* Instrument::GetScriptOfSlot(uint index) {
5504 LoadScripts();
5505 if (index >= pScriptRefs->size()) return NULL;
5506 return pScriptRefs->at(index).script;
5507 }
5508
5509 /** @brief Add new instrument script slot (gig format extension).
5510 *
5511 * Add the given real-time instrument script reference to this instrument,
5512 * which shall be executed by the sampler for for this instrument. The
5513 * script will be added to the end of the script list of this instrument.
5514 * The positions of the scripts in the Instrument's Script list are
5515 * relevant, because they define in which order they shall be executed by
5516 * the sampler. For this reason it is also legal to add the same script
5517 * twice to an instrument, for example you might have a script called
5518 * "MyFilter" which performs an event filter task, and you might have
5519 * another script called "MyNoteTrigger" which triggers new notes, then you
5520 * might for example have the following list of scripts on the instrument:
5521 *
5522 * 1. Script "MyFilter"
5523 * 2. Script "MyNoteTrigger"
5524 * 3. Script "MyFilter"
5525 *
5526 * Which would make sense, because the 2nd script launched new events, which
5527 * you might need to filter as well.
5528 *
5529 * There are two ways to disable / "bypass" scripts. You can either disable
5530 * a script locally for the respective script slot on an instrument (i.e. by
5531 * passing @c false to the 2nd argument of this method, or by calling
5532 * SetScriptBypassed()). Or you can disable a script globally for all slots
5533 * and all instruments by setting Script::Bypass.
5534 *
5535 * @note This is an own format extension which did not exist i.e. in the
5536 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5537 * gigedit.
5538 *
5539 * @param pScript - script that shall be executed for this instrument
5540 * @param bypass - if enabled, the sampler shall skip executing this
5541 * script (in the respective list position)
5542 * @see SetScriptBypassed()
5543 */
5544 void Instrument::AddScriptSlot(Script* pScript, bool bypass) {
5545 LoadScripts();
5546 _ScriptPooolRef ref = { pScript, bypass };
5547 pScriptRefs->push_back(ref);
5548 }
5549
5550 /** @brief Flip two script slots with each other (gig format extension).
5551 *
5552 * Swaps the position of the two given scripts in the Instrument's Script
5553 * list. The positions of the scripts in the Instrument's Script list are
5554 * relevant, because they define in which order they shall be executed by
5555 * the sampler.
5556 *
5557 * @note This is an own format extension which did not exist i.e. in the
5558 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5559 * gigedit.
5560 *
5561 * @param index1 - index of the first script slot to swap
5562 * @param index2 - index of the second script slot to swap
5563 */
5564 void Instrument::SwapScriptSlots(uint index1, uint index2) {
5565 LoadScripts();
5566 if (index1 >= pScriptRefs->size() || index2 >= pScriptRefs->size())
5567 return;
5568 _ScriptPooolRef tmp = (*pScriptRefs)[index1];
5569 (*pScriptRefs)[index1] = (*pScriptRefs)[index2];
5570 (*pScriptRefs)[index2] = tmp;
5571 }
5572
5573 /** @brief Remove script slot.
5574 *
5575 * Removes the script slot with the given slot index.
5576 *
5577 * @param index - index of script slot to remove
5578 */
5579 void Instrument::RemoveScriptSlot(uint index) {
5580 LoadScripts();
5581 if (index >= pScriptRefs->size()) return;
5582 pScriptRefs->erase( pScriptRefs->begin() + index );
5583 }
5584
5585 /** @brief Remove reference to given Script (gig format extension).
5586 *
5587 * This will remove all script slots on the instrument which are referencing
5588 * the given script.
5589 *
5590 * @note This is an own format extension which did not exist i.e. in the
5591 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5592 * gigedit.
5593 *
5594 * @param pScript - script reference to remove from this instrument
5595 * @see RemoveScriptSlot()
5596 */
5597 void Instrument::RemoveScript(Script* pScript) {
5598 LoadScripts();
5599 for (ssize_t i = pScriptRefs->size() - 1; i >= 0; --i) {
5600 if ((*pScriptRefs)[i].script == pScript) {
5601 pScriptRefs->erase( pScriptRefs->begin() + i );
5602 }
5603 }
5604 }
5605
5606 /** @brief Instrument's amount of script slots.
5607 *
5608 * This method returns the amount of script slots this instrument currently
5609 * uses.
5610 *
5611 * A script slot is a reference of a real-time instrument script to be
5612 * executed by the sampler. The scripts will be executed by the sampler in
5613 * sequence of the slots. One (same) script may be referenced multiple
5614 * times in different slots.
5615 *
5616 * @note This is an own format extension which did not exist i.e. in the
5617 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5618 * gigedit.
5619 */
5620 uint Instrument::ScriptSlotCount() const {
5621 return uint(pScriptRefs ? pScriptRefs->size() : scriptPoolFileOffsets.size());
5622 }
5623
5624 /** @brief Whether script execution shall be skipped.
5625 *
5626 * Defines locally for the Script reference slot in the Instrument's Script
5627 * list, whether the script shall be skipped by the sampler regarding
5628 * execution.
5629 *
5630 * It is also possible to ignore exeuction of the script globally, for all
5631 * slots and for all instruments by setting Script::Bypass.
5632 *
5633 * @note This is an own format extension which did not exist i.e. in the
5634 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5635 * gigedit.
5636 *
5637 * @param index - index of the script slot on this instrument
5638 * @see Script::Bypass
5639 */
5640 bool Instrument::IsScriptSlotBypassed(uint index) {
5641 if (index >= ScriptSlotCount()) return false;
5642 return pScriptRefs ? pScriptRefs->at(index).bypass
5643 : scriptPoolFileOffsets.at(index).bypass;
5644
5645 }
5646
5647 /** @brief Defines whether execution shall be skipped.
5648 *
5649 * You can call this method to define locally whether or whether not the
5650 * given script slot shall be executed by the sampler.
5651 *
5652 * @note This is an own format extension which did not exist i.e. in the
5653 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5654 * gigedit.
5655 *
5656 * @param index - script slot index on this instrument
5657 * @param bBypass - if true, the script slot will be skipped by the sampler
5658 * @see Script::Bypass
5659 */
5660 void Instrument::SetScriptSlotBypassed(uint index, bool bBypass) {
5661 if (index >= ScriptSlotCount()) return;
5662 if (pScriptRefs)
5663 pScriptRefs->at(index).bypass = bBypass;
5664 else
5665 scriptPoolFileOffsets.at(index).bypass = bBypass;
5666 }
5667
5668 /// type cast (by copy) uint8_t[16] -> std::array<uint8_t,16>
5669 inline std::array<uint8_t,16> _UUIDFromCArray(const uint8_t* pData) {
5670 std::array<uint8_t,16> uuid;
5671 memcpy(&uuid[0], pData, 16);
5672 return uuid;
5673 }
5674
5675 /**
5676 * Returns true if this @c Instrument has any script slot which references
5677 * the @c Script identified by passed @p uuid.
5678 */
5679 bool Instrument::ReferencesScriptWithUuid(const _UUID& uuid) {
5680 const uint nSlots = ScriptSlotCount();
5681 for (uint iSlot = 0; iSlot < nSlots; ++iSlot)
5682 if (_UUIDFromCArray(&GetScriptOfSlot(iSlot)->Uuid[0]) == uuid)
5683 return true;
5684 return false;
5685 }
5686
5687 /** @brief Checks whether a certain script 'patch' variable value is set.
5688 *
5689 * Returns @c true if the initial value for the requested script variable is
5690 * currently overridden by this instrument.
5691 *
5692 * @remarks Real-time instrument scripts allow to declare special 'patch'
5693 * variables, which essentially behave like regular variables of their data
5694 * type, however their initial value may optionally be overridden on a per
5695 * instrument basis. That allows to share scripts between instruments while
5696 * still being able to fine tune certain aspects of the script for each
5697 * instrument individually.
5698 *
5699 * @note This is an own format extension which did not exist i.e. in the
5700 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5701 * Gigedit.
5702 *
5703 * @param slot - script slot index of the variable to be retrieved
5704 * @param variable - name of the 'patch' variable in that script
5705 */
5706 bool Instrument::IsScriptPatchVariableSet(int slot, String variable) {
5707 if (variable.empty()) return false;
5708 Script* script = GetScriptOfSlot(slot);
5709 if (!script) return false;
5710 const _UUID uuid = _UUIDFromCArray(&script->Uuid[0]);
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);
5716 else
5717 return slots.begin()->second.count(variable);
5718 }
5719
5720 /** @brief Get all overridden script 'patch' variables.
5721 *
5722 * Returns map of key-value pairs reflecting all patch variables currently
5723 * being overridden by this instrument for the given script @p slot, where
5724 * key is the variable name and value is the hereby currently overridden
5725 * value for that variable.
5726 *
5727 * @remarks Real-time instrument scripts allow to declare special 'patch'
5728 * variables, which essentially behave like regular variables of their data
5729 * type, however their initial value may optionally be overridden on a per
5730 * instrument basis. That allows to share scripts between instruments while
5731 * still being able to fine tune certain aspects of the script for each
5732 * instrument individually.
5733 *
5734 * @note This is an own format extension which did not exist i.e. in the
5735 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5736 * Gigedit.
5737 *
5738 * @param slot - script slot index of the variable to be retrieved
5739 */
5740 std::map<String,String> Instrument::GetScriptPatchVariables(int slot) {
5741 Script* script = GetScriptOfSlot(slot);
5742 if (!script) return std::map<String,String>();
5743 const _UUID uuid = _UUIDFromCArray(&script->Uuid[0]);
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;
5750 return vars;
5751 }
5752
5753 /** @brief Get overridden initial value for 'patch' variable.
5754 *
5755 * Returns current initial value for the requested script variable being
5756 * overridden by this instrument.
5757 *
5758 * @remarks Real-time instrument scripts allow to declare special 'patch'
5759 * variables, which essentially behave like regular variables of their data
5760 * type, however their initial value may optionally be overridden on a per
5761 * instrument basis. That allows to share scripts between instruments while
5762 * still being able to fine tune certain aspects of the script for each
5763 * instrument individually.
5764 *
5765 * @note This is an own format extension which did not exist i.e. in the
5766 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5767 * Gigedit.
5768 *
5769 * @param slot - script slot index of the variable to be retrieved
5770 * @param variable - name of the 'patch' variable in that script
5771 */
5772 String Instrument::GetScriptPatchVariable(int slot, String variable) {
5773 std::map<String,String> vars = GetScriptPatchVariables(slot);
5774 return (vars.count(variable)) ? vars.find(variable)->second : "";
5775 }
5776
5777 /** @brief Override initial value for 'patch' variable.
5778 *
5779 * Overrides initial value for the requested script variable for this
5780 * instrument with the passed value.
5781 *
5782 * @remarks Real-time instrument scripts allow to declare special 'patch'
5783 * variables, which essentially behave like regular variables of their data
5784 * type, however their initial value may optionally be overridden on a per
5785 * instrument basis. That allows to share scripts between instruments while
5786 * still being able to fine tune certain aspects of the script for each
5787 * instrument individually.
5788 *
5789 * @note This is an own format extension which did not exist i.e. in the
5790 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5791 * Gigedit.
5792 *
5793 * @param slot - script slot index of the variable to be set
5794 * @param variable - name of the 'patch' variable in that script
5795 * @param value - overridden initial value for that script variable
5796 * @throws gig::Exception if given script @p slot index is invalid or given
5797 * @p variable name is empty
5798 */
5799 void Instrument::SetScriptPatchVariable(int slot, String variable, String value) {
5800 if (variable.empty())
5801 throw Exception("Variable name must not be empty");
5802 Script* script = GetScriptOfSlot(slot);
5803 if (!script)
5804 throw Exception("No script slot with index " + ToString(slot));
5805 const _UUID uuid = _UUIDFromCArray(&script->Uuid[0]);
5806 scriptVars[uuid][slot][variable] = value;
5807 }
5808
5809 /** @brief Drop overridden initial value(s) for 'patch' variable(s).
5810 *
5811 * Reverts initial value(s) for requested script variable(s) back to their
5812 * default initial value(s) defined in the script itself.
5813 *
5814 * Both arguments of this method are optional. The most obvious use case of
5815 * this method would be passing a valid script @p slot index and a
5816 * (non-emtpy string as) @p variable name to this method, which would cause
5817 * that single variable to be unset for that specific script slot (on this
5818 * @c Instrument level).
5819 *
5820 * Not passing a value (or @c -1 for @p slot and/or empty string for
5821 * @p variable) means 'wildcard'. So accordingly absence of argument(s) will
5822 * cause all variables and/or for all script slots being unset. Hence this
5823 * method serves 2^2 = 4 possible use cases in total and accordingly covers
5824 * 4 different behaviours in one method.
5825 *
5826 * @remarks Real-time instrument scripts allow to declare special 'patch'
5827 * variables, which essentially behave like regular variables of their data
5828 * type, however their initial value may optionally be overridden on a per
5829 * instrument basis. That allows to share scripts between instruments while
5830 * still being able to fine tune certain aspects of the script for each
5831 * instrument individually.
5832 *
5833 * @note This is an own format extension which did not exist i.e. in the
5834 * GigaStudio 4 software. It will currently only work with LinuxSampler and
5835 * Gigedit.
5836 *
5837 * @param slot - script slot index of the variable to be unset
5838 * @param variable - name of the 'patch' variable in that script
5839 */
5840 void Instrument::UnsetScriptPatchVariable(int slot, String variable) {
5841 Script* script = GetScriptOfSlot(slot);
5842
5843 // option 1: unset a particular variable of one particular script slot
5844 if (slot != -1 && !variable.empty()) {
5845 if (!script) return;
5846 const _UUID uuid = _UUIDFromCArray(&script->Uuid[0]);
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)
5852 );
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) );
5857 return;
5858 }
5859
5860 // option 2: unset all variables of all script slots
5861 if (slot == -1 && variable.empty()) {
5862 scriptVars.clear();
5863 return;
5864 }
5865
5866 // option 3: unset all variables of one particular script slot only
5867 if (slot != -1) {
5868 if (!script) return;
5869 const _UUID uuid = _UUIDFromCArray(&script->Uuid[0]);
5870 if (scriptVars.count(uuid))
5871 scriptVars.erase( scriptVars.find(uuid) );
5872 return;
5873 }
5874
5875 // option 4: unset a particular variable of all script slots
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) );
5886 if (vars.empty())
5887 slots.erase(itSlot++); // postfix increment to avoid iterator invalidation
5888 else
5889 ++itSlot;
5890 }
5891 if (slots.empty())
5892 scriptVars.erase(itScript++); // postfix increment to avoid iterator invalidation
5893 else
5894 ++itScript;
5895 }
5896 }
5897
5898 /**
5899 * Returns stripped version of member variable @c scriptVars, where scripts
5900 * no longer referenced by this @c Instrument are filtered out, and so are
5901 * variables of meanwhile obsolete slots (i.e. a script still being
5902 * referenced, but previously overridden on a script slot which either no
5903 * longer exists or is hosting another script now).
5904 */
5905 Instrument::_VarsByScript Instrument::stripScriptVars() {
5906 _VarsByScript vars;
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))
5912 continue;
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) {
5917 Script* script = GetScriptOfSlot(itSlot->first);
5918 if (!script) continue;
5919 if (_UUIDFromCArray(&script->Uuid[0]) != uuid) continue;
5920 if (itSlot->second.empty()) continue;
5921 vars[uuid][itSlot->first] = itSlot->second;
5922 }
5923 }
5924 return vars;
5925 }
5926
5927 /**
5928 * Make a (semi) deep copy of the Instrument object given by @a orig
5929 * and assign it to this object.
5930 *
5931 * Note that all sample pointers referenced by @a orig are simply copied as
5932 * memory address. Thus the respective samples are shared, not duplicated!
5933 *
5934 * @param orig - original Instrument object to be copied from
5935 */
5936 void Instrument::CopyAssign(const Instrument* orig) {
5937 CopyAssign(orig, NULL);
5938 }
5939
5940 /**
5941 * Make a (semi) deep copy of the Instrument object given by @a orig
5942 * and assign it to this object.
5943 *
5944 * @param orig - original Instrument object to be copied from
5945 * @param mSamples - crosslink map between the foreign file's samples and
5946 * this file's samples
5947 */
5948 void Instrument::CopyAssign(const Instrument* orig, const std::map<Sample*,Sample*>* mSamples) {
5949 // handle base class
5950 // (without copying DLS region stuff)
5951 DLS::Instrument::CopyAssignCore(orig);
5952
5953 // handle own member variables
5954 Attenuation = orig->Attenuation;
5955 EffectSend = orig->EffectSend;
5956 FineTune = orig->FineTune;
5957 PitchbendRange = orig->PitchbendRange;
5958 PianoReleaseMode = orig->PianoReleaseMode;
5959 DimensionKeyRange = orig->DimensionKeyRange;
5960 scriptPoolFileOffsets = orig->scriptPoolFileOffsets;
5961 // deep copy of pScriptRefs required (to avoid undefined behaviour)
5962 if (pScriptRefs) delete pScriptRefs;
5963 pScriptRefs = new std::vector<_ScriptPooolRef>;
5964 if (orig->pScriptRefs)
5965 *pScriptRefs = *orig->pScriptRefs;
5966 scriptVars = orig->scriptVars;
5967
5968 // free old midi rules
5969 for (int i = 0 ; pMidiRules[i] ; i++) {
5970 delete pMidiRules[i];
5971 }
5972 //TODO: MIDI rule copying
5973 pMidiRules[0] = NULL;
5974
5975 // delete all old regions
5976 while (Regions) DeleteRegion(GetFirstRegion());
5977 // create new regions and copy them from original
5978 {
5979 RegionList::const_iterator it = orig->pRegions->begin();
5980 for (int i = 0; i < orig->Regions; ++i, ++it) {
5981 Region* dstRgn = AddRegion();
5982 //NOTE: Region does semi-deep copy !
5983 dstRgn->CopyAssign(
5984 static_cast<gig::Region*>(*it),
5985 mSamples
5986 );
5987 }
5988 }
5989
5990 UpdateRegionKeyTable();
5991 }
5992
5993 /**
5994 * Returns @c true in case this Instrument object uses any gig format
5995 * extension, that is e.g. whether any DimensionRegion object currently
5996 * has any setting effective that would require our "LSDE" RIFF chunk to
5997 * be stored to the gig file.
5998 *
5999 * Right now this is a private method. It is considerable though this method
6000 * to become (in slightly modified form) a public API method in future, i.e.
6001 * to allow instrument editors to visualize and/or warn the user of any gig
6002 * format extension being used. See also comments on
6003 * DimensionRegion::UsesAnyGigFormatExtension() for details about such a
6004 * potential public API change in future.
6005 */
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) {
6012 gig::Region* rgn = static_cast<gig::Region*>(*iter);
6013 if (rgn->UsesAnyGigFormatExtension())
6014 return true;
6015 }
6016 return false;
6017 }
6018
6019
6020 // *************** Group ***************
6021 // *
6022
6023 /** @brief Constructor.
6024 *
6025 * @param file - pointer to the gig::File object
6026 * @param ck3gnm - pointer to 3gnm chunk associated with this group or
6027 * NULL if this is a new Group
6028 */
6029 Group::Group(File* file, RIFF::Chunk* ck3gnm) {
6030 pFile = file;
6031 pNameChunk = ck3gnm;
6032 ::LoadString(pNameChunk, Name);
6033 }
6034
6035 /** @brief Destructor.
6036 *
6037 * Currently this destructor implementation does nothing.
6038 */
6039 Group::~Group() {
6040 }
6041
6042 /** @brief Remove all RIFF chunks associated with this Group object.
6043 *
6044 * See DLS::Storage::DeleteChunks() for details.
6045 */
6046 void Group::DeleteChunks() {
6047 // handle own RIFF chunks
6048 if (pNameChunk) {
6049 pNameChunk->GetParent()->DeleteSubChunk(pNameChunk);
6050 pNameChunk = NULL;
6051 }
6052 }
6053
6054 /** @brief Update chunks with current group settings.
6055 *
6056 * Apply current Group field values to the respective chunks. You have
6057 * to call File::Save() to make changes persistent.
6058 *
6059 * Usually there is absolutely no need to call this method explicitly.
6060 * It will be called automatically when File::Save() was called.
6061 *
6062 * @param pProgress - callback function for progress notification
6063 */
6064 void Group::UpdateChunks(progress_t* pProgress) {
6065 // make sure <3gri> and <3gnl> list chunks exist
6066 RIFF::List* _3gri = pFile->pRIFF->GetSubList(LIST_TYPE_3GRI);
6067 if (!_3gri) {
6068 _3gri = pFile->pRIFF->AddSubList(LIST_TYPE_3GRI);
6069 pFile->pRIFF->MoveSubChunk(_3gri, pFile->pRIFF->GetSubChunk(CHUNK_ID_PTBL));
6070 }
6071 RIFF::List* _3gnl = _3gri->GetSubList(LIST_TYPE_3GNL);
6072 if (!_3gnl) _3gnl = _3gri->AddSubList(LIST_TYPE_3GNL);
6073
6074 if (!pNameChunk && pFile->pVersion && pFile->pVersion->major > 2) {
6075 // v3 has a fixed list of 128 strings, find a free one
6076 for (RIFF::Chunk* ck = _3gnl->GetFirstSubChunk() ; ck ; ck = _3gnl->GetNextSubChunk()) {
6077 if (strcmp(static_cast<char*>(ck->LoadChunkData()), "") == 0) {
6078 pNameChunk = ck;
6079 break;
6080 }
6081 }
6082 }
6083
6084 // now store the name of this group as <3gnm> chunk as subchunk of the <3gnl> list chunk
6085 ::SaveString(CHUNK_ID_3GNM, pNameChunk, _3gnl, Name, String("Unnamed Group"), true, 64);
6086 }
6087
6088 /**
6089 * Returns the first Sample of this Group. You have to call this method
6090 * once before you use GetNextSample().
6091 *
6092 * <b>Notice:</b> this method might block for a long time, in case the
6093 * samples of this .gig file were not scanned yet
6094 *
6095 * @returns pointer address to first Sample or NULL if there is none
6096 * applied to this Group
6097 * @see GetNextSample()
6098 */
6099 Sample* Group::GetFirstSample() {
6100 // FIXME: lazy und unsafe implementation, should be an autonomous iterator
6101 for (Sample* pSample = pFile->GetFirstSample(); pSample; pSample = pFile->GetNextSample()) {
6102 if (pSample->GetGroup() == this) return pSample;
6103 }
6104 return NULL;
6105 }
6106
6107 /**
6108 * Returns the next Sample of the Group. You have to call
6109 * GetFirstSample() once before you can use this method. By calling this
6110 * method multiple times it iterates through the Samples assigned to
6111 * this Group.
6112 *
6113 * @returns pointer address to the next Sample of this Group or NULL if
6114 * end reached
6115 * @see GetFirstSample()
6116 */
6117 Sample* Group::GetNextSample() {
6118 // FIXME: lazy und unsafe implementation, should be an autonomous iterator
6119 for (Sample* pSample = pFile->GetNextSample(); pSample; pSample = pFile->GetNextSample()) {
6120 if (pSample->GetGroup() == this) return pSample;
6121 }
6122 return NULL;
6123 }
6124
6125 /**
6126 * Move Sample given by \a pSample from another Group to this Group.
6127 */
6128 void Group::AddSample(Sample* pSample) {
6129 pSample->pGroup = this;
6130 }
6131
6132 /**
6133 * Move all members of this group to another group (preferably the 1st
6134 * one except this). This method is called explicitly by
6135 * File::DeleteGroup() thus when a Group was deleted. This code was
6136 * intentionally not placed in the destructor!
6137 */
6138 void Group::MoveAll() {
6139 // get "that" other group first
6140 Group* pOtherGroup = NULL;
6141 for (pOtherGroup = pFile->GetFirstGroup(); pOtherGroup; pOtherGroup = pFile->GetNextGroup()) {
6142 if (pOtherGroup != this) break;
6143 }
6144 if (!pOtherGroup) throw Exception(
6145 "Could not move samples to another group, since there is no "
6146 "other Group. This is a bug, report it!"
6147 );
6148 // now move all samples of this group to the other group
6149 for (Sample* pSample = GetFirstSample(); pSample; pSample = GetNextSample()) {
6150 pOtherGroup->AddSample(pSample);
6151 }
6152 }
6153
6154
6155
6156 // *************** File ***************
6157 // *
6158
6159 /// Reflects Gigasampler file format version 2.0 (1998-06-28).
6160 const DLS::version_t File::VERSION_2 = {
6161 0, 2, 19980628 & 0xffff, 19980628 >> 16
6162 };
6163
6164 /// Reflects Gigasampler file format version 3.0 (2003-03-31).
6165 const DLS::version_t File::VERSION_3 = {
6166 0, 3, 20030331 & 0xffff, 20030331 >> 16
6167 };
6168
6169 /// Reflects Gigasampler file format version 4.0 (2007-10-12).
6170 const DLS::version_t File::VERSION_4 = {
6171 0, 4, 20071012 & 0xffff, 20071012 >> 16
6172 };
6173
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 },
6192 { 0, 0 }
6193 };
6194
6195 File::File() : DLS::File() {
6196 bAutoLoad = true;
6197 *pVersion = VERSION_3;
6198 pGroups = NULL;
6199 pScriptGroups = NULL;
6200 pInfo->SetFixedStringLengths(_FileFixedStringLengths);
6201 pInfo->ArchivalLocation = String(256, ' ');
6202
6203 // add some mandatory chunks to get the file chunks in right
6204 // order (INFO chunk will be moved to first position later)
6205 pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);
6206 pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);
6207 pRIFF->AddSubChunk(CHUNK_ID_DLID, 16);
6208
6209 GenerateDLSID();
6210 }
6211
6212 File::File(RIFF::File* pRIFF) : DLS::File(pRIFF) {
6213 bAutoLoad = true;
6214 pGroups = NULL;
6215 pScriptGroups = NULL;
6216 pInfo->SetFixedStringLengths(_FileFixedStringLengths);
6217 }
6218
6219 File::~File() {
6220 if (pGroups) {
6221 std::list<Group*>::iterator iter = pGroups->begin();
6222 std::list<Group*>::iterator end = pGroups->end();
6223 while (iter != end) {
6224 delete *iter;
6225 ++iter;
6226 }
6227 delete pGroups;
6228 }
6229 if (pScriptGroups) {
6230 std::list<ScriptGroup*>::iterator iter = pScriptGroups->begin();
6231 std::list<ScriptGroup*>::iterator end = pScriptGroups->end();
6232 while (iter != end) {
6233 delete *iter;
6234 ++iter;
6235 }
6236 delete pScriptGroups;
6237 }
6238 }
6239
6240 Sample* File::GetFirstSample(progress_t* pProgress) {
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 );
6245 }
6246
6247 Sample* File::GetNextSample() {
6248 if (!pSamples) return NULL;
6249 SamplesIterator++;
6250 return static_cast<gig::Sample*>( (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL );
6251 }
6252
6253 /**
6254 * Returns Sample object of @a index.
6255 *
6256 * @returns sample object or NULL if index is out of bounds
6257 */
6258 Sample* File::GetSample(uint index) {
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) {
6263 ++it;
6264 if (it == pSamples->end()) return NULL;
6265 }
6266 if (it == pSamples->end()) return NULL;
6267 return static_cast<gig::Sample*>( *it );
6268 }
6269
6270 /**
6271 * Returns the total amount of samples of this gig file.
6272 *
6273 * Note that this method might block for a long time in case it is required
6274 * to load the sample info for the first time.
6275 *
6276 * @returns total amount of samples
6277 */
6278 size_t File::CountSamples() {
6279 if (!pSamples) LoadSamples();
6280 if (!pSamples) return 0;
6281 return pSamples->size();
6282 }
6283
6284 /** @brief Add a new sample.
6285 *
6286 * This will create a new Sample object for the gig file. You have to
6287 * call Save() to make this persistent to the file.
6288 *
6289 * @returns pointer to new Sample object
6290 */
6291 Sample* File::AddSample() {
6292 if (!pSamples) LoadSamples();
6293 __ensureMandatoryChunksExist();
6294 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
6295 // create new Sample object and its respective 'wave' list chunk
6296 RIFF::List* wave = wvpl->AddSubList(LIST_TYPE_WAVE);
6297 Sample* pSample = new Sample(this, wave, 0 /*arbitrary value, we update offsets when we save*/);
6298
6299 // add mandatory chunks to get the chunks in right order
6300 wave->AddSubChunk(CHUNK_ID_FMT, 16);
6301 wave->AddSubList(LIST_TYPE_INFO);
6302
6303 pSamples->push_back(pSample);
6304 return pSample;
6305 }
6306
6307 /** @brief Delete a sample.
6308 *
6309 * This will delete the given Sample object from the gig file. Any
6310 * references to this sample from Regions and DimensionRegions will be
6311 * removed. You have to call Save() to make this persistent to the file.
6312 *
6313 * @param pSample - sample to delete
6314 * @throws gig::Exception if given sample could not be found
6315 */
6316 void File::DeleteSample(Sample* 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; // avoid iterator invalidation
6321 pSamples->erase(iter);
6322 pSample->DeleteChunks();
6323 delete pSample;
6324
6325 SampleList::iterator tmp = SamplesIterator;
6326 // remove all references to the sample
6327 for (Instrument* instrument = GetFirstInstrument() ; instrument ;
6328 instrument = GetNextInstrument()) {
6329 for (Region* region = instrument->GetFirstRegion() ; region ;
6330 region = instrument->GetNextRegion()) {
6331
6332 if (region->GetSample() == pSample) region->SetSample(NULL);
6333
6334 for (int i = 0 ; i < region->DimensionRegions ; i++) {
6335 gig::DimensionRegion *d = region->pDimensionRegions[i];
6336 if (d->pSample == pSample) d->pSample = NULL;
6337 }
6338 }
6339 }
6340 SamplesIterator = tmp; // restore iterator
6341 }
6342
6343 void File::LoadSamples() {
6344 LoadSamples(NULL);
6345 }
6346
6347 void File::LoadSamples(progress_t* pProgress) {
6348 // Groups must be loaded before samples, because samples will try
6349 // to resolve the group they belong to
6350 if (!pGroups) LoadGroups();
6351
6352 if (!pSamples) pSamples = new SampleList;
6353
6354 RIFF::File* file = pRIFF;
6355
6356 // just for progress calculation
6357 int iSampleIndex = 0;
6358 int iTotalSamples = WavePoolCount;
6359
6360 // just for assembling path of optional extension files to be read
6361 const std::string folder = parentPath(pRIFF->GetFileName());
6362 const std::string baseName = pathWithoutExtension(pRIFF->GetFileName());
6363
6364 // the main gig file and the extension files (.gx01, ... , .gx98) may
6365 // contain wave data (wave pool)
6366 std::vector<RIFF::File*> poolFiles;
6367 poolFiles.push_back(pRIFF);
6368
6369 // get info about all extension files
6370 RIFF::Chunk* ckXfil = pRIFF->GetSubChunk(CHUNK_ID_XFIL);
6371 if (ckXfil) { // there are extension files (.gx01, ... , .gx98) ...
6372 const uint32_t n = ckXfil->ReadInt32();
6373 for (int i = 0; i < n; i++) {
6374 // read the filename and load the extension file
6375 std::string name;
6376 ckXfil->ReadString(name, 128);
6377 std::string path = concatPath(folder, name);
6378 RIFF::File* pExtFile = new RIFF::File(path);
6379 // check that the dlsids match
6380 RIFF::Chunk* ckDLSID = pExtFile->GetSubChunk(CHUNK_ID_DLID);
6381 if (ckDLSID) {
6382 ::DLS::dlsid_t idExpected;
6383 idExpected.ulData1 = ckXfil->ReadInt32();
6384 idExpected.usData2 = ckXfil->ReadInt16();
6385 idExpected.usData3 = ckXfil->ReadInt16();
6386 ckXfil->Read(idExpected.abData, 8, 1);
6387 ::DLS::dlsid_t idFound;
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());
6394 }
6395 poolFiles.push_back(pExtFile);
6396 ExtensionFiles.push_back(pExtFile);
6397 }
6398 }
6399
6400 // check if a .gx99 (GigaPulse) file exists
6401 RIFF::Chunk* ckDoxf = pRIFF->GetSubChunk(CHUNK_ID_DOXF);
6402 if (ckDoxf) { // there is a .gx99 (GigaPulse) file ...
6403 std::string path = baseName + ".gx99";
6404 RIFF::File* pExtFile = new RIFF::File(path);
6405
6406 // skip unused int and filename
6407 ckDoxf->SetPos(132, RIFF::stream_curpos);
6408
6409 // check that the dlsids match
6410 RIFF::Chunk* ckDLSID = pExtFile->GetSubChunk(CHUNK_ID_DLID);
6411 if (ckDLSID) {
6412 ::DLS::dlsid_t idExpected;
6413 idExpected.ulData1 = ckDoxf->ReadInt32();
6414 idExpected.usData2 = ckDoxf->ReadInt16();
6415 idExpected.usData3 = ckDoxf->ReadInt16();
6416 ckDoxf->Read(idExpected.abData, 8, 1);
6417 ::DLS::dlsid_t idFound;
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());
6424 }
6425 poolFiles.push_back(pExtFile);
6426 ExtensionFiles.push_back(pExtFile);
6427 }
6428
6429 // load samples from extension files (if required)
6430 for (int i = 0; i < poolFiles.size(); i++) {
6431 RIFF::File* file = poolFiles[i];
6432 RIFF::List* wvpl = file->GetSubList(LIST_TYPE_WVPL);
6433 if (wvpl) {
6434 file_offset_t wvplFileOffset = wvpl->GetFilePos() -
6435 wvpl->GetPos(); // should be zero, but just to be sure
6436 RIFF::List* wave = wvpl->GetFirstSubList();
6437 while (wave) {
6438 if (wave->GetListType() == LIST_TYPE_WAVE) {
6439 // notify current progress
6440 if (pProgress) {
6441 const float subprogress = (float) iSampleIndex / (float) iTotalSamples;
6442 __notify_progress(pProgress, subprogress);
6443 }
6444
6445 file_offset_t waveFileOffset = wave->GetFilePos();
6446 pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset, i, iSampleIndex));
6447
6448 iSampleIndex++;
6449 }
6450 wave = wvpl->GetNextSubList();
6451 }
6452 }
6453 }
6454
6455 if (pProgress)
6456 __notify_progress(pProgress, 1.0); // notify done
6457 }
6458
6459 Instrument* File::GetFirstInstrument() {
6460 if (!pInstruments) LoadInstruments();
6461 if (!pInstruments) return NULL;
6462 InstrumentsIterator = pInstruments->begin();
6463 return static_cast<gig::Instrument*>( (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL );
6464 }
6465
6466 Instrument* File::GetNextInstrument() {
6467 if (!pInstruments) return NULL;
6468 InstrumentsIterator++;
6469 return static_cast<gig::Instrument*>( (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL );
6470 }
6471
6472 /**
6473 * Returns the total amount of instruments of this gig file.
6474 *
6475 * Note that this method might block for a long time in case it is required
6476 * to load the instruments info for the first time.
6477 *
6478 * @returns total amount of instruments
6479 */
6480 size_t File::CountInstruments() {
6481 if (!pInstruments) LoadInstruments();
6482 if (!pInstruments) return 0;
6483 return pInstruments->size();
6484 }
6485
6486 /**
6487 * Returns the instrument with the given index.
6488 *
6489 * @param index - number of the sought instrument (0..n)
6490 * @param pProgress - optional: callback function for progress notification
6491 * @returns sought instrument or NULL if there's no such instrument
6492 */
6493 Instrument* File::GetInstrument(uint index, progress_t* pProgress) {
6494 if (!pInstruments) {
6495 // TODO: hack - we simply load ALL samples here, it would have been done in the Region constructor anyway (ATM)
6496
6497 if (pProgress) {
6498 // sample loading subtask
6499 progress_t subprogress;
6500 __divide_progress(pProgress, &subprogress, 3.0f, 0.0f); // randomly schedule 33% for this subtask
6501 __notify_progress(&subprogress, 0.0f);
6502 if (GetAutoLoad())
6503 GetFirstSample(&subprogress); // now force all samples to be loaded
6504 __notify_progress(&subprogress, 1.0f);
6505
6506 // instrument loading subtask
6507 if (pProgress->callback) {
6508 subprogress.__range_min = subprogress.__range_max;
6509 subprogress.__range_max = pProgress->__range_max; // schedule remaining percentage for this subtask
6510 }
6511 __notify_progress(&subprogress, 0.0f);
6512 LoadInstruments(&subprogress);
6513 __notify_progress(&subprogress, 1.0f);
6514 } else {
6515 // sample loading subtask
6516 if (GetAutoLoad())
6517 GetFirstSample(); // now force all samples to be loaded
6518
6519 // instrument loading subtask
6520 LoadInstruments();
6521 }
6522 }
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++;
6528 }
6529 return NULL;
6530 }
6531
6532 /** @brief Add a new instrument definition.
6533 *
6534 * This will create a new Instrument object for the gig file. You have
6535 * to call Save() to make this persistent to the file.
6536 *
6537 * @returns pointer to new Instrument object
6538 */
6539 Instrument* File::AddInstrument() {
6540 if (!pInstruments) LoadInstruments();
6541 __ensureMandatoryChunksExist();
6542 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
6543 RIFF::List* lstInstr = lstInstruments->AddSubList(LIST_TYPE_INS);
6544
6545 // add mandatory chunks to get the chunks in right order
6546 lstInstr->AddSubList(LIST_TYPE_INFO);
6547 lstInstr->AddSubChunk(CHUNK_ID_DLID, 16);
6548
6549 Instrument* pInstrument = new Instrument(this, lstInstr);
6550 pInstrument->GenerateDLSID();
6551
6552 lstInstr->AddSubChunk(CHUNK_ID_INSH, 12);
6553
6554 // this string is needed for the gig to be loadable in GSt:
6555 pInstrument->pInfo->Software = "Endless Wave";
6556
6557 pInstruments->push_back(pInstrument);
6558 return pInstrument;
6559 }
6560
6561 /** @brief Add a duplicate of an existing instrument.
6562 *
6563 * Duplicates the instrument definition given by @a orig and adds it
6564 * to this file. This allows in an instrument editor application to
6565 * easily create variations of an instrument, which will be stored in
6566 * the same .gig file, sharing i.e. the same samples.
6567 *
6568 * Note that all sample pointers referenced by @a orig are simply copied as
6569 * memory address. Thus the respective samples are shared, not duplicated!
6570 *
6571 * You have to call Save() to make this persistent to the file.
6572 *
6573 * @param orig - original instrument to be copied
6574 * @returns duplicated copy of the given instrument
6575 */
6576 Instrument* File::AddDuplicateInstrument(const Instrument* orig) {
6577 Instrument* instr = AddInstrument();
6578 instr->CopyAssign(orig);
6579 return instr;
6580 }
6581
6582 /** @brief Add content of another existing file.
6583 *
6584 * Duplicates the samples, groups and instruments of the original file
6585 * given by @a pFile and adds them to @c this File. In case @c this File is
6586 * a new one that you haven't saved before, then you have to call
6587 * SetFileName() before calling AddContentOf(), because this method will
6588 * automatically save this file during operation, which is required for
6589 * writing the sample waveform data by disk streaming.
6590 *
6591 * @param pFile - original file whose's content shall be copied from
6592 */
6593 void File::AddContentOf(File* pFile) {
6594 static int iCallCount = -1;
6595 iCallCount++;
6596 std::map<Group*,Group*> mGroups;
6597 std::map<Sample*,Sample*> mSamples;
6598
6599 // clone sample groups
6600 for (int i = 0; pFile->GetGroup(i); ++i) {
6601 Group* g = AddGroup();
6602 g->Name =
6603 "COPY" + ToString(iCallCount) + "_" + pFile->GetGroup(i)->Name;
6604 mGroups[pFile->GetGroup(i)] = g;
6605 }
6606
6607 // clone samples (not waveform data here yet)
6608 for (int i = 0; pFile->GetSample(i); ++i) {
6609 Sample* s = AddSample();
6610 s->CopyAssignMeta(pFile->GetSample(i));
6611 mGroups[pFile->GetSample(i)->GetGroup()]->AddSample(s);
6612 mSamples[pFile->GetSample(i)] = s;
6613 }
6614
6615 // clone script groups and their scripts
6616 for (int iGroup = 0; pFile->GetScriptGroup(iGroup); ++iGroup) {
6617 ScriptGroup* sg = pFile->GetScriptGroup(iGroup);
6618 ScriptGroup* dg = AddScriptGroup();
6619 dg->Name = "COPY" + ToString(iCallCount) + "_" + sg->Name;
6620 for (int iScript = 0; sg->GetScript(iScript); ++iScript) {
6621 Script* ss = sg->GetScript(iScript);
6622 Script* ds = dg->AddScript();
6623 ds->CopyAssign(ss);
6624 }
6625 }
6626
6627 //BUG: For some reason this method only works with this additional
6628 // Save() call in between here.
6629 //
6630 // Important: The correct one of the 2 Save() methods has to be called
6631 // here, depending on whether the file is completely new or has been
6632 // saved to disk already, otherwise it will result in data corruption.
6633 if (pRIFF->IsNew())
6634 Save(GetFileName());
6635 else
6636 Save();
6637
6638 // clone instruments
6639 // (passing the crosslink table here for the cloned samples)
6640 for (int i = 0; pFile->GetInstrument(i); ++i) {
6641 Instrument* instr = AddInstrument();
6642 instr->CopyAssign(pFile->GetInstrument(i), &mSamples);
6643 }
6644
6645 // Mandatory: file needs to be saved to disk at this point, so this
6646 // file has the correct size and data layout for writing the samples'
6647 // waveform data to disk.
6648 Save();
6649
6650 // clone samples' waveform data
6651 // (using direct read & write disk streaming)
6652 for (int i = 0; pFile->GetSample(i); ++i) {
6653 mSamples[pFile->GetSample(i)]->CopyAssignWave(pFile->GetSample(i));
6654 }
6655 }
6656
6657 /** @brief Delete an instrument.
6658 *
6659 * This will delete the given Instrument object from the gig file. You
6660 * have to call Save() to make this persistent to the file.
6661 *
6662 * @param pInstrument - instrument to delete
6663 * @throws gig::Exception if given instrument could not be found
6664 */
6665 void File::DeleteInstrument(Instrument* pInstrument) {
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);
6670 pInstrument->DeleteChunks();
6671 delete pInstrument;
6672 }
6673
6674 void File::LoadInstruments() {
6675 LoadInstruments(NULL);
6676 }
6677
6678 void File::LoadInstruments(progress_t* pProgress) {
6679 if (!pInstruments) pInstruments = new InstrumentList;
6680 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
6681 if (lstInstruments) {
6682 int iInstrumentIndex = 0;
6683 RIFF::List* lstInstr = lstInstruments->GetFirstSubList();
6684 while (lstInstr) {
6685 if (lstInstr->GetListType() == LIST_TYPE_INS) {
6686 if (pProgress) {
6687 // notify current progress
6688 const float localProgress = (float) iInstrumentIndex / (float) Instruments;
6689 __notify_progress(pProgress, localProgress);
6690
6691 // divide local progress into subprogress for loading current Instrument
6692 progress_t subprogress;
6693 __divide_progress(pProgress, &subprogress, Instruments, iInstrumentIndex);
6694
6695 pInstruments->push_back(new Instrument(this, lstInstr, &subprogress));
6696 } else {
6697 pInstruments->push_back(new Instrument(this, lstInstr));
6698 }
6699
6700 iInstrumentIndex++;
6701 }
6702 lstInstr = lstInstruments->GetNextSubList();
6703 }
6704 if (pProgress)
6705 __notify_progress(pProgress, 1.0); // notify done
6706 }
6707 }
6708
6709 /// Updates the 3crc chunk with the checksum of a sample. The
6710 /// update is done directly to disk, as this method is called
6711 /// after File::Save()
6712 void File::SetSampleChecksum(Sample* pSample, uint32_t crc) {
6713 RIFF::Chunk* _3crc = pRIFF->GetSubChunk(CHUNK_ID_3CRC);
6714 if (!_3crc) return;
6715
6716 // get the index of the sample
6717 int iWaveIndex = GetWaveTableIndexOf(pSample);
6718 if (iWaveIndex < 0) throw gig::Exception("Could not update crc, could not find sample");
6719
6720 // write the CRC-32 checksum to disk
6721 _3crc->SetPos(iWaveIndex * 8);
6722 uint32_t one = 1;
6723 _3crc->WriteUint32(&one); // always 1
6724 _3crc->WriteUint32(&crc);
6725 }
6726
6727 uint32_t File::GetSampleChecksum(Sample* pSample) {
6728 // get the index of the sample
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");
6731
6732 return GetSampleChecksumByIndex(iWaveIndex);
6733 }
6734
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");
6737
6738 RIFF::Chunk* _3crc = pRIFF->GetSubChunk(CHUNK_ID_3CRC);
6739 if (!_3crc) throw gig::Exception("Could not retrieve reference crc of sample, no checksums stored for this file yet");
6740 uint8_t* pData = (uint8_t*) _3crc->LoadChunkData();
6741 if (!pData) throw gig::Exception("Could not retrieve reference crc of sample, no checksums stored for this file yet");
6742
6743 // read the CRC-32 checksum directly from disk
6744 size_t pos = index * 8;
6745 if (pos + 8 > _3crc->GetNewSize())
6746 throw gig::Exception("Could not retrieve reference crc of sample, could not seek to required position in crc chunk");
6747
6748 uint32_t one = load32(&pData[pos]); // always 1
6749 if (one != 1)
6750 throw gig::Exception("Could not retrieve reference crc of sample, because reference checksum table is damaged");
6751
6752 return load32(&pData[pos+4]);
6753 }
6754
6755 int File::GetWaveTableIndexOf(gig::Sample* pSample) {
6756 if (!pSamples) GetFirstSample(); // make sure sample chunks were scanned
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)
6761 return index;
6762 return -1;
6763 }
6764
6765 /**
6766 * Checks whether the file's "3CRC" chunk was damaged. This chunk contains
6767 * the CRC32 check sums of all samples' raw wave data.
6768 *
6769 * @return true if 3CRC chunk is OK, or false if 3CRC chunk is damaged
6770 */
6771 bool File::VerifySampleChecksumTable() {
6772 RIFF::Chunk* _3crc = pRIFF->GetSubChunk(CHUNK_ID_3CRC);
6773 if (!_3crc) return false;
6774 if (_3crc->GetNewSize() <= 0) return false;
6775 if (_3crc->GetNewSize() % 8) return false;
6776 if (!pSamples) GetFirstSample(); // make sure sample chunks were scanned
6777 if (_3crc->GetNewSize() != pSamples->size() * 8) return false;
6778
6779 const file_offset_t n = _3crc->GetNewSize() / 8;
6780
6781 uint32_t* pData = (uint32_t*) _3crc->LoadChunkData();
6782 if (!pData) return false;
6783
6784 for (file_offset_t i = 0; i < n; ++i) {
6785 uint32_t one = pData[i*2];
6786 if (one != 1) return false;
6787 }
6788
6789 return true;
6790 }
6791
6792 /**
6793 * Recalculates CRC32 checksums for all samples and rebuilds this gig
6794 * file's checksum table with those new checksums. This might usually
6795 * just be necessary if the checksum table was damaged.
6796 *
6797 * @e IMPORTANT: The current implementation of this method only works
6798 * with files that have not been modified since it was loaded, because
6799 * it expects that no externally caused file structure changes are
6800 * required!
6801 *
6802 * Due to the expectation above, this method is currently protected
6803 * and actually only used by the command line tool "gigdump" yet.
6804 *
6805 * @returns true if Save() is required to be called after this call,
6806 * false if no further action is required
6807 */
6808 bool File::RebuildSampleChecksumTable() {
6809 // make sure sample chunks were scanned
6810 if (!pSamples) GetFirstSample();
6811
6812 bool bRequiresSave = false;
6813
6814 // make sure "3CRC" chunk exists with required size
6815 RIFF::Chunk* _3crc = pRIFF->GetSubChunk(CHUNK_ID_3CRC);
6816 if (!_3crc) {
6817 _3crc = pRIFF->AddSubChunk(CHUNK_ID_3CRC, pSamples->size() * 8);
6818 // the order of einf and 3crc is not the same in v2 and v3
6819 RIFF::Chunk* einf = pRIFF->GetSubChunk(CHUNK_ID_EINF);
6820 if (einf && pVersion && pVersion->major > 2) pRIFF->MoveSubChunk(_3crc, einf);
6821 bRequiresSave = true;
6822 } else if (_3crc->GetNewSize() != pSamples->size() * 8) {
6823 _3crc->Resize(pSamples->size() * 8);
6824 bRequiresSave = true;
6825 }
6826
6827 if (bRequiresSave) { // refill CRC table for all samples in RAM ...
6828 uint32_t* pData = (uint32_t*) _3crc->LoadChunkData();
6829 {
6830 File::SampleList::iterator iter = pSamples->begin();
6831 File::SampleList::iterator end = pSamples->end();
6832 for (; iter != end; ++iter) {
6833 gig::Sample* pSample = (gig::Sample*) *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");
6836 pData[index*2] = 1; // always 1
6837 pData[index*2+1] = pSample->CalculateWaveDataChecksum();
6838 }
6839 }
6840 } else { // no file structure changes necessary, so directly write to disk and we are done ...
6841 // make sure file is in write mode
6842 pRIFF->SetMode(RIFF::stream_mode_read_write);
6843 {
6844 File::SampleList::iterator iter = pSamples->begin();
6845 File::SampleList::iterator end = pSamples->end();
6846 for (; iter != end; ++iter) {
6847 gig::Sample* pSample = (gig::Sample*) *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();
6851 SetSampleChecksum(pSample, pSample->crc);
6852 }
6853 }
6854 }
6855
6856 return bRequiresSave;
6857 }
6858
6859 Group* File::GetFirstGroup() {
6860 if (!pGroups) LoadGroups();
6861 // there must always be at least one group
6862 GroupsIterator = pGroups->begin();
6863 return *GroupsIterator;
6864 }
6865
6866 Group* File::GetNextGroup() {
6867 if (!pGroups) return NULL;
6868 ++GroupsIterator;
6869 return (GroupsIterator == pGroups->end()) ? NULL : *GroupsIterator;
6870 }
6871
6872 /**
6873 * Returns the group with the given index.
6874 *
6875 * @param index - number of the sought group (0..n)
6876 * @returns sought group or NULL if there's no such group
6877 */
6878 Group* File::GetGroup(uint index) {
6879 if (!pGroups) LoadGroups();
6880 GroupsIterator = pGroups->begin();
6881 for (uint i = 0; GroupsIterator != pGroups->end(); i++) {
6882 if (i == index) return *GroupsIterator;
6883 ++GroupsIterator;
6884 }
6885 return NULL;
6886 }
6887
6888 /**
6889 * Returns the group with the given group name.
6890 *
6891 * Note: group names don't have to be unique in the gig format! So there
6892 * can be multiple groups with the same name. This method will simply
6893 * return the first group found with the given name.
6894 *
6895 * @param name - name of the sought group
6896 * @returns sought group or NULL if there's no group with that name
6897 */
6898 Group* File::GetGroup(String name) {
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;
6903 return NULL;
6904 }
6905
6906 Group* File::AddGroup() {
6907 if (!pGroups) LoadGroups();
6908 // there must always be at least one group
6909 __ensureMandatoryChunksExist();
6910 Group* pGroup = new Group(this, NULL);
6911 pGroups->push_back(pGroup);
6912 return pGroup;
6913 }
6914
6915 /** @brief Delete a group and its samples.
6916 *
6917 * This will delete the given Group object and all the samples that
6918 * belong to this group from the gig file. You have to call Save() to
6919 * make this persistent to the file.
6920 *
6921 * @param pGroup - group to delete
6922 * @throws gig::Exception if given group could not be found
6923 */
6924 void File::DeleteGroup(Group* 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!");
6929 // delete all members of this group
6930 for (Sample* pSample = pGroup->GetFirstSample(); pSample; pSample = pGroup->GetNextSample()) {
6931 DeleteSample(pSample);
6932 }
6933 // now delete this group object
6934 pGroups->erase(iter);
6935 pGroup->DeleteChunks();
6936 delete pGroup;
6937 }
6938
6939 /** @brief Delete a group.
6940 *
6941 * This will delete the given Group object from the gig file. All the
6942 * samples that belong to this group will not be deleted, but instead
6943 * be moved to another group. You have to call Save() to make this
6944 * persistent to the file.
6945 *
6946 * @param pGroup - group to delete
6947 * @throws gig::Exception if given group could not be found
6948 */
6949 void File::DeleteGroupOnly(Group* pGroup) {
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!");
6954 // move all members of this group to another group
6955 pGroup->MoveAll();
6956 pGroups->erase(iter);
6957 pGroup->DeleteChunks();
6958 delete pGroup;
6959 }
6960
6961 void File::LoadGroups() {
6962 if (!pGroups) pGroups = new std::list<Group*>;
6963 // try to read defined groups from file
6964 RIFF::List* lst3gri = pRIFF->GetSubList(LIST_TYPE_3GRI);
6965 if (lst3gri) {
6966 RIFF::List* lst3gnl = lst3gri->GetSubList(LIST_TYPE_3GNL);
6967 if (lst3gnl) {
6968 RIFF::Chunk* ck = lst3gnl->GetFirstSubChunk();
6969 while (ck) {
6970 if (ck->GetChunkID() == CHUNK_ID_3GNM) {
6971 if (pVersion && pVersion->major > 2 &&
6972 strcmp(static_cast<char*>(ck->LoadChunkData()), "") == 0) break;
6973
6974 pGroups->push_back(new Group(this, ck));
6975 }
6976 ck = lst3gnl->GetNextSubChunk();
6977 }
6978 }
6979 }
6980 // if there were no group(s), create at least the mandatory default group
6981 if (!pGroups->size()) {
6982 Group* pGroup = new Group(this, NULL);
6983 pGroup->Name = "Default Group";
6984 pGroups->push_back(pGroup);
6985 }
6986 }
6987
6988 /** @brief Get instrument script group (by index).
6989 *
6990 * Returns the real-time instrument script group with the given index.
6991 *
6992 * @param index - number of the sought group (0..n)
6993 * @returns sought script group or NULL if there's no such group
6994 */
6995 ScriptGroup* File::GetScriptGroup(uint index) {
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;
7000 return NULL;
7001 }
7002
7003 /** @brief Get instrument script group (by name).
7004 *
7005 * Returns the first real-time instrument script group found with the given
7006 * group name. Note that group names may not necessarily be unique.
7007 *
7008 * @param name - name of the sought script group
7009 * @returns sought script group or NULL if there's no such group
7010 */
7011 ScriptGroup* File::GetScriptGroup(const String& name) {
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;
7016 return NULL;
7017 }
7018
7019 /** @brief Add new instrument script group.
7020 *
7021 * Adds a new, empty real-time instrument script group to the file.
7022 *
7023 * You have to call Save() to make this persistent to the file.
7024 *
7025 * @return new empty script group
7026 */
7027 ScriptGroup* File::AddScriptGroup() {
7028 if (!pScriptGroups) LoadScriptGroups();
7029 ScriptGroup* pScriptGroup = new ScriptGroup(this, NULL);
7030 pScriptGroups->push_back(pScriptGroup);
7031 return pScriptGroup;
7032 }
7033
7034 /** @brief Delete an instrument script group.
7035 *
7036 * This will delete the given real-time instrument script group and all its
7037 * instrument scripts it contains. References inside instruments that are
7038 * using the deleted scripts will be removed from the respective instruments
7039 * accordingly.
7040 *
7041 * You have to call Save() to make this persistent to the file.
7042 *
7043 * @param pScriptGroup - script group to delete
7044 * @throws gig::Exception if given script group could not be found
7045 */
7046 void File::DeleteScriptGroup(ScriptGroup* 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)
7054 pScriptGroup->DeleteScript(pScriptGroup->GetScript(i));
7055 if (pScriptGroup->pList)
7056 pScriptGroup->pList->GetParent()->DeleteSubChunk(pScriptGroup->pList);
7057 pScriptGroup->DeleteChunks();
7058 delete pScriptGroup;
7059 }
7060
7061 void File::LoadScriptGroups() {
7062 if (pScriptGroups) return;
7063 pScriptGroups = new std::list<ScriptGroup*>;
7064 RIFF::List* lstLS = pRIFF->GetSubList(LIST_TYPE_3LS);
7065 if (lstLS) {
7066 for (RIFF::List* lst = lstLS->GetFirstSubList(); lst;
7067 lst = lstLS->GetNextSubList())
7068 {
7069 if (lst->GetListType() == LIST_TYPE_RTIS) {
7070 pScriptGroups->push_back(new ScriptGroup(this, lst));
7071 }
7072 }
7073 }
7074 }
7075
7076 /**
7077 * Apply all the gig file's current instruments, samples, groups and settings
7078 * to the respective RIFF chunks. You have to call Save() to make changes
7079 * persistent.
7080 *
7081 * Usually there is absolutely no need to call this method explicitly.
7082 * It will be called automatically when File::Save() was called.
7083 *
7084 * @param pProgress - callback function for progress notification
7085 * @throws Exception - on errors
7086 */
7087 void File::UpdateChunks(progress_t* pProgress) {
7088 bool newFile = pRIFF->GetSubList(LIST_TYPE_INFO) == NULL;
7089
7090 // update own gig format extension chunks
7091 // (not part of the GigaStudio 4 format)
7092 RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS);
7093 if (!lst3LS) {
7094 lst3LS = pRIFF->AddSubList(LIST_TYPE_3LS);
7095 }
7096 // Make sure <3LS > chunk is placed before <ptbl> chunk. The precise
7097 // location of <3LS > is irrelevant, however it should be located
7098 // before the actual wave data
7099 RIFF::Chunk* ckPTBL = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
7100 pRIFF->MoveSubChunk(lst3LS, ckPTBL);
7101
7102 // This must be performed before writing the chunks for instruments,
7103 // because the instruments' script slots will write the file offsets
7104 // of the respective instrument script chunk as reference.
7105 if (pScriptGroups) {
7106 // Update instrument script (group) chunks.
7107 for (std::list<ScriptGroup*>::iterator it = pScriptGroups->begin();
7108 it != pScriptGroups->end(); ++it)
7109 {
7110 (*it)->UpdateChunks(pProgress);
7111 }
7112 }
7113
7114 // in case no libgig custom format data was added, then remove the
7115 // custom "3LS " chunk again
7116 if (!lst3LS->CountSubChunks()) {
7117 pRIFF->DeleteSubChunk(lst3LS);
7118 lst3LS = NULL;
7119 }
7120
7121 // first update base class's chunks
7122 DLS::File::UpdateChunks(pProgress);
7123
7124 if (newFile) {
7125 // INFO was added by Resource::UpdateChunks - make sure it
7126 // is placed first in file
7127 RIFF::Chunk* info = pRIFF->GetSubList(LIST_TYPE_INFO);
7128 RIFF::Chunk* first = pRIFF->GetFirstSubChunk();
7129 if (first != info) {
7130 pRIFF->MoveSubChunk(info, first);
7131 }
7132 }
7133
7134 // update group's chunks
7135 if (pGroups) {
7136 // make sure '3gri' and '3gnl' list chunks exist
7137 // (before updating the Group chunks)
7138 RIFF::List* _3gri = pRIFF->GetSubList(LIST_TYPE_3GRI);
7139 if (!_3gri) {
7140 _3gri = pRIFF->AddSubList(LIST_TYPE_3GRI);
7141 pRIFF->MoveSubChunk(_3gri, pRIFF->GetSubChunk(CHUNK_ID_PTBL));
7142 }
7143 RIFF::List* _3gnl = _3gri->GetSubList(LIST_TYPE_3GNL);
7144 if (!_3gnl) _3gnl = _3gri->AddSubList(LIST_TYPE_3GNL);
7145
7146 // v3: make sure the file has 128 3gnm chunks
7147 // (before updating the Group chunks)
7148 if (pVersion && pVersion->major > 2) {
7149 RIFF::Chunk* _3gnm = _3gnl->GetFirstSubChunk();
7150 for (int i = 0 ; i < 128 ; i++) {
7151 // create 128 empty placeholder strings which will either
7152 // be filled by Group::UpdateChunks below or left empty.
7153 ::SaveString(CHUNK_ID_3GNM, _3gnm, _3gnl, "", "", true, 64);
7154 if (_3gnm) _3gnm = _3gnl->GetNextSubChunk();
7155 }
7156 }
7157
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);
7162 }
7163 }
7164
7165 // update einf chunk
7166
7167 // The einf chunk contains statistics about the gig file, such
7168 // as the number of regions and samples used by each
7169 // instrument. It is divided in equally sized parts, where the
7170 // first part contains information about the whole gig file,
7171 // and the rest of the parts map to each instrument in the
7172 // file.
7173 //
7174 // At the end of each part there is a bit map of each sample
7175 // in the file, where a set bit means that the sample is used
7176 // by the file/instrument.
7177 //
7178 // Note that there are several fields with unknown use. These
7179 // are set to zero.
7180
7181 int sublen = int(pSamples->size() / 8 + 49);
7182 int einfSize = (Instruments + 1) * sublen;
7183
7184 RIFF::Chunk* einf = pRIFF->GetSubChunk(CHUNK_ID_EINF);
7185 if (einf) {
7186 if (einf->GetSize() != einfSize) {
7187 einf->Resize(einfSize);
7188 memset(einf->LoadChunkData(), 0, einfSize);
7189 }
7190 } else if (newFile) {
7191 einf = pRIFF->AddSubChunk(CHUNK_ID_EINF, einfSize);
7192 }
7193 if (einf) {
7194 uint8_t* pData = (uint8_t*) einf->LoadChunkData();
7195
7196 std::map<gig::Sample*,int> sampleMap;
7197 int sampleIdx = 0;
7198 for (Sample* pSample = GetFirstSample(); pSample; pSample = GetNextSample()) {
7199 sampleMap[pSample] = sampleIdx++;
7200 }
7201
7202 int totnbusedsamples = 0;
7203 int totnbusedchannels = 0;
7204 int totnbregions = 0;
7205 int totnbdimregions = 0;
7206 int totnbloops = 0;
7207 int instrumentIdx = 0;
7208
7209 memset(&pData[48], 0, sublen - 48);
7210
7211 for (Instrument* instrument = GetFirstInstrument() ; instrument ;
7212 instrument = GetNextInstrument()) {
7213 int nbusedsamples = 0;
7214 int nbusedchannels = 0;
7215 int nbdimregions = 0;
7216 int nbloops = 0;
7217
7218 memset(&pData[(instrumentIdx + 1) * sublen + 48], 0, sublen - 48);
7219
7220 for (Region* region = instrument->GetFirstRegion() ; region ;
7221 region = instrument->GetNextRegion()) {
7222 for (int i = 0 ; i < region->DimensionRegions ; i++) {
7223 gig::DimensionRegion *d = region->pDimensionRegions[i];
7224 if (d->pSample) {
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;
7230 nbusedsamples++;
7231 nbusedchannels += d->pSample->Channels;
7232
7233 if ((pData[byte] & bit) == 0) {
7234 pData[byte] |= bit;
7235 totnbusedsamples++;
7236 totnbusedchannels += d->pSample->Channels;
7237 }
7238 }
7239 }
7240 if (d->SampleLoops) nbloops++;
7241 }
7242 nbdimregions += region->DimensionRegions;
7243 }
7244 // first 4 bytes unknown - sometimes 0, sometimes length of einf part
7245 // store32(&pData[(instrumentIdx + 1) * sublen], sublen);
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);
7252 // next 8 bytes unknown
7253 store32(&pData[(instrumentIdx + 1) * sublen + 36], instrumentIdx);
7254 store32(&pData[(instrumentIdx + 1) * sublen + 40], (uint32_t) pSamples->size());
7255 // next 4 bytes unknown
7256
7257 totnbregions += instrument->Regions;
7258 totnbdimregions += nbdimregions;
7259 totnbloops += nbloops;
7260 instrumentIdx++;
7261 }
7262 // first 4 bytes unknown - sometimes 0, sometimes length of einf part
7263 // store32(&pData[0], sublen);
7264 store32(&pData[4], totnbusedchannels);
7265 store32(&pData[8], totnbusedsamples);
7266 store32(&pData[12], Instruments);
7267 store32(&pData[16], totnbregions);
7268 store32(&pData[20], totnbdimregions);
7269 store32(&pData[24], totnbloops);
7270 // next 8 bytes unknown
7271 // next 4 bytes unknown, not always 0
7272 store32(&pData[40], (uint32_t) pSamples->size());
7273 // next 4 bytes unknown
7274 }
7275
7276 // update 3crc chunk
7277
7278 // The 3crc chunk contains CRC-32 checksums for the
7279 // samples. When saving a gig file to disk, we first update the 3CRC
7280 // chunk here (in RAM) with the old crc values which we read from the
7281 // 3CRC chunk when we opened the file (available with gig::Sample::crc
7282 // member variable). This step is required, because samples might have
7283 // been deleted by the user since the file was opened, which in turn
7284 // changes the order of the (i.e. old) checksums within the 3crc chunk.
7285 // If a sample was conciously modified by the user (that is if
7286 // Sample::Write() was called later on) then Sample::Write() will just
7287 // update the respective individual checksum(s) directly on disk and
7288 // leaves all other sample checksums untouched.
7289
7290 RIFF::Chunk* _3crc = pRIFF->GetSubChunk(CHUNK_ID_3CRC);
7291 if (_3crc) {
7292 _3crc->Resize(pSamples->size() * 8);
7293 } else /*if (newFile)*/ {
7294 _3crc = pRIFF->AddSubChunk(CHUNK_ID_3CRC, pSamples->size() * 8);
7295 // the order of einf and 3crc is not the same in v2 and v3
7296 if (einf && pVersion && pVersion->major > 2) pRIFF->MoveSubChunk(_3crc, einf);
7297 }
7298 { // must be performed in RAM here ...
7299 uint32_t* pData = (uint32_t*) _3crc->LoadChunkData();
7300 if (pData) {
7301 File::SampleList::iterator iter = pSamples->begin();
7302 File::SampleList::iterator end = pSamples->end();
7303 for (int index = 0; iter != end; ++iter, ++index) {
7304 gig::Sample* pSample = (gig::Sample*) *iter;
7305 pData[index*2] = 1; // always 1
7306 pData[index*2+1] = pSample->crc;
7307 }
7308 }
7309 }
7310 }
7311
7312 void File::UpdateFileOffsets() {
7313 DLS::File::UpdateFileOffsets();
7314
7315 for (Instrument* instrument = GetFirstInstrument(); instrument;
7316 instrument = GetNextInstrument())
7317 {
7318 instrument->UpdateScriptFileOffsets();
7319 }
7320 }
7321
7322 /**
7323 * Enable / disable automatic loading. By default this property is
7324 * enabled and every information is loaded automatically. However
7325 * loading all Regions, DimensionRegions and especially samples might
7326 * take a long time for large .gig files, and sometimes one might only
7327 * be interested in retrieving very superficial informations like the
7328 * amount of instruments and their names. In this case one might disable
7329 * automatic loading to avoid very slow response times.
7330 *
7331 * @e CAUTION: by disabling this property many pointers (i.e. sample
7332 * references) and attributes will have invalid or even undefined
7333 * data! This feature is currently only intended for retrieving very
7334 * superficial information in a very fast way. Don't use it to retrieve
7335 * details like synthesis information or even to modify .gig files!
7336 */
7337 void File::SetAutoLoad(bool b) {
7338 bAutoLoad = b;
7339 }
7340
7341 /**
7342 * Returns whether automatic loading is enabled.
7343 * @see SetAutoLoad()
7344 */
7345 bool File::GetAutoLoad() {
7346 return bAutoLoad;
7347 }
7348
7349 /**
7350 * Returns @c true in case this gig File object uses any gig format
7351 * extension, that is e.g. whether any DimensionRegion object currently
7352 * has any setting effective that would require our "LSDE" RIFF chunk to
7353 * be stored to the gig file.
7354 *
7355 * Right now this is a private method. It is considerable though this method
7356 * to become (in slightly modified form) a public API method in future, i.e.
7357 * to allow instrument editors to visualize and/or warn the user of any gig
7358 * format extension being used. See also comments on
7359 * DimensionRegion::UsesAnyGigFormatExtension() for details about such a
7360 * potential public API change in future.
7361 */
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) {
7367 Instrument* pInstrument = static_cast<gig::Instrument*>(*iter);
7368 if (pInstrument->UsesAnyGigFormatExtension())
7369 return true;
7370 }
7371 return false;
7372 }
7373
7374
7375 // *************** Exception ***************
7376 // *
7377
7378 Exception::Exception() : DLS::Exception() {
7379 }
7380
7381 Exception::Exception(String format, ...) : DLS::Exception() {
7382 va_list arg;
7383 va_start(arg, format);
7384 Message = assemble(format, arg);
7385 va_end(arg);
7386 }
7387
7388 Exception::Exception(String format, va_list arg) : DLS::Exception() {
7389 Message = assemble(format, arg);
7390 }
7391
7392 void Exception::PrintMessage() {
7393 std::cout << "gig::Exception: " << Message << std::endl;
7394 }
7395
7396
7397 // *************** functions ***************
7398 // *
7399
7400 /**
7401 * Returns the name of this C++ library. This is usually "libgig" of
7402 * course. This call is equivalent to RIFF::libraryName() and
7403 * DLS::libraryName().
7404 */
7405 String libraryName() {
7406 return PACKAGE;
7407 }
7408
7409 /**
7410 * Returns version of this C++ library. This call is equivalent to
7411 * RIFF::libraryVersion() and DLS::libraryVersion().
7412 */
7413 String libraryVersion() {
7414 return VERSION;
7415 }
7416
7417 } // namespace gig

  ViewVC Help
Powered by ViewVC