This file is indexed.

/usr/include/libgig/Akai.h is in libgig-dev 4.1.0~repack-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
/*
  libakai - C++ cross-platform akai sample disk reader
  Copyright (C) 2002-2003 Sébastien Métrot

  Linux port by Christian Schoenebeck <cuse@users.sourceforge.net> 2003-2014
  
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
// Akai.h
// Info for the akai disk & file format found here:
// http://www.abel.co.uk/~maxim/akai/akaiinfo.htm
//
#ifndef __akai_h__
#define __akai_h__

// for use with autoconf
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#if !defined(_CARBON_) && !defined(__APPLE__) && !defined(WIN32)
# define LINUX 1
#endif

#include <stdint.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <list>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>

#if defined(_CARBON_) || defined(__APPLE__) || LINUX
# include <sys/ioctl.h>
# include <unistd.h>
#elif defined(WIN32)
# include <windows.h>
  typedef unsigned int   uint;
#endif
#if LINUX
# include <linux/cdrom.h>
#endif

typedef std::string String;
typedef std::streampos streampos;

class AkaiVolume;
class AkaiPartition;
class AkaiDisk;


/* current state of the Akai stream */
typedef enum {
  akai_stream_ready       = 0,
  akai_stream_end_reached = 1,
  akai_stream_closed      = 2
} akai_stream_state_t;

/* stream position dependent to these relations */
typedef enum {
  akai_stream_start  = 0,
  akai_stream_curpos = 1,
  akai_stream_end    = 2
} akai_stream_whence_t;


/* We need to cache IO access to reduce IO system calls which else would slow
   down things tremendously. For that we differ between the following two
   cache sizes:

   CD_FRAMESIZE       for CDROM access
   DISK_CLUSTER_SIZE  for normal IO access (e.g. from hard disk)

   Not yet sure if these are the optimum sizes.
 */

#ifndef CD_FRAMESIZE
#  define CD_FRAMESIZE 2048 /* frame size for Yellow Book, Form 1 */
#endif

#define DISK_CLUSTER_SIZE 61440 /* 60 kB */

typedef std::string String;

/** @brief Accessing AKAI image either from file or a drive (i.e. CDROM).
 *
 * This class implements a hardware abstraction layer, providing an abstract
 * streaming API to read from AKAI data images, no matter if the AKAI image is
 * already available as image file or whether the respective hardware drive
 * needs to be accessed directly (i.e. CDROM drive, ZIP drive). So the main task
 * of this class is isolating operating system dependent file/hardware access.
 */
class DiskImage
{
public:
  DiskImage(const char* path); ///< Open an image from a file.
  DiskImage(int disk); ///< Open an image from a device number (0='a:', 1='b:', etc...).

  bool WriteImage(const char* path); ///< Extract Akai data track and write it into a regular file.

  virtual ~DiskImage();

  virtual akai_stream_state_t GetState() const;
  virtual int GetPos() const;
  virtual int SetPos(int Where, akai_stream_whence_t Whence = akai_stream_start);

  virtual int Available (uint WordSize = 1);
  virtual int Read (void* pData, uint WordCount, uint WordSize); ///< Returns number of successfully read words.

  void     ReadInt8(uint8_t* pData, uint WordCount);
  void     ReadInt16(uint16_t* pData, uint WordCount);
  void     ReadInt32(uint32_t* pData, uint WordCount);
  int      ReadInt8(uint8_t* pData);    ///< Returns number of successfully read 8 Bit words.
  int      ReadInt16(uint16_t* pData);  ///< Returns number of successfully read 16 Bit words.
  int      ReadInt32(uint32_t* pData);  ///< Returns number of successfully read 32 Bit words.
  uint8_t  ReadInt8();
  uint16_t ReadInt16();
  uint32_t ReadInt32();


  virtual uint GetError() const
  {
    return 0;
  }

  /*virtual const nglChar* GetErrorStr(uint err) const
  {
    return _T("No Error");
  }*/

protected:
#ifdef WIN32
  HANDLE mFile;
#elif defined _CARBON_ || defined(__APPLE__) || LINUX
  int mFile;
#endif
  bool mRegularFile;
  int mPos;
  int mCluster;
  int mClusterSize;
  int mSize; /* in bytes */
  /* start and end of the data track we chose (if we're reading from CDROM) */
  int mStartFrame;
  int mEndFrame;
  char* mpCache;

