/* libakai - C++ cross-platform akai sample disk reader Copyright (C) 2002-2003 Sébastien Métrot Linux port by Christian Schoenebeck 2003 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 */ // DeviceAccessTest.cpp : Defines the entry point for the console application. // #ifdef _WIN32_ #define _WIN32_WINNT 0x0500 #include #include #endif #ifdef HAVE_CONFIG_H # include #endif #if LINUX # include # include # include # include # include # include # define USE_DISK_STREAMING 1 // for testing the disk streaming methods #endif // LINUX #include #include #include "DiskImage.h" #include "AkaiDisk.h" #if LINUX int writeWav(const char* filename, void* samples, long samplecount); void* hAFlib; // handle to libaudiofile void openAFlib(void); void closeAFlib(void); // pointers to libaudiofile functions AFfilesetup(*_afNewFileSetup)(void); void(*_afFreeFileSetup)(AFfilesetup); void(*_afInitChannels)(AFfilesetup,int,int); void(*_afInitSampleFormat)(AFfilesetup,int,int,int); void(*_afInitFileFormat)(AFfilesetup,int); void(*_afInitRate)(AFfilesetup,int,double); int(*_afWriteFrames)(AFfilehandle,int,const void*,int); AFfilehandle(*_afOpenFile)(const char*,const char*,AFfilesetup); int(*_afCloseFile)(AFfilehandle file); #endif // LINUX void ConvertAkaiToAscii(char * buffer, int length); // debugging purpose only void PrintLastError(char* file, int line) { #ifdef _WIN32_ LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the string. char buf[2048]; sprintf(buf,"%s(%d): %s",file, line, (LPCTSTR)lpMsgBuf); printf("%s",buf); OutputDebugString(buf); // Free the buffer. LocalFree( lpMsgBuf ); #endif } #define SHOWERROR PrintLastError(__FILE__,__LINE__) int main(int argc, char** argv) { char drive; char rootpath[4]="a:\\"; int type; #ifdef _WIN32_ printf("GetDriveType result for your drives:\n"); for (drive='a';drive<='z';drive++) { rootpath[0]=drive; type=GetDriveType(rootpath); if (type != DRIVE_NO_ROOT_DIR) { printf("Drive %s is a ",rootpath); switch(type) { case DRIVE_UNKNOWN: printf("Unknown\n"); break; case DRIVE_NO_ROOT_DIR: printf("Unavailable\n"); case DRIVE_REMOVABLE: printf("removable disk\n"); break; case DRIVE_FIXED: printf("fixed disk\n"); break; case DRIVE_REMOTE: printf("remote (network) drive\n"); break; case DRIVE_CDROM: printf("CD-ROM drive\n"); break; case DRIVE_RAMDISK: printf("RAM disk\n"); break; } } } #endif DiskImage* pImage; // pImage = new DiskImage(3); #if LINUX pImage = new DiskImage("/dev/cdrom"); #else pImage = new DiskImage("../strange.iso"); #endif // pImage = new DiskImage("../test.iso"); AkaiDisk* pAkai = new AkaiDisk(pImage); printf("Reading Akai file entries (this may take a while)...\n"); printf("Partitions: %d\n", pAkai->GetPartitionCount()); printf("Partitions list:\n"); long totalSamplesSize = 0, totalSamples = 0; uint i; for (i = 0; i < pAkai->GetPartitionCount(); i++) { printf("%2.2d: Partition %c\n",i,'A'+i); AkaiPartition* pPartition = pAkai->GetPartition(i); if (pPartition) { std::list Volumes; pPartition->ListVolumes(Volumes); std::list::iterator it; std::list::iterator end = Volumes.end(); int vol = 0; for (it = Volumes.begin(); it != end; it++) { AkaiDirEntry DirEntry = *it; printf(" %d (%d) '%.12s' [start=%d - type=%d]\n", vol,DirEntry.mIndex, DirEntry.mName.c_str(), DirEntry.mStart, DirEntry.mType); AkaiVolume* pVolume = pPartition->GetVolume(vol); if (pVolume) { std::list Programs; pVolume->ListPrograms(Programs); std::list::iterator it; std::list::iterator end = Programs.end(); uint prog = 0; for (it = Programs.begin(); it != end; it++) { AkaiDirEntry DirEntry = *it; printf(" Program %d (%d) '%.12s' [start=%d size=%d - type=%c]\n", prog,DirEntry.mIndex, DirEntry.mName.c_str(), DirEntry.mStart, DirEntry.mSize, DirEntry.mType); AkaiProgram* pProgram = pVolume->GetProgram(prog); printf(" Number of key groups: %d\n",pProgram->mNumberOfKeygroups); pProgram->Release(); prog++; } std::list Samples; pVolume->ListSamples(Samples); end = Samples.end(); uint samp = 0; for (it = Samples.begin(); it != end; it++) { AkaiDirEntry DirEntry = *it; printf(" Sample %d (%d) '%.12s' [start=%d size=%d - type=%c]\n", samp,DirEntry.mIndex, DirEntry.mName.c_str(), DirEntry.mStart, DirEntry.mSize, DirEntry.mType); AkaiSample* pSample= pVolume->GetSample(samp); printf(" Number of samples: %d (%d Hz)\n",pSample->mNumberOfSamples,pSample->mSamplingFrequency); totalSamplesSize += pSample->mNumberOfSamples; totalSamples++; pSample->Release(); samp++; } pVolume->Release(); } vol++; } pPartition->Release(); } } #if 0 printf("Writing Akai track to hard disk..."); fflush(stdout); bool success = pImage->WriteImage("/tmp/some.akai"); if (success) printf("ok\n"); else printf("error\n"); #endif #if LINUX hAFlib = NULL; totalSamplesSize *= 2; // due to 16 bit samples printf("There are %d samples on this disk with a total size of %d Bytes. ", totalSamples, totalSamplesSize); printf("Do you want to extract them (wav files will be written to /tmp/akai)? [y/n]\n"); char c = getchar(); if (c == 'y' || c == 'Y') { bool errorOccured = false; openAFlib(); DIR* dir = opendir("/tmp/akai"); if (!dir) { if (errno == ENOENT) { struct stat filestat; if (lstat("/tmp/akai", &filestat) < 0) { printf("Creating directory /tmp/akai..."); fflush(stdout); if (mkdir("/tmp/akai", 0770) < 0) { perror("failed"); errorOccured = true; } else printf("ok\n"); } else { if (!S_ISLNK(filestat.st_mode)) { printf("Cannot create directory /tmp/akai: "); printf("a file of that name already exists\n"); errorOccured = true; } } } else { perror("error while opening /tmp/akai"); errorOccured = true; } } if (dir) closedir(dir); if (!errorOccured) { printf("starting extraction...\n"); long currentsample = 1; uint i; for (i = 0; i < pAkai->GetPartitionCount() && !errorOccured; i++) { AkaiPartition* pPartition = pAkai->GetPartition(i); if (pPartition) { std::list Volumes; pPartition->ListVolumes(Volumes); std::list::iterator it; std::list::iterator end = Volumes.end(); int vol = 0; for (it = Volumes.begin(); it != end && !errorOccured; it++) { AkaiDirEntry DirEntry = *it; AkaiVolume* pVolume = pPartition->GetVolume(vol); if (pVolume) { std::list Samples; pVolume->ListSamples(Samples); std::list::iterator it; std::list::iterator end = Samples.end(); uint samp = 0; for (it = Samples.begin(); it != end && !errorOccured; it++) { AkaiDirEntry DirEntry = *it; AkaiSample* pSample = pVolume->GetSample(samp); printf("Extracting Sample (%d/%d) %s...", currentsample++, totalSamples, DirEntry.mName.c_str()); fflush(stdout); #if USE_DISK_STREAMING if (pSample->LoadHeader()) { uint16_t* pSampleBuf = new uint16_t[pSample->mNumberOfSamples]; pSample->Read(pSampleBuf, pSample->mNumberOfSamples); String filename = "/tmp/akai/" + DirEntry.mName + ".wav"; int res = writeWav(filename.c_str(), pSampleBuf, pSample->mNumberOfSamples); /* if (res < 0) { printf("couldn't write sample data\n"); errorOccured = true; } else */printf("ok\n"); delete[] pSampleBuf; } else { printf("failed to load sample data\n"); errorOccured = true; } #else // no disk streaming if (pSample->LoadSampleData()) { String filename = "/tmp/akai/" + DirEntry.mName + ".wav"; int res = writeWav(filename.c_str(), pSample->mpSamples, pSample->mNumberOfSamples); /* if (res < 0) { printf("couldn't write sample data\n"); errorOccured = true; } else */ printf("ok\n"); pSample->ReleaseSampleData(); } else { printf("failed to load sample data\n"); errorOccured = true; } #endif // USE_DISK_STREAMING pSample->Release(); samp++; } pVolume->Release(); } vol++; } pPartition->Release(); } } } if (errorOccured) printf("Extraction failed\n"); closeAFlib(); } #endif // LINUX #if 0 // this is just for debugging purpose - it converts the whole image to ascii printf("Converting...\n"); FILE* f = fopen("akai_converted_to_ascii.iso", "w"); if (f) { char* buf = (char*) malloc(AKAI_BLOCK_SIZE); pImage->SetPos(0); while (pImage->Available(1)) { int readbytes = pImage->Read(buf,1,AKAI_BLOCK_SIZE); if (readbytes != AKAI_BLOCK_SIZE) printf("Block incomplete (read: %d)\n",readbytes); ConvertAkaiToAscii(buf, readbytes); fwrite(buf, AKAI_BLOCK_SIZE, 1, f); } free(buf); fclose(f); } else printf("Could not open file\n"); #endif delete pAkai; delete pImage; #if _WIN32_ while(!_kbhit()); #endif } // only for debugging void ConvertAkaiToAscii(char * buffer, int length) { int i; for (i = 0; i < length; i++) { if (buffer[i]>=0 && buffer[i]<=9) buffer[i] +=48; else if (buffer[i]==10) buffer[i] = 32; else if (buffer[i]>=11 && buffer[i]<=36) buffer[i] = 64+(buffer[i]-10); else buffer[i] = 32; } buffer[length] = '\0'; while (length-- > 0 && buffer[length] == 32) { // This block intentionaly left blank :) } buffer[length+1] = '\0'; } #if LINUX int writeWav(const char* filename, void* samples, long samplecount) { AFfilesetup setup = _afNewFileSetup(); _afInitFileFormat(setup, AF_FILE_WAVE); _afInitChannels(setup, AF_DEFAULT_TRACK, 1); // Mono _afInitSampleFormat(setup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); // 16 bit _afInitRate(setup, AF_DEFAULT_TRACK, 44100); // 44.1 kHz if (setup == AF_NULL_FILESETUP) return -1; AFfilehandle hFile = _afOpenFile(filename, "w", setup); if (hFile == AF_NULL_FILEHANDLE) return -1; if (_afWriteFrames(hFile, AF_DEFAULT_TRACK, samples, samplecount) < 0) return 0; // if (_afWriteFrames(hFile, AF_DEFAULT_TRACK, samples, samplecount) < 0) return -1; _afCloseFile(hFile); _afFreeFileSetup(setup); } void openAFlib() { hAFlib = dlopen("libaudiofile.so", RTLD_NOW); if (!hAFlib) { printf("Unable to load library libaudiofile.so: %s\n", dlerror()); return; } _afNewFileSetup = (AFfilesetup(*)(void)) dlsym(hAFlib, "afNewFileSetup"); _afFreeFileSetup = (void(*)(AFfilesetup)) dlsym(hAFlib, "afFreeFileSetup"); _afInitChannels = (void(*)(AFfilesetup,int,int)) dlsym(hAFlib, "afInitChannels"); _afInitSampleFormat = (void(*)(AFfilesetup,int,int,int)) dlsym(hAFlib, "afInitSampleFormat"); _afInitFileFormat = (void(*)(AFfilesetup,int)) dlsym(hAFlib, "afInitFileFormat"); _afInitRate = (void(*)(AFfilesetup,int,double)) dlsym(hAFlib, "afInitRate"); _afWriteFrames = (int(*)(AFfilehandle,int,const void*,int)) dlsym(hAFlib, "afWriteFrames"); _afOpenFile = (AFfilehandle(*)(const char*,const char*,AFfilesetup)) dlsym(hAFlib, "afOpenFile"); _afCloseFile = (int(*)(AFfilehandle file)) dlsym(hAFlib, "afCloseFile"); if (dlerror()) printf("Failed to load function from libaudiofile.so: %s\n", dlerror()); } void closeAFlib() { if (hAFlib) dlclose(hAFlib); } #endif // LINUX