/[svn]/linuxsampler/tags/start/DLS.cpp
ViewVC logotype

Contents of /linuxsampler/tags/start/DLS.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC