libgig 4.4.1
Akai.h
1/*
2 libakai - C++ cross-platform akai sample disk reader
3 Copyright (C) 2002-2003 Sébastien Métrot
4
5 Linux port by Christian Schoenebeck <cuse@users.sourceforge.net> 2003-2019
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20*/
21// Akai.h
22// Info for the akai disk & file format found here:
23// http://www.abel.co.uk/~maxim/akai/akaiinfo.htm
24//
25#ifndef __akai_h__
26#define __akai_h__
27
28// for use with autoconf
29#ifdef HAVE_CONFIG_H
30# include <config.h>
31#endif
32
33#if !defined(_CARBON_) && !defined(__APPLE__) && !defined(WIN32)
34# define LINUX 1
35#endif
36
37#include <stdint.h>
38#include <string>
39#include <stdio.h>
40#include <stdlib.h>
41#include <iostream>
42#include <list>
43#include <fstream>
44#include <sys/types.h>
45#include <sys/stat.h>
46#ifndef _MSC_VER
47# include <sys/fcntl.h>
48#endif
49#if defined(_CARBON_) || defined(__APPLE__) || LINUX
50# include <sys/ioctl.h>
51# include <unistd.h>
52#elif defined(WIN32)
53# include <windows.h>
54 typedef unsigned int uint;
55#endif
56#if LINUX
57# include <linux/cdrom.h>
58#endif
59
60typedef std::string String;
61typedef std::streampos streampos;
62
63class AkaiVolume;
64class AkaiPartition;
65class AkaiDisk;
66
67
68/* current state of the Akai stream */
69typedef enum {
70 akai_stream_ready = 0,
71 akai_stream_end_reached = 1,
72 akai_stream_closed = 2
73} akai_stream_state_t;
74
75/* stream position dependent to these relations */
76typedef enum {
77 akai_stream_start = 0,
78 akai_stream_curpos = 1,
79 akai_stream_end = 2
80} akai_stream_whence_t;
81
82
83/* We need to cache IO access to reduce IO system calls which else would slow
84 down things tremendously. For that we differ between the following two
85 cache sizes:
86
87 CD_FRAMESIZE for CDROM access
88 DISK_CLUSTER_SIZE for normal IO access (e.g. from hard disk)
89
90 Not yet sure if these are the optimum sizes.
91 */
92
93#ifndef CD_FRAMESIZE
94# define CD_FRAMESIZE 2048 /* frame size for Yellow Book, Form 1 */
95#endif
96
97#define DISK_CLUSTER_SIZE 61440 /* 60 kB */
98
99typedef std::string String;
100
110{
111public:
112 DiskImage(const char* path);
113 DiskImage(int disk);
114
115 bool WriteImage(const char* path);
116
117 virtual ~DiskImage();
118
119 virtual akai_stream_state_t GetState() const;
120 virtual int GetPos() const;
121 virtual int SetPos(int Where, akai_stream_whence_t Whence = akai_stream_start);
122
123 virtual int Available (uint WordSize = 1);
124 virtual int Read (void* pData, uint WordCount, uint WordSize);
125
126 void ReadInt8(uint8_t* pData, uint WordCount);
127 void ReadInt16(uint16_t* pData, uint WordCount);
128 void ReadInt32(uint32_t* pData, uint WordCount);
129 int ReadInt8(uint8_t* pData);
130 int ReadInt16(uint16_t* pData);
131 int ReadInt32(uint32_t* pData);
132 uint8_t ReadInt8();
133 uint16_t ReadInt16();
134 uint32_t ReadInt32();
135
136
137 virtual uint GetError() const
138 {
139 return 0;
140 }
141
142 /*virtual const nglChar* GetErrorStr(uint err) const
143 {
144 return _T("No Error");
145 }*/
146
147protected:
148#ifdef WIN32
149 HANDLE mFile;
150#elif defined _CARBON_ || defined(__APPLE__) || LINUX
151 int mFile;
152#endif
153 bool mRegularFile;
154 int mPos;
155 int mCluster;
156 int mClusterSize;
157 int mSize; /* in bytes */
158 /* start and end of the data track we chose (if we're reading from CDROM) */
159 int mStartFrame;
160 int mEndFrame;
161 char* mpCache;
162
163 void OpenStream(const char* path);
164 inline void swapBytes_16(void* Word);
165 inline void swapBytes_32(void* Word);
166
167private:
168 void Init();
169};
170
171
172class Resource
173{
174public:
175 Resource()
176 {
177 mRefCount = 0;
178 }
179 virtual ~Resource()
180 {
181 //NGL_ASSERT(mRefCount==0);
182 }
183 uint Acquire()
184 {
185 return mRefCount++;
186 }
187 uint Release()
188 {
189 uint res;
190 //NGL_ASSERT(mRefCount!=0);
191 mRefCount--;
192 res = mRefCount;
193 if (!mRefCount)
194 delete this;
195 return res;
196 }
197private:
198 uint mRefCount;
199};
200
201class AkaiDirEntry
202{
203public:
204 String mName;
205 uint16_t mType;
206 int mSize;
207 uint16_t mStart;
208 int mIndex;
209};
210
211// AkaiDiskElement:
212class AkaiDiskElement : public Resource
213{
214public:
215 AkaiDiskElement(uint Offset = 0)
216 {
217 mOffset = Offset;
218 }
219
220 uint GetOffset()
221 {
222 return mOffset;
223 }
224
225protected:
226 void SetOffset(uint Offset)
227 {
228 mOffset = Offset;
229 }
230
231 void AkaiToAscii(char * buffer, int length);
232 int ReadFAT(DiskImage* pDisk, AkaiPartition* pPartition, int block);
233 bool ReadDirEntry(DiskImage* pDisk, AkaiPartition* pPartition, AkaiDirEntry& rEntry, int block, int pos);
234private:
235 uint mOffset;
236};
237
238class AkaiSampleLoop
239{
240public:
241 // 4 unsigned Loop 1 marker
242 uint32_t mMarker;
243 // 2 unsigned Loop 1 fine length (65536ths)
244 uint16_t mFineLength;
245 // 4 unsigned Loop 1 coarse length (words)
246 uint32_t mCoarseLength;
247 // 2 unsigned Loop 1 time (msec. or 9999=infinite)
248 uint16_t mTime;
249private:
250 friend class AkaiSample;
251 bool Load(DiskImage* pDisk);
252};
253
254class AkaiSample : public AkaiDiskElement
255{
256public:
257 AkaiDirEntry GetDirEntry();
258 // Length Format Description
259 // --------------------------------------------------------------
260 // 1 3
261 // 1 Not important: 0 for 22050Hz, 1 for 44100Hz
262 // 1 unsigned MIDI root note (C3=60)
263 uint8_t mMidiRootNote;
264 // 12 AKAII Filename
265 String mName;
266 // 1 128
267 // 1 unsigned Number of active loops
268 uint8_t mActiveLoops;
269 // 1 unsigned char First active loop (0 for none)
270 uint8_t mFirstActiveLoop;
271 // 1 0
272 // 1 unsigned Loop mode: 0=in release 1=until release
273 // 2=none 3=play to end
274 uint8_t mLoopMode;
275 // 1 signed Cents tune -50...+50
276 int8_t mTuneCents;
277 // 1 signed Semi tune -50...+50
278 int8_t mTuneSemitones;
279 // 4 0,8,2,0
280 //
281 // 4 unsigned Number of sample words
282 uint32_t mNumberOfSamples;
283 // 4 unsigned Start marker
284 uint32_t mStartMarker;
285 // 4 unsigned End marker
286 uint32_t mEndMarker;
287 //
288 // 4 unsigned Loop 1 marker
289 // 2 unsigned Loop 1 fine length (65536ths)
290 // 4 unsigned Loop 1 coarse length (words)
291 // 2 unsigned Loop 1 time (msec. or 9999=infinite)
292 //
293 // 84 [as above] Loops 2 to 8
294 //
295 AkaiSampleLoop mLoops[8];
296 // 4 0,0,255,255
297 // 2 unsigned Sampling frequency
298 uint16_t mSamplingFrequency;
299 // 1 signed char Loop tune offset -50...+50
300 int8_t mLoopTuneOffset;
301 // 10 0,0,0...
302
303 int16_t* mpSamples;
304
305 bool LoadSampleData();
306 void ReleaseSampleData();
307 int SetPos(int Where, akai_stream_whence_t Whence = akai_stream_start);
308 int Read(void* pBuffer, uint SampleCount);
309 bool LoadHeader();
310private:
311 AkaiSample(DiskImage* pDisk, AkaiVolume* pParent, const AkaiDirEntry& DirEntry);
312 virtual ~AkaiSample();
313
314 friend class AkaiVolume;
315
316 AkaiVolume* mpParent;
317 DiskImage* mpDisk;
318 AkaiDirEntry mDirEntry;
319 bool mHeaderOK;
320 int mPos;
321 int mImageOffset; // actual position in the image where sample starts
322};
323
324class AkaiKeygroupSample : public AkaiDiskElement
325{
326public:
327 // 35-46 sample 1 name 10,10,10... AKAII character set
328 String mName;
329 // 47 low vel 0 0..127
330 uint8_t mLowLevel;
331 // 48 high vel 127 0..127
332 uint8_t mHighLevel;
333 // 49 tune cents 0 -128..127 (-50..50 cents)
334 int8_t mTuneCents;
335 // 50 tune semitones 0 -50..50
336 int8_t mTuneSemitones;
337 // 51 loudness 0 -50..+50
338 int8_t mLoudness;
339 // 52 filter 0 -50..+50
340 int8_t mFilter;
341 // 53 pan 0 -50..+50
342 int8_t mPan;
343 // 54 loop mode 0 0=AS_SAMPLE 1=LOOP_IN_REL
344 // 2=LOOP_UNTIL_REL 3=NO_LOOP
345 // 4=PLAY_TO_END
346 uint8_t mLoopMode;
347 // 55 (internal use) 255
348 // 56 (internal use) 255
349 // 57-58 (internal use) 44,1
350 //
351private:
352 friend class AkaiKeygroup;
353 bool Load(DiskImage* pDisk);
354};
355
356class AkaiEnveloppe
357{
358public:
359 // 13 env1 attack 0 0..99
360 uint8_t mAttack;
361 // 14 env1 decay 30 0..99
362 uint8_t mDecay;
363 // 15 env1 sustain 99 0..99
364 uint8_t mSustain;
365 // 16 env1 release 45 0..99
366 uint8_t mRelease;
367 // 17 env1 vel>attack 0 -50..50
368 int8_t mVelocityToAttack;
369 // 18 env1 vel>release 0 -50..50
370 int8_t mVelocityToRelease;
371 // 19 env1 offvel>release 0 -50..50
372 int8_t mOffVelocityToRelease;
373 // 20 env1 key>dec&rel 0 -50..50
374 int8_t mKeyToDecayAndRelease;
375private:
376 friend class AkaiKeygroup;
377 bool Load(DiskImage* pDisk);
378};
379
380class AkaiKeygroup
381{
382public:
383 // byte description default range/comments
384 // ---------------------------------------------------------------------------
385 // 1 keygroup ID 2
386 // 2-3 next keygroup address 44,1 300,450,600,750.. (16-bit)
387 // 4 low key 24 24..127
388 uint8_t mLowKey;
389 // 5 high key 127 24..127
390 uint8_t mHighKey;
391 // 6 tune cents 0 -128..127 (-50..50 cents)
392 int8_t mTuneCents;
393 // 7 tune semitones 0 -50..50
394 int8_t mTuneSemitones;
395 // 8 filter 99 0..99
396 uint8_t mFilter;
397 // 9 key>filter 12 0..24 semitone/oct
398 uint8_t mKeyToFilter;
399 // 10 vel>filt 0 -50..50
400 uint8_t mVelocityToFilter;
401 // 11 pres>filt 0 -50..50
402 uint8_t mPressureToFilter;
403 // 12 env2>filt 0 -50..50
404 uint8_t mEnveloppe2ToFilter;
405
406 // 13 env1 attack 0 0..99
407 // 14 env1 decay 30 0..99
408 // 15 env1 sustain 99 0..99
409 // 16 env1 release 45 0..99
410 // 17 env1 vel>attack 0 -50..50
411 // 18 env1 vel>release 0 -50..50
412 // 19 env1 offvel>release 0 -50..50
413 // 20 env1 key>dec&rel 0 -50..50
414 // 21 env2 attack 0 0..99
415 // 22 env2 decay 50 0..99
416 // 23 env2 sustain 99 0..99
417 // 24 env2 release 45 0..99
418 // 25 env2 vel>attack 0 -50..50
419 // 26 env2 vel>release 0 -50..50
420 // 27 env2 offvel>release 0 -50..50
421 // 28 env2 key>dec&rel 0 -50..50
422 AkaiEnveloppe mEnveloppes[2];
423
424 // 29 vel>env2>filter 0 -50..50
425 int8_t mVelocityToEnveloppe2ToFilter;
426 // 30 env2>pitch 0 -50..50
427 int8_t mEnveloppe2ToPitch;
428 // 31 vel zone crossfade 1 0=OFF 1=ON
429 bool mVelocityZoneCrossfade;
430 // 32 vel zones used 4
431 uint mVelocityZoneUsed;
432 // 33 (internal use) 255
433 // 34 (internal use) 255
434 //
435
436 // 35-46 sample 1 name 10,10,10... AKAII character set
437 // 47 low vel 0 0..127
438 // 48 high vel 127 0..127
439 // 49 tune cents 0 -128..127 (-50..50 cents)
440 // 50 tune semitones 0 -50..50
441 // 51 loudness 0 -50..+50
442 // 52 filter 0 -50..+50
443 // 53 pan 0 -50..+50
444 // 54 loop mode 0 0=AS_SAMPLE 1=LOOP_IN_REL
445 // 2=LOOP_UNTIL_REL 3=NO_LOOP
446 // 4=PLAY_TO_END
447 // 55 (internal use) 255
448 // 56 (internal use) 255
449 // 57-58 (internal use) 44,1
450 //
451 // 59-82 [repeat 35-58 for sample 2]
452 //
453 // 83-106 [repeat 35-58 for sample 3]
454 //
455 // 107-130 [repeat 35-58 for sample 4]
456 //
457 AkaiKeygroupSample mSamples[4];
458
459 // 131 beat detune 0 -50..50
460 int8_t mBeatDetune;
461 // 132 hold attack until loop 0 0=OFF 1=ON
462 bool mHoldAttackUntilLoop;
463 // 133-136 sample 1-4 key tracking 0 0=TRACK 1=FIXED
464 bool mSampleKeyTracking[4];
465 // 137-140 sample 1-4 aux out offset 0 0..7
466 uint8_t mSampleAuxOutOffset[4];
467 // 141-148 vel>sample start 0 -9999..9999 (16-bit signed)
468 int16_t mVelocityToSampleStart[4];
469 // 149 vel>volume offset 0 -50..50
470 int8_t mVelocityToVolumeOffset[4];
471 // 150 (not used)
472
473private:
474 friend class AkaiProgram;
475 bool Load(DiskImage* pDisk);
476};
477
482class AkaiProgram : public AkaiDiskElement
483{
484public:
485 AkaiDirEntry GetDirEntry();
486 // Samples:
487 uint ListSamples(std::list<String>& rSamples);
488 AkaiSample* GetSample(uint Index);
489 AkaiSample* GetSample(const String& rName);
490
491 // byte description default range/comments
492 // ---------------------------------------------------------------------------
493 // 1 program ID 1
494 // 2-3 first keygroup address 150,0
495 // 4-15 program name 10,10,10... AKAII character set
496 String mName;
497 // 16 MIDI program number 0 0..127
498 uint8_t mMidiProgramNumber;
499 // 17 MIDI channel 0 0..15, 255=OMNI
500 uint8_t mMidiChannel;
501 // 18 polyphony 15 1..16
502 uint8_t mPolyphony;
503 // 19 priority 1 0=LOW 1=NORM 2=HIGH 3=HOLD
504 uint8_t mPriority;
505 // 20 low key 24 24..127
506 uint8_t mLowKey;
507 // 21 high key 127 24..127
508 uint8_t mHighKey;
509 // 22 octave shift 0 -2..2
510 int8_t mOctaveShift;
511 // 23 aux output select 255 0..7, 255=OFF
512 uint8_t mAuxOutputSelect;
513 // 24 mix output level 99 0..99
514 uint8_t mMixOutputSelect;
515 // 25 mix output pan 0 -50..50
516 int8_t mMixPan;
517 // 26 volume 80 0..99
518 uint8_t mVolume;
519 // 27 vel>volume 20 -50..50
520 int8_t mVelocityToVolume;
521 // 28 key>volume 0 -50..50
522 int8_t mKeyToVolume;
523 // 29 pres>volume 0 -50..50
524 int8_t mPressureToVolume;
525 // 30 pan lfo rate 50 0..99
526 uint8_t mPanLFORate;
527 // 31 pan lfo depth 0 0..99
528 uint8_t mPanLFODepth;
529 // 32 pan lfo delay 0 0..99
530 uint8_t mPanLFODelay;
531 // 33 key>pan 0 -50..50
532 int8_t mKeyToPan;
533 // 34 lfo rate 50 0..99
534 uint8_t mLFORate;
535 // 35 lfo depth 0 0..99
536 uint8_t mLFODepth;
537 // 36 lfo delay 0 0..99
538 uint8_t mLFODelay;
539 // 37 mod>lfo depth 30 0..99
540 uint8_t mModulationToLFODepth;
541 // 38 pres>lfo depth 0 0..99
542 uint8_t mPressureToLFODepth;
543 // 39 vel>lfo depth 0 0..99
544 uint8_t mVelocityToLFODepth;
545 // 40 bend>pitch 2 0..12 semitones
546 uint8_t mBendToPitch;
547 // 41 pres>pitch 0 -12..12 semitones
548 int8_t mPressureToPitch;
549 // 42 keygroup crossfade 0 0=OFF 1=ON
550 bool mKeygroupCrossfade;
551 // 43 number of keygroups 1 1..99
552 uint8_t mNumberOfKeygroups;
553 // 44 (internal use) 0 program number
554 // 45-56 key temperament C,C#,D... 0 -25..25 cents
555 int8_t mKeyTemperament[11];
556 // 57 fx output 0 0=OFF 1=ON
557 bool mFXOutput;
558 // 58 mod>pan 0 -50..50
559 int8_t mModulationToPan;
560 // 59 stereo coherence 0 0=OFF 1=ON
561 bool mStereoCoherence;
562 // 60 lfo desync 1 0=OFF 1=ON
563 bool mLFODesync;
564 // 61 pitch law 0 0=LINEAR
565 uint8_t mPitchLaw;
566 // 62 voice re-assign 0 0=OLDEST 1=QUIETEST
567 uint8_t mVoiceReassign;
568 // 63 softped>volume 10 0..99
569 uint8_t mSoftpedToVolume;
570 // 64 softped>attack 10 0..99
571 uint8_t mSoftpedToAttack;
572 // 65 softped>filt 10 0..99
573 uint8_t mSoftpedToFilter;
574 // 66 tune cents 0 -128..127 (-50..50 cents)
575 int8_t mSoftpedToTuneCents;
576 // 67 tune semitones 0 -50..50
577 int8_t mSoftpedToTuneSemitones;
578 // 68 key>lfo rate 0 -50..50
579 int8_t mKeyToLFORate;
580 // 69 key>lfo depth 0 -50..50
581 int8_t mKeyToLFODepth;
582 // 70 key>lfo delay 0 -50..50
583 int8_t mKeyToLFODelay;
584 // 71 voice output scale 1 0=-6dB 1=0dB 2=+12dB
585 uint8_t mVoiceOutputScale;
586 // 72 stereo output scale 0 0=0dB 1=+6dB
587 uint8_t mStereoOutputScale;
588 // 73-150 (not used)
589
590 AkaiKeygroup* mpKeygroups;
591
592 bool Load();
593 AkaiVolume* GetParent()
594 {
595 return mpParent;
596 }
597
598private:
599 AkaiProgram(DiskImage* pDisk, AkaiVolume* pParent, const AkaiDirEntry& DirEntry);
600 virtual ~AkaiProgram();
601
602 friend class AkaiVolume;
603
604 std::list<AkaiSample*> mpSamples;
605 AkaiVolume* mpParent;
606 DiskImage* mpDisk;
607 AkaiDirEntry mDirEntry;
608};
609
618class AkaiVolume : public AkaiDiskElement
619{
620public:
621 AkaiDirEntry GetDirEntry();
622 // Programs:
623 uint ListPrograms(std::list<AkaiDirEntry>& rPrograms);
624 AkaiProgram* GetProgram(uint Index);
625 AkaiProgram* GetProgram(const String& rName);
626
627 // Samples:
628 uint ListSamples(std::list<AkaiDirEntry>& rSamples);
629 AkaiSample* GetSample(uint Index);
630 AkaiSample* GetSample(const String& rName);
631
632 AkaiPartition* GetParent()
633 {
634 return mpParent;
635 }
636
637 bool IsEmpty();
638private:
639 AkaiVolume(DiskImage* pDisk, AkaiPartition* pParent, const AkaiDirEntry& DirEntry);
640 virtual ~AkaiVolume();
641 uint ReadDir();
642
643 friend class AkaiPartition;
644
645 String mName;
646 std::list<AkaiProgram*> mpPrograms;
647 std::list<AkaiSample*> mpSamples;
648 DiskImage* mpDisk;
649 AkaiPartition* mpParent;
650 AkaiDirEntry mDirEntry;
651};
652
661class AkaiPartition : public AkaiDiskElement
662{
663public:
664 // Samples:
665 uint ListVolumes(std::list<AkaiDirEntry>& rVolumes);
666 AkaiVolume* GetVolume(uint Index);
667 AkaiVolume* GetVolume(const String& rName);
668
669 AkaiDisk* GetParent()
670 {
671 return mpParent;
672 }
673
674 bool IsEmpty();
675private:
676 AkaiPartition(DiskImage* pDisk, AkaiDisk* pParent);
677 virtual ~AkaiPartition();
678
679 friend class AkaiDisk;
680
681 String mName;
682 std::list<AkaiVolume*> mpVolumes;
683 AkaiDisk* mpParent;
684 DiskImage* mpDisk;
685};
686
695class AkaiDisk : public AkaiDiskElement
696{
697public:
698 AkaiDisk(DiskImage* pDisk);
699 virtual ~AkaiDisk();
700
701 // Partitions:
702 uint GetPartitionCount();
703 AkaiPartition* GetPartition(uint count);
704
705private:
706 DiskImage* mpDisk;
707 std::list<AkaiPartition*> mpPartitions;
708};
709
710#define AKAI_FILE_ENTRY_SIZE 24
711#define AKAI_DIR_ENTRY_OFFSET 0xca
712#define AKAI_DIR_ENTRY_SIZE 16
713#define AKAI_ROOT_ENTRY_OFFSET 0x0
714
715#define AKAI_PARTITION_END_MARK 0x8000
716#define AKAI_BLOCK_SIZE 0x2000
717
718#define AKAI_FAT_OFFSET 0x70a
719
720#define AKAI_MAX_FILE_ENTRIES_S1000 125 //should be 128 ??
721#define AKAI_MAX_FILE_ENTRIES_S3000 509 // should be 512 ??
722#define AKAI_MAX_DIR_ENTRIES 100
723#define AKAI_TYPE_DIR_S1000 1
724#define AKAI_TYPE_DIR_S3000 3
725
726#define AKAI_PROGRAM_ID 1
727#define AKAI_KEYGROUP_ID 2
728#define AKAI_SAMPLE_ID 3
729
730#endif // __akai_h__
Toplevel AKAI image interpreter.
Definition Akai.h:696
Encapsulates one disk partition of an AKAI disk.
Definition Akai.h:662
AKAI instrument definition.
Definition Akai.h:483
Subdivision of an AKAI disk partition.
Definition Akai.h:619
Accessing AKAI image either from file or a drive (i.e.
Definition Akai.h:110
bool WriteImage(const char *path)
Extract Akai data track and write it into a regular file.
Definition Akai.cpp:1878
virtual int Read(void *pData, uint WordCount, uint WordSize)
Returns number of successfully read words.
Definition Akai.cpp:1660