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