  void OpenStream(const char* path);
  inline void swapBytes_16(void* Word);
  inline void swapBytes_32(void* Word);

private:
  void Init();
};


class Resource
{
public:
  Resource()
  {
    mRefCount = 0;
  }
  virtual ~Resource()
  {
    //NGL_ASSERT(mRefCount==0);
  }
  uint Acquire()
  {
    return mRefCount++;
  }
  uint Release()
  {
    uint res;
    //NGL_ASSERT(mRefCount!=0);
    mRefCount--;
    res = mRefCount;
    if (!mRefCount)
      delete this;
    return res;
  }
private:
  uint mRefCount;
};

class AkaiDirEntry
{
public:
  String mName;
  uint16_t mType;
  int mSize;
  uint16_t mStart;
  int mIndex;
};

// AkaiDiskElement:
class AkaiDiskElement : public Resource
{
public:
  AkaiDiskElement(uint Offset = 0)
  {
    mOffset = Offset;
  }

  uint GetOffset()
  {
    return mOffset;
  }

protected:
  void SetOffset(uint Offset)
  {
    mOffset = Offset;
  }

  void AkaiToAscii(char * buffer, int length);
  int ReadFAT(DiskImage* pDisk, AkaiPartition* pPartition, int block);
  bool ReadDirEntry(DiskImage* pDisk, AkaiPartition* pPartition, AkaiDirEntry& rEntry, int block, int pos);
private:
  uint mOffset;
};

class AkaiSampleLoop
{
public:
  //    4     unsigned    Loop 1 marker
  uint32_t mMarker;
  //    2     unsigned    Loop 1 fine length   (65536ths)
  uint16_t mFineLength;
  //    4     unsigned    Loop 1 coarse length (words)
  uint32_t mCoarseLength;
  //    2     unsigned    Loop 1 time          (msec. or 9999=infinite)
  uint16_t mTime;
private:
  friend class AkaiSample;
  bool Load(DiskImage* pDisk);
};

class AkaiSample : public AkaiDiskElement
{
public:
  AkaiDirEntry GetDirEntry();
  // Length   Format      Description
  // --------------------------------------------------------------
  //    1                 3
  //    1                 Not important: 0 for 22050Hz, 1 for 44100Hz
  //    1     unsigned    MIDI root note (C3=60)
  uint8_t mMidiRootNote;
  //   12     AKAII       Filename
  String mName;
  //    1                 128
  //    1     unsigned    Number of active loops
  uint8_t mActiveLoops;
  //    1     unsigned char       First active loop (0 for none)
  uint8_t mFirstActiveLoop;
  //    1                         0
  //    1     unsigned    Loop mode: 0=in release 1=until release
  //                                 2=none       3=play to end
  uint8_t mLoopMode;
  //    1     signed      Cents tune -50...+50
  int8_t mTuneCents;
  //    1     signed      Semi tune  -50...+50
  int8_t mTuneSemitones;
  //    4                 0,8,2,0
  //
  //    4     unsigned    Number of sample words
  uint32_t mNumberOfSamples;
  //    4     unsigned    Start marker
  uint32_t mStartMarker;
  //    4     unsigned    End marker
  uint32_t mEndMarker;
  //
  //    4     unsigned    Loop 1 marker
  //    2     unsigned    Loop 1 fine length   (65536ths)
  //    4     unsigned    Loop 1 coarse length (words)
  //    2     unsigned    Loop 1 time          (msec. or 9999=infinite)
  //
  //   84     [as above]  Loops 2 to 8
  //
  AkaiSampleLoop mLoops[8];
  //    4                 0,0,255,255
  //    2     unsigned    Sampling frequency
  uint16_t mSamplingFrequency;
  //    1     signed char         Loop tune offset -50...+50
  int8_t mLoopTuneOffset;
  //   10                 0,0,0...

  int16_t* mpSamples;

  bool LoadSampleData(); ///< Load sample into RAM
  void ReleaseSampleData(); ///< release the samples once you used them if you don't want to be bothered to
  int SetPos(int Where, akai_stream_whence_t Whence = akai_stream_start); ///< Use this method and Read() if you don't want to load the sample into RAM, thus for disk streaming.
  int Read(void* pBuffer, uint SampleCount); ///< Use this method and SetPos() if you don't want to load the sample into RAM, thus for disk streaming.
  bool LoadHeader();
private:
  AkaiSample(DiskImage* pDisk, AkaiVolume* pParent, const AkaiDirEntry& DirEntry);
  virtual ~AkaiSample();

  friend class AkaiVolume;

  AkaiVolume* mpParent;
  DiskImage* mpDisk;
  AkaiDirEntry mDirEntry;
  bool mHeaderOK;
  int mPos;
  int mImageOffset; // actual position in the image where sample starts
};

class AkaiKeygroupSample : public AkaiDiskElement
{
public:
  //     35-46   sample 1 name               10,10,10... AKAII character set
  String mName;
  //     47      low vel                     0           0..127
  uint8_t mLowLevel;
  //     48      high vel                    127         0..127
  uint8_t mHighLevel;
  //     49      tune cents                  0           -128..127 (-50..50 cents)
  int8_t mTuneCents;
  //     50      tune semitones              0           -50..50
  int8_t mTuneSemitones;
  //     51      loudness                    0           -50..+50
  int8_t mLoudness;
  //     52      filter                      0           -50..+50
  int8_t mFilter;
  //     53      pan                         0           -50..+50
  int8_t mPan;
  //     54      loop mode                   0           0=AS_SAMPLE 1=LOOP_IN_REL 
  //                                                     2=LOOP_UNTIL_REL 3=NO_LOOP 
  //                                                     4=PLAY_TO_END
  uint8_t mLoopMode;
  //     55      (internal use)              255
  //     56      (internal use)              255
  //     57-58   (internal use)              44,1
  //
private:
  friend class AkaiKeygroup;
  bool Load(DiskImage* pDisk);
};

class AkaiEnveloppe
{
public:
  //     13      env1 attack                 0           0..99
  uint8_t mAttack;
  //     14      env1 decay                  30          0..99
  uint8_t mDecay;
  //     15      env1 sustain                99          0..99
  uint8_t mSustain;
  //     16      env1 release                45          0..99
  uint8_t mRelease;
  //     17      env1 vel>attack             0           -50..50
  int8_t mVelocityToAttack;
  //     18      env1 vel>release            0           -50..50 
  int8_t mVelocityToRelease;
  //     19      env1 offvel>release         0           -50..50
  int8_t mOffVelocityToRelease;
  //     20      env1 key>dec&rel            0           -50..50
  int8_t mKeyToDecayAndRelease;
private:
  friend class AkaiKeygroup;
  bool Load(DiskImage* pDisk);
};

class AkaiKeygroup
{
public:
  //    byte     description                 default     range/comments
  //   ---------------------------------------------------------------------------
  //     1       keygroup ID                 2
  //     2-3     next keygroup address       44,1        300,450,600,750.. (16-bit)         
  //     4       low key                     24          24..127
  uint8_t mLowKey;
  //     5       high key                    127         24..127
  uint8_t mHighKey;
  //     6       tune cents                  0           -128..127 (-50..50 cents)
  int8_t mTuneCents;
  //     7       tune semitones              0           -50..50
  int8_t mTuneSemitones;
  //     8       filter                      99          0..99
  uint8_t mFilter;
  //     9       key>filter                  12          0..24 semitone/oct
  uint8_t mKeyToFilter;
  //     10      vel>filt                    0           -50..50
  uint8_t mVelocityToFilter;
  //     11      pres>filt                   0           -50..50
  uint8_t mPressureToFilter;
  //     12      env2>filt                   0           -50..50
  uint8_t mEnveloppe2ToFilter;

