libgig  4.3.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-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 
60 typedef std::string String;
61 typedef std::streampos streampos;
62 
63 class AkaiVolume;
64 class AkaiPartition;
65 class AkaiDisk;
66 
67 
68 /* current state of the Akai stream */
69 typedef 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 */
76 typedef 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 
99 typedef std::string String;
100 
110 {
111 public:
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 
147 protected:
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 
167 private:
168  void Init();
169 };
170 
171 
172 class Resource
173 {
174 public:
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  }
197 private:
198  uint mRefCount;
199 };
200 
201 class AkaiDirEntry
202 {
203 public:
204  String mName;
205  uint16_t mType;
206  int mSize;
207  uint16_t mStart;
208  int mIndex;
209 };
210 
211 // AkaiDiskElement:
212 class AkaiDiskElement : public Resource
213 {
214 public:
215  AkaiDiskElement(uint Offset = 0)
216  {
217  mOffset = Offset;
218  }
219 
220  uint GetOffset()
221  {
222  return mOffset;
223  }
224 
225 protected:
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);
234 private:
235  uint mOffset;
236 };
237 
238 class AkaiSampleLoop
239 {
240 public:
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;
249 private:
250  friend class AkaiSample;
251  bool Load(DiskImage* pDisk);
252 };
253 
254 class AkaiSample : public AkaiDiskElement
255 {
256 public:
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();
310 private:
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 
324 class AkaiKeygroupSample : public AkaiDiskElement
325 {
326 public:
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  //
351 private:
352  friend class AkaiKeygroup;
353  bool Load(DiskImage* pDisk);
354 };
355 
356 class AkaiEnveloppe
357 {
358 public:
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;
375 private:
376  friend class AkaiKeygroup;
377  bool Load(DiskImage* pDisk);
378 };
379 
380 class AkaiKeygroup
381 {
382 public:
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 
473 private:
474  friend class AkaiProgram;
475  bool Load(DiskImage* pDisk);
476 };
477 
482 class AkaiProgram : public AkaiDiskElement
483 {
484 public:
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 
598 private:
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 
618 class AkaiVolume : public AkaiDiskElement
619 {
620 public:
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();
638 private:
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 
661 class AkaiPartition : public AkaiDiskElement
662 {
663 public:
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();
675 private:
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 
695 class AkaiDisk : public AkaiDiskElement
696 {
697 public:
698  AkaiDisk(DiskImage* pDisk);
699  virtual ~AkaiDisk();
700 
701  // Partitions:
702  uint GetPartitionCount();
703  AkaiPartition* GetPartition(uint count);
704 
705 private:
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
DiskImage(const char *path)
Open an image from a file.
Definition: Akai.cpp:1266