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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 317 - (show annotations) (download)
Sat Dec 4 14:13:49 2004 UTC (15 years, 7 months ago) by schoenebeck
File size: 20952 byte(s)
* src/DLS.cpp, src/gig.cpp: experimental support for Gigasampler v3 format;
  64 bit file offsets are truncated to 32 bit, 24 bit samples are truncated
  to 16 bit and additional articulation informations are ignored at the
  moment, added some file format compatibility checks
  (patch by Andreas Persson)

1 /***************************************************************************
2 * *
3 * libgig - C++ cross-platform Gigasampler format file loader library *
4 * *
5 * Copyright (C) 2003, 2004 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 "DLS.h"
25
26 namespace DLS {
27
28 // *************** Connection ***************
29 // *
30
31 void Connection::Init(conn_block_t* Header) {
32 Source = (conn_src_t) Header->source;
33 Control = (conn_src_t) Header->control;
34 Destination = (conn_dst_t) Header->destination;
35 Scale = Header->scale;
36 SourceTransform = (conn_trn_t) CONN_TRANSFORM_SRC(Header->transform);
37 ControlTransform = (conn_trn_t) CONN_TRANSFORM_CTL(Header->transform);
38 DestinationTransform = (conn_trn_t) CONN_TRANSFORM_DST(Header->transform);
39 SourceInvert = CONN_TRANSFORM_INVERT_SRC(Header->transform);
40 SourceBipolar = CONN_TRANSFORM_BIPOLAR_SRC(Header->transform);
41 ControlInvert = CONN_TRANSFORM_INVERT_CTL(Header->transform);
42 ControlBipolar = CONN_TRANSFORM_BIPOLAR_CTL(Header->transform);
43 }
44
45
46
47 // *************** Articulation ***************
48 // *
49
50 Articulation::Articulation(RIFF::List* artList) {
51 if (artList->GetListType() != LIST_TYPE_ART2 &&
52 artList->GetListType() != LIST_TYPE_ART1) {
53 throw DLS::Exception("<art1-list> or <art2-list> chunk expected");
54 }
55 uint32_t headerSize = artList->ReadUint32();
56 Connections = artList->ReadUint32();
57 artList->SetPos(headerSize);
58
59 pConnections = new Connection[Connections];
60 Connection::conn_block_t connblock;
61 for (uint32_t i = 0; i <= Connections; i++) {
62 artList->Read(&connblock.source, 1, 2);
63 artList->Read(&connblock.control, 1, 2);
64 artList->Read(&connblock.destination, 1, 2);
65 artList->Read(&connblock.transform, 1, 2);
66 artList->Read(&connblock.scale, 1, 4);
67 pConnections[i].Init(&connblock);
68 }
69 }
70
71 Articulation::~Articulation() {
72 if (pConnections) delete[] pConnections;
73 }
74
75
76
77 // *************** Articulator ***************
78 // *
79
80 Articulator::Articulator(RIFF::List* ParentList) {
81 pParentList = ParentList;
82 pArticulations = NULL;
83 }
84
85 Articulation* Articulator::GetFirstArticulation() {
86 if (!pArticulations) LoadArticulations();
87 if (!pArticulations) return NULL;
88 ArticulationsIterator = pArticulations->begin();
89 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
90 }
91
92 Articulation* Articulator::GetNextArticulation() {
93 if (!pArticulations) return NULL;
94 ArticulationsIterator++;
95 return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL;
96 }
97
98 void Articulator::LoadArticulations() {
99 // prefer articulation level 2
100 RIFF::List* lart = pParentList->GetSubList(LIST_TYPE_LAR2);
101 if (!lart) lart = pParentList->GetSubList(LIST_TYPE_LART);
102 if (lart) {
103 uint32_t artCkType = (lart->GetListType() == LIST_TYPE_LAR2) ? LIST_TYPE_ART2
104 : LIST_TYPE_ART1;
105 RIFF::List* art = lart->GetFirstSubList();
106 while (art) {
107 if (art->GetListType() == artCkType) {
108 if (!pArticulations) pArticulations = new ArticulationList;
109 pArticulations->push_back(new Articulation(art));
110 }
111 art = lart->GetNextSubList();
112 }
113 }
114 }
115
116 Articulator::~Articulator() {
117 if (pArticulations) {
118 ArticulationList::iterator iter = pArticulations->begin();
119 ArticulationList::iterator end = pArticulations->end();
120 while (iter != end) {
121 delete *iter;
122 iter++;
123 }
124 delete pArticulations;
125 }
126 }
127
128
129
130 // *************** Info ***************
131 // *
132
133 Info::Info(RIFF::List* list) {
134 if (list) {
135 RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);
136 if (lstINFO) {
137 LoadString(CHUNK_ID_INAM, lstINFO, Name);
138 LoadString(CHUNK_ID_IARL, lstINFO, ArchivalLocation);
139 LoadString(CHUNK_ID_ICRD, lstINFO, CreationDate);
140 LoadString(CHUNK_ID_ICMT, lstINFO, Comments);
141 LoadString(CHUNK_ID_IPRD, lstINFO, Product);
142 LoadString(CHUNK_ID_ICOP, lstINFO, Copyright);
143 LoadString(CHUNK_ID_IART, lstINFO, Artists);
144 LoadString(CHUNK_ID_IGNR, lstINFO, Genre);
145 LoadString(CHUNK_ID_IKEY, lstINFO, Keywords);
146 LoadString(CHUNK_ID_IENG, lstINFO, Engineer);
147 LoadString(CHUNK_ID_ITCH, lstINFO, Technician);
148 LoadString(CHUNK_ID_ISFT, lstINFO, Software);
149 LoadString(CHUNK_ID_IMED, lstINFO, Medium);
150 LoadString(CHUNK_ID_ISRC, lstINFO, Source);
151 LoadString(CHUNK_ID_ISRF, lstINFO, SourceForm);
152 LoadString(CHUNK_ID_ICMS, lstINFO, Commissioned);
153 }
154 }
155 }
156
157
158
159 // *************** Resource ***************
160 // *
161
162 Resource::Resource(Resource* Parent, RIFF::List* lstResource) {
163 pParent = Parent;
164
165 pInfo = new Info(lstResource);
166
167 RIFF::Chunk* ckDLSID = lstResource->GetSubChunk(CHUNK_ID_DLID);
168 if (ckDLSID) {
169 pDLSID = new dlsid_t;
170 ckDLSID->Read(&pDLSID->ulData1, 1, 4);
171 ckDLSID->Read(&pDLSID->usData2, 1, 2);
172 ckDLSID->Read(&pDLSID->usData3, 1, 2);
173 ckDLSID->Read(pDLSID->abData, 8, 1);
174 }
175 else pDLSID = NULL;
176 }
177
178 Resource::~Resource() {
179 if (pDLSID) delete pDLSID;
180 if (pInfo) delete pInfo;
181 }
182
183
184
185 // *************** Sampler ***************
186 // *
187
188 Sampler::Sampler(RIFF::List* ParentList) {
189 RIFF::Chunk* wsmp = ParentList->GetSubChunk(CHUNK_ID_WSMP);
190 if (!wsmp) throw DLS::Exception("Mandatory <wsmp> chunk not found.");
191 uint32_t headersize = wsmp->ReadUint32();
192 UnityNote = wsmp->ReadUint16();
193 FineTune = wsmp->ReadInt16();
194 Gain = wsmp->ReadInt32();
195 SamplerOptions = wsmp->ReadUint32();
196 NoSampleDepthTruncation = SamplerOptions & F_WSMP_NO_TRUNCATION;
197 NoSampleCompression = SamplerOptions & F_WSMP_NO_COMPRESSION;
198 SampleLoops = wsmp->ReadUint32();
199 pSampleLoops = (SampleLoops) ? new sample_loop_t[SampleLoops] : NULL;
200 wsmp->SetPos(headersize);
201 for (uint32_t i = 0; i < SampleLoops; i++) {
202 wsmp->Read(pSampleLoops + i, 4, 4);
203 if (pSampleLoops[i].Size > sizeof(sample_loop_t)) { // if loop struct was extended
204 wsmp->SetPos(pSampleLoops[i].Size - sizeof(sample_loop_t), RIFF::stream_curpos);
205 }
206 }
207 }
208
209 Sampler::~Sampler() {
210 if (pSampleLoops) delete[] pSampleLoops;
211 }
212
213
214
215 // *************** Sample ***************
216 // *
217
218 Sample::Sample(File* pFile, RIFF::List* waveList, unsigned long WavePoolOffset) : Resource(pFile, waveList) {
219 ulWavePoolOffset = WavePoolOffset - LIST_HEADER_SIZE;
220 pCkFormat = waveList->GetSubChunk(CHUNK_ID_FMT);
221 pCkData = waveList->GetSubChunk(CHUNK_ID_DATA);
222 if (!pCkFormat || !pCkData) throw DLS::Exception("Mandatory chunks in wave list not found.");
223
224 // common fields
225 FormatTag = pCkFormat->ReadUint16();
226 Channels = pCkFormat->ReadUint16();
227 SamplesPerSecond = pCkFormat->ReadUint32();
228 AverageBytesPerSecond = pCkFormat->ReadUint32();
229 BlockAlign = pCkFormat->ReadUint16();
230
231 // PCM format specific
232 if (FormatTag == WAVE_FORMAT_PCM) {
233 BitDepth = pCkFormat->ReadUint16();
234 FrameSize = (FormatTag == WAVE_FORMAT_PCM) ? (BitDepth / 8) * Channels
235 : 0;
236 SamplesTotal = (FormatTag == WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize
237 : 0;
238 }
239 else {
240 BitDepth = 0;
241 FrameSize = 0;
242 SamplesTotal = 0;
243 }
244 }
245
246 void* Sample::LoadSampleData() {
247 return pCkData->LoadChunkData();
248 }
249
250 void Sample::ReleaseSampleData() {
251 pCkData->ReleaseChunkData();
252 }
253
254 /**
255 * Sets the position within the sample (in sample points, not in
256 * bytes). Use this method and <i>Read()</i> if you don't want to load
257 * the sample into RAM, thus for disk streaming.
258 *
259 * @param SampleCount number of sample points
260 * @param Whence to which relation \a SampleCount refers to
261 */
262 unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {
263 if (FormatTag != WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format
264 unsigned long orderedBytes = SampleCount * FrameSize;
265 unsigned long result = pCkData->SetPos(orderedBytes, Whence);
266 return (result == orderedBytes) ? SampleCount
267 : result / FrameSize;
268 }
269
270 /**
271 * Reads \a SampleCount number of sample points from the current
272 * position into the buffer pointed by \a pBuffer and increments the
273 * position within the sample. Use this method and <i>SetPos()</i> if you
274 * don't want to load the sample into RAM, thus for disk streaming.
275 *
276 * @param pBuffer destination buffer
277 * @param SampleCount number of sample points to read
278 */
279 unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
280 if (FormatTag != WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format
281 return pCkData->Read(pBuffer, SampleCount, FrameSize); // FIXME: channel inversion due to endian correction?
282 }
283
284
285
286 // *************** Region ***************
287 // *
288
289 Region::Region(Instrument* pInstrument, RIFF::List* rgnList) : Resource(pInstrument, rgnList), Articulator(rgnList), Sampler(rgnList) {
290 pCkRegion = rgnList;
291
292 RIFF::Chunk* rgnh = rgnList->GetSubChunk(CHUNK_ID_RGNH);
293 rgnh->Read(&KeyRange, 2, 2);
294 rgnh->Read(&VelocityRange, 2, 2);
295 uint16_t optionflags = rgnh->ReadUint16();
296 SelfNonExclusive = optionflags & F_RGN_OPTION_SELFNONEXCLUSIVE;
297 KeyGroup = rgnh->ReadUint16();
298 // Layer is optional
299 if (rgnh->RemainingBytes() >= sizeof(uint16_t)) {
300 rgnh->Read(&Layer, 1, sizeof(uint16_t));
301 }
302 else Layer = 0;
303
304 RIFF::Chunk* wlnk = rgnList->GetSubChunk(CHUNK_ID_WLNK);
305 optionflags = wlnk->ReadUint16();
306 PhaseMaster = optionflags & F_WAVELINK_PHASE_MASTER;
307 MultiChannel = optionflags & F_WAVELINK_MULTICHANNEL;
308 PhaseGroup = wlnk->ReadUint16();
309 Channel = wlnk->ReadUint32();
310 WavePoolTableIndex = wlnk->ReadUint32();
311
312 pSample = NULL;
313 }
314
315 Region::~Region() {
316 }
317
318 Sample* Region::GetSample() {
319 if (pSample) return pSample;
320 File* file = (File*) GetParent()->GetParent();
321 unsigned long soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
322 Sample* sample = file->GetFirstSample();
323 while (sample) {
324 if (sample->ulWavePoolOffset == soughtoffset) return (pSample = sample);
325 sample = file->GetNextSample();
326 }
327 return NULL;
328 }
329
330
331
332 // *************** Instrument ***************
333 // *
334
335 Instrument::Instrument(File* pFile, RIFF::List* insList) : Resource(pFile, insList), Articulator(insList) {
336 pCkInstrument = insList;
337
338 RIFF::Chunk* insh = pCkInstrument->GetSubChunk(CHUNK_ID_INSH);
339 if (!insh) throw DLS::Exception("Mandatory chunks in <lins> list chunk not found.");
340 Regions = insh->ReadUint32();
341 midi_locale_t locale;
342 insh->Read(&locale, 2, 4);
343 MIDIProgram = locale.instrument;
344 IsDrum = locale.bank & DRUM_TYPE_MASK;
345 MIDIBankCoarse = (uint8_t) MIDI_BANK_COARSE(locale.bank);
346 MIDIBankFine = (uint8_t) MIDI_BANK_FINE(locale.bank);
347 MIDIBank = MIDI_BANK_MERGE(MIDIBankCoarse, MIDIBankFine);
348
349 pRegions = NULL;
350 }
351
352 Region* Instrument::GetFirstRegion() {
353 if (!pRegions) LoadRegions();
354 if (!pRegions) return NULL;
355 RegionsIterator = pRegions->begin();
356 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
357 }
358
359 Region* Instrument::GetNextRegion() {
360 if (!pRegions) return NULL;
361 RegionsIterator++;
362 return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL;
363 }
364
365 void Instrument::LoadRegions() {
366 RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
367 if (!lrgn) throw DLS::Exception("Mandatory chunks in <ins > chunk not found.");
368 uint32_t regionCkType = (lrgn->GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN; // prefer regions level 2
369 RIFF::List* rgn = lrgn->GetFirstSubList();
370 while (rgn) {
371 if (rgn->GetListType() == regionCkType) {
372 if (!pRegions) pRegions = new RegionList;
373 pRegions->push_back(new Region(this, rgn));
374 }
375 rgn = lrgn->GetNextSubList();
376 }
377 }
378
379 Instrument::~Instrument() {
380 if (pRegions) {
381 RegionList::iterator iter = pRegions->begin();
382 RegionList::iterator end = pRegions->end();
383 while (iter != end) {
384 delete *iter;
385 iter++;
386 }
387 delete pRegions;
388 }
389 }
390
391
392
393 // *************** File ***************
394 // *
395
396 File::File(RIFF::File* pRIFF) : Resource(NULL, pRIFF) {
397 if (!pRIFF) throw DLS::Exception("NULL pointer reference to RIFF::File object.");
398 this->pRIFF = pRIFF;
399
400 RIFF::Chunk* ckVersion = pRIFF->GetSubChunk(CHUNK_ID_VERS);
401 if (ckVersion) {
402 pVersion = new version_t;
403 ckVersion->Read(pVersion, 4, 2);
404 }
405 else pVersion = NULL;
406
407 RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
408 if (!colh) throw DLS::Exception("Mandatory chunks in RIFF list chunk not found.");
409 Instruments = colh->ReadUint32();
410
411 RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
412 if (!ptbl) throw DLS::Exception("Mandatory <ptbl> chunk not found.");
413 uint32_t headersize = ptbl->ReadUint32();
414 WavePoolCount = ptbl->ReadUint32();
415 pWavePoolTable = new uint32_t[WavePoolCount];
416 ptbl->SetPos(headersize);
417
418 // Check for 64 bit offsets (used in gig v3 files)
419 if (ptbl->GetSize() - headersize == WavePoolCount * 8) {
420 for (int i = 0 ; i < WavePoolCount ; i++) {
421 // Just ignore the upper bits for now
422 uint32_t upper = ptbl->ReadUint32();
423 pWavePoolTable[i] = ptbl->ReadUint32();
424 if (upper || (pWavePoolTable[i] & 0x80000000))
425 throw DLS::Exception("Files larger than 2 GB not yet supported");
426 }
427 }
428 else ptbl->Read(pWavePoolTable, WavePoolCount, sizeof(uint32_t));
429
430 pSamples = NULL;
431 pInstruments = NULL;
432 Instruments = 0;
433 }
434
435 File::~File() {
436 if (pInstruments) {
437 InstrumentList::iterator iter = pInstruments->begin();
438 InstrumentList::iterator end = pInstruments->end();
439 while (iter != end) {
440 delete *iter;
441 iter++;
442 }
443 delete pInstruments;
444 }
445
446 if (pSamples) {
447 SampleList::iterator iter = pSamples->begin();
448 SampleList::iterator end = pSamples->end();
449 while (iter != end) {
450 delete *iter;
451 iter++;
452 }
453 delete pSamples;
454 }
455
456 if (pWavePoolTable) delete[] pWavePoolTable;
457 if (pVersion) delete pVersion;
458 }
459
460 Sample* File::GetFirstSample() {
461 if (!pSamples) LoadSamples();
462 if (!pSamples) return NULL;
463 SamplesIterator = pSamples->begin();
464 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
465 }
466
467 Sample* File::GetNextSample() {
468 if (!pSamples) return NULL;
469 SamplesIterator++;
470 return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL;
471 }
472
473 void File::LoadSamples() {
474 RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
475 if (wvpl) {
476 unsigned long wvplFileOffset = wvpl->GetFilePos();
477 RIFF::List* wave = wvpl->GetFirstSubList();
478 while (wave) {
479 if (wave->GetListType() == LIST_TYPE_WAVE) {
480 if (!pSamples) pSamples = new SampleList;
481 unsigned long waveFileOffset = wave->GetFilePos();
482 pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset));
483 }
484 wave = wvpl->GetNextSubList();
485 }
486 }
487 else { // Seen a dwpl list chunk instead of a wvpl list chunk in some file (officially not DLS compliant)
488 RIFF::List* dwpl = pRIFF->GetSubList(LIST_TYPE_DWPL);
489 if (dwpl) {
490 unsigned long dwplFileOffset = dwpl->GetFilePos();
491 RIFF::List* wave = dwpl->GetFirstSubList();
492 while (wave) {
493 if (wave->GetListType() == LIST_TYPE_WAVE) {
494 if (!pSamples) pSamples = new SampleList;
495 unsigned long waveFileOffset = wave->GetFilePos();
496 pSamples->push_back(new Sample(this, wave, waveFileOffset - dwplFileOffset));
497 }
498 wave = dwpl->GetNextSubList();
499 }
500 }
501 }
502 }
503
504 Instrument* File::GetFirstInstrument() {
505 if (!pInstruments) LoadInstruments();
506 if (!pInstruments) return NULL;
507 InstrumentsIterator = pInstruments->begin();
508 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
509 }
510
511 Instrument* File::GetNextInstrument() {
512 if (!pInstruments) return NULL;
513 InstrumentsIterator++;
514 return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL;
515 }
516
517 void File::LoadInstruments() {
518 RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
519 if (lstInstruments) {
520 RIFF::List* lstInstr = lstInstruments->GetFirstSubList();
521 while (lstInstr) {
522 if (lstInstr->GetListType() == LIST_TYPE_INS) {
523 if (!pInstruments) pInstruments = new InstrumentList;
524 pInstruments->push_back(new Instrument(this, lstInstr));
525 }
526 lstInstr = lstInstruments->GetNextSubList();
527 }
528 }
529 }
530
531
532
533 // *************** Exception ***************
534 // *
535
536 Exception::Exception(String Message) : RIFF::Exception(Message) {
537 }
538
539 void Exception::PrintMessage() {
540 std::cout << "DLS::Exception: " << Message << std::endl;
541 }
542
543 } // namespace DLS

  ViewVC Help
Powered by ViewVC