  //     13      env1 attack                 0           0..99
  //     14      env1 decay                  30          0..99
  //     15      env1 sustain                99          0..99
  //     16      env1 release                45          0..99
  //     17      env1 vel>attack             0           -50..50
  //     18      env1 vel>release            0           -50..50 
  //     19      env1 offvel>release         0           -50..50
  //     20      env1 key>dec&rel            0           -50..50
  //     21      env2 attack                 0           0..99
  //     22      env2 decay                  50          0..99
  //     23      env2 sustain                99          0..99
  //     24      env2 release                45          0..99
  //     25      env2 vel>attack             0           -50..50
  //     26      env2 vel>release            0           -50..50
  //     27      env2 offvel>release         0           -50..50
  //     28      env2 key>dec&rel            0           -50..50
  AkaiEnveloppe mEnveloppes[2];

  //     29      vel>env2>filter             0           -50..50
  int8_t mVelocityToEnveloppe2ToFilter;
  //     30      env2>pitch                  0           -50..50
  int8_t mEnveloppe2ToPitch;
  //     31      vel zone crossfade          1           0=OFF 1=ON
  bool mVelocityZoneCrossfade;
  //     32      vel zones used              4           
  uint mVelocityZoneUsed;
  //     33      (internal use)              255         
  //     34      (internal use)              255         
  //

  //     35-46   sample 1 name               10,10,10... AKAII character set
  //     47      low vel                     0           0..127
  //     48      high vel                    127         0..127
  //     49      tune cents                  0           -128..127 (-50..50 cents)
  //     50      tune semitones              0           -50..50
  //     51      loudness                    0           -50..+50
  //     52      filter                      0           -50..+50
  //     53      pan                         0           -50..+50
  //     54      loop mode                   0           0=AS_SAMPLE 1=LOOP_IN_REL 
  //                                                     2=LOOP_UNTIL_REL 3=NO_LOOP 
  //                                                     4=PLAY_TO_END
  //     55      (internal use)              255
  //     56      (internal use)              255
  //     57-58   (internal use)              44,1
  //
  //     59-82   [repeat 35-58 for sample 2]
  //
  //     83-106  [repeat 35-58 for sample 3]
  //
  //     107-130 [repeat 35-58 for sample 4]
  //
  AkaiKeygroupSample mSamples[4];
  
  //     131     beat detune                 0           -50..50
  int8_t mBeatDetune;
  //     132     hold attack until loop      0           0=OFF 1=ON
  bool mHoldAttackUntilLoop;
  //     133-136 sample 1-4 key tracking     0           0=TRACK 1=FIXED
  bool mSampleKeyTracking[4];
  //     137-140 sample 1-4 aux out offset   0           0..7
  uint8_t mSampleAuxOutOffset[4];
  //     141-148 vel>sample start            0           -9999..9999 (16-bit signed)
  int16_t mVelocityToSampleStart[4];
  //     149     vel>volume offset           0           -50..50
  int8_t mVelocityToVolumeOffset[4];
  //     150     (not used)

private:
  friend class AkaiProgram;
  bool Load(DiskImage* pDisk);
};

/** @brief AKAI instrument definition
 *
 * Represents exactly one sample based instrument on the AKAI media.
 */
class AkaiProgram : public AkaiDiskElement
{
public:
  AkaiDirEntry GetDirEntry();
  // Samples:
  uint ListSamples(std::list<String>& rSamples);
  AkaiSample* GetSample(uint Index);
  AkaiSample* GetSample(const String& rName);

  //    byte     description                 default     range/comments
  //   ---------------------------------------------------------------------------
  //     1       program ID                  1
  //     2-3     first keygroup address      150,0       
  //     4-15    program name                10,10,10... AKAII character set
  String mName;
  //     16      MIDI program number         0           0..127
  uint8_t mMidiProgramNumber;
  //     17      MIDI channel                0           0..15, 255=OMNI
  uint8_t mMidiChannel;
  //     18      polyphony                   15          1..16
  uint8_t mPolyphony;
  //     19      priority                    1           0=LOW 1=NORM 2=HIGH 3=HOLD
  uint8_t mPriority;
  //     20      low key                     24          24..127
  uint8_t mLowKey;
  //     21      high key                    127         24..127
  uint8_t mHighKey;
  //     22      octave shift                0           -2..2
  int8_t mOctaveShift;
  //     23      aux output select           255         0..7, 255=OFF
  uint8_t mAuxOutputSelect;
  //     24      mix output level            99          0..99
  uint8_t mMixOutputSelect;
  //     25      mix output pan              0           -50..50
  int8_t mMixPan;
  //     26      volume                      80          0..99
  uint8_t mVolume;
  //     27      vel>volume                  20          -50..50
  int8_t mVelocityToVolume;
  //     28      key>volume                  0           -50..50
  int8_t mKeyToVolume;
  //     29      pres>volume                 0           -50..50
  int8_t mPressureToVolume;
  //     30      pan lfo rate                50          0..99
  uint8_t mPanLFORate;
  //     31      pan lfo depth               0           0..99
  uint8_t mPanLFODepth;
  //     32      pan lfo delay               0           0..99
  uint8_t mPanLFODelay;
  //     33      key>pan                     0           -50..50
  int8_t mKeyToPan;
  //     34      lfo rate                    50          0..99
  uint8_t mLFORate;
  //     35      lfo depth                   0           0..99
  uint8_t mLFODepth;
  //     36      lfo delay                   0           0..99
  uint8_t mLFODelay;
  //     37      mod>lfo depth               30          0..99
  uint8_t mModulationToLFODepth;
  //     38      pres>lfo depth              0           0..99
  uint8_t mPressureToLFODepth;
  //     39      vel>lfo depth               0           0..99
  uint8_t mVelocityToLFODepth;
  //     40      bend>pitch                  2           0..12 semitones
  uint8_t mBendToPitch;
  //     41      pres>pitch                  0           -12..12 semitones
  int8_t mPressureToPitch;
  //     42      keygroup crossfade          0           0=OFF 1=ON
  bool mKeygroupCrossfade;
  //     43      number of keygroups         1           1..99
  uint8_t mNumberOfKeygroups;
  //     44      (internal use)              0           program number
  //     45-56   key temperament C,C#,D...   0           -25..25 cents
  int8_t mKeyTemperament[11];
  //     57      fx output                   0           0=OFF 1=ON
  bool mFXOutput;
  //     58      mod>pan                     0           -50..50
  int8_t mModulationToPan;
  //     59      stereo coherence            0           0=OFF 1=ON
  bool mStereoCoherence;
  //     60      lfo desync                  1           0=OFF 1=ON
  bool mLFODesync;
  //     61      pitch law                   0           0=LINEAR
  uint8_t mPitchLaw;
  //     62      voice re-assign             0           0=OLDEST 1=QUIETEST
  uint8_t mVoiceReassign;
  //     63      softped>volume              10          0..99
  uint8_t mSoftpedToVolume;
  //     64      softped>attack              10          0..99
  uint8_t mSoftpedToAttack;
  //     65      softped>filt                10          0..99
  uint8_t mSoftpedToFilter;
  //     66      tune cents                  0           -128..127 (-50..50 cents)
  int8_t mSoftpedToTuneCents;
  //     67      tune semitones              0           -50..50
  int8_t mSoftpedToTuneSemitones;
  //     68      key>lfo rate                0           -50..50
  int8_t mKeyToLFORate;
  //     69      key>lfo depth               0           -50..50
  int8_t mKeyToLFODepth;
  //     70      key>lfo delay               0           -50..50
  int8_t mKeyToLFODelay;
  //     71      voice output scale          1           0=-6dB 1=0dB 2=+12dB
  uint8_t mVoiceOutputScale;
  //     72      stereo output scale         0           0=0dB 1=+6dB
  uint8_t mStereoOutputScale;
  //     73-150  (not used)

  AkaiKeygroup* mpKeygroups;

  bool Load();
  AkaiVolume* GetParent()
  {
    return mpParent;
  }

private:
  AkaiProgram(DiskImage* pDisk, AkaiVolume* pParent, const AkaiDirEntry& DirEntry);
  virtual ~AkaiProgram();

  friend class AkaiVolume;

  std::list<AkaiSample*> mpSamples;
  AkaiVolume* mpParent;
  DiskImage* mpDisk;
  AkaiDirEntry mDirEntry;
};

/** @brief Subdivision of an AKAI disk partition.
 *
 * An AKAI volume is a further subdivision of an AKAI disk partition.
 *
 * An AKAI volume actually provides access to the list of instruments (programs)
 * and samples. Samples referenced by an instrument (program) are always part of
 * the same volume.
 */
class AkaiVolume : public AkaiDiskElement
{
public:
  AkaiDirEntry GetDirEntry();
  // Programs:
  uint ListPrograms(std::list<AkaiDirEntry>& rPrograms);
  AkaiProgram* GetProgram(uint Index);
  AkaiProgram* GetProgram(const String& rName);

  // Samples:
  uint ListSamples(std::list<AkaiDirEntry>& rSamples);
  AkaiSample* GetSample(uint Index);
  AkaiSample* GetSample(const String& rName);

  AkaiPartition* GetParent()
  {
    return mpParent;
  }

  bool IsEmpty();
private:
  AkaiVolume(DiskImage* pDisk, AkaiPartition* pParent, const AkaiDirEntry& DirEntry);
  virtual ~AkaiVolume();
  uint ReadDir();

  friend class AkaiPartition;

  String mName;
  std::list<AkaiProgram*> mpPrograms;
  std::list<AkaiSample*> mpSamples;
  DiskImage* mpDisk;
  AkaiPartition* mpParent;
  AkaiDirEntry mDirEntry;
};

/** @brief Encapsulates one disk partition of an AKAI disk.
 *
 * An object of this class represents exactly one disk partition of an AKAI disk
 * media or of an AKAI disk image file. This is similar to a hard disk partition
 * on other operating systems, just in AKAI's own custom format.
 *
 * Each AKAI disk partition is further subdivided into so called "volumes".
 */
class AkaiPartition : public AkaiDiskElement
{
public:
  // Samples:
  uint ListVolumes(std::list<AkaiDirEntry>& rVolumes);
  AkaiVolume* GetVolume(uint Index);
  AkaiVolume* GetVolume(const String& rName);

  AkaiDisk* GetParent()
  {
    return mpParent;
  }

  bool IsEmpty();
private:
  AkaiPartition(DiskImage* pDisk, AkaiDisk* pParent);
  virtual ~AkaiPartition();

  friend class AkaiDisk;

  String mName;
  std::list<AkaiVolume*> mpVolumes;
  AkaiDisk* mpParent;
  DiskImage* mpDisk;
};

/** @brief Toplevel AKAI image interpreter.
 *
 * This class takes an AKAI disk image as constructor argument and provides
 * access to the individual partitions of that AKAI disk/image. The concept is
 * similar to hard disc layout for other operating systems, which are also
 * divided into individual partitions as topmost instance on the mass data
 * media.
 */
class AkaiDisk : public AkaiDiskElement
{
public:
  AkaiDisk(DiskImage* pDisk);
  virtual ~AkaiDisk();

  // Partitions:
  uint GetPartitionCount();
  AkaiPartition* GetPartition(uint count);

private:
  DiskImage* mpDisk;
  std::list<AkaiPartition*> mpPartitions;
};

#define AKAI_FILE_ENTRY_SIZE            24
#define AKAI_DIR_ENTRY_OFFSET           0xca
#define AKAI_DIR_ENTRY_SIZE             16
#define AKAI_ROOT_ENTRY_OFFSET          0x0

#define AKAI_PARTITION_END_MARK         0x8000
#define AKAI_BLOCK_SIZE                 0x2000

#define AKAI_FAT_OFFSET                 0x70a

#define AKAI_MAX_FILE_ENTRIES_S1000     125  //should be 128 ??
#define AKAI_MAX_FILE_ENTRIES_S3000     509  // should be 512 ??
#define AKAI_MAX_DIR_ENTRIES            100
#define AKAI_TYPE_DIR_S1000             1
#define AKAI_TYPE_DIR_S3000             3

#define AKAI_PROGRAM_ID   1
#define AKAI_KEYGROUP_ID  2
#define AKAI_SAMPLE_ID    3

#endif // __akai_h__