diff --git a/src/tests/kits/midi/synth_file_reader/Jamfile b/src/tests/kits/midi/synth_file_reader/Jamfile index c1a0b8c32c..67261f584f 100644 --- a/src/tests/kits/midi/synth_file_reader/Jamfile +++ b/src/tests/kits/midi/synth_file_reader/Jamfile @@ -2,6 +2,7 @@ SubDir OBOS_TOP src tests kits midi synth_file_reader ; SimpleTest sfr : SynthFileReader.cpp + SynthFile.cpp main.cpp : be root game ; diff --git a/src/tests/kits/midi/synth_file_reader/SynthFileFormat.txt b/src/tests/kits/midi/synth_file_reader/SynthFileFormat.txt index 0926816e7e..e56426dafc 100644 --- a/src/tests/kits/midi/synth_file_reader/SynthFileFormat.txt +++ b/src/tests/kits/midi/synth_file_reader/SynthFileFormat.txt @@ -9,16 +9,26 @@ chunks: ------- next[4] | tag[4] -tag: ----- +tags: +----- + +'INST' +'snd ' +'CACH' + + +'INST' +------ 'INST' | instr[4] | nameLen[1] | name[nameLen] | dataSize[4] | data[dataSize] -| sndId[2] | ???[10] | size[2] | ???[size*8+21] | rest[dataSize-...] | +| sndId[2] | ???[10] | size[2] | insts[size*8+21] | rest[dataSize-...] | -'snd ' | sndId[4] | nameLen[1] | name[nameLen] | dataSize[4] | [28] | -rate[2] | ... -data[dataSize]: ----------------- +insts[size*8+21]: +noteStart[1] | noteEnd[1] | sndId[2] | ??[4] | repeats number of size times +??[21] + +rest[dataSize]: + ADSR | [1] | [4] | [4] | LINE | [4] | [4] | SUST | [4] | [4] | @@ -33,4 +43,13 @@ VOLU | [1] | [4] | [4] | SPAN | [1] | [4] | [4] | TRIA | [4] | [4] | SQU2 | [8] | -SQUA | [8] | \ No newline at end of file +SQUA | [8] | + + + +'snd ' +------ +'snd ' | sndId[4] | nameLen[1] | name[nameLen] | dataSize[4] | [28] | +rate[2] | ?[10] | 255 | drumId | ... + + diff --git a/src/tests/kits/midi/synth_file_reader/SynthFileReader.cpp b/src/tests/kits/midi/synth_file_reader/SynthFileReader.cpp index 53d55278ff..6ebc609857 100644 --- a/src/tests/kits/midi/synth_file_reader/SynthFileReader.cpp +++ b/src/tests/kits/midi/synth_file_reader/SynthFileReader.cpp @@ -29,13 +29,14 @@ THE SOFTWARE. */ #include "SynthFileReader.h" +#include "SynthFile.h" #include #include #define DEBUG 1 #include -SynthFileReader::SynthFileReader(const char* synthFile) { +SSynthFileReader::SSynthFileReader(const char* synthFile) { fFile = fopen(synthFile, "r+b"); tag tag; if (fFile) { @@ -47,29 +48,29 @@ SynthFileReader::SynthFileReader(const char* synthFile) { } -SynthFileReader::~SynthFileReader() { +SSynthFileReader::~SSynthFileReader() { if (fFile) { fclose(fFile); fFile = NULL; } } -bool SynthFileReader::InitCheck() const { - return fFile != NULL; +status_t SSynthFileReader::InitCheck() const { + return fFile != NULL ? B_OK : B_ERROR; } -bool SynthFileReader::TagEquals(const char* tag1, const char* tag2) const { +bool SSynthFileReader::TagEquals(const char* tag1, const char* tag2) const { return strncmp(tag1, tag2, 4) == 0; } -bool SynthFileReader::Read(void* data, uint32 size) { +bool SSynthFileReader::Read(void* data, uint32 size) { return 1 == fread(data, size, 1, fFile); } -bool SynthFileReader::Read(tag &tag) { +bool SSynthFileReader::Read(tag &tag) { return Read((void*)tag, sizeof(tag)); } -bool SynthFileReader::Read(uint64 &n, uint32 size) { +bool SSynthFileReader::Read(uint64 &n, uint32 size) { uint8 number[8]; ASSERT(size <= sizeof(number)); if (Read((void*)number, size)) { @@ -83,7 +84,7 @@ bool SynthFileReader::Read(uint64 &n, uint32 size) { return false; } -bool SynthFileReader::Read(uint32 &n) { +bool SSynthFileReader::Read(uint32 &n) { uint64 num; bool ok = Read(num, 4); n = num; @@ -91,7 +92,7 @@ bool SynthFileReader::Read(uint32 &n) { } -bool SynthFileReader::Read(uint16 &n) { +bool SSynthFileReader::Read(uint16 &n) { uint64 num; bool ok = Read(num, 2); n = num; @@ -99,11 +100,11 @@ bool SynthFileReader::Read(uint16 &n) { } -bool SynthFileReader::Read(uint8 &n) { +bool SSynthFileReader::Read(uint8 &n) { return Read((void*)&n, 1); } -bool SynthFileReader::Read(BString& s, uint32 len) { +bool SSynthFileReader::Read(BString& s, uint32 len) { char* str = s.LockBuffer(len+1); str[len] = 0; bool ok = Read((void*)str, len); @@ -111,18 +112,115 @@ bool SynthFileReader::Read(BString& s, uint32 len) { return ok; } -bool SynthFileReader::Skip(uint32 bytes) { +bool SSynthFileReader::Skip(uint32 bytes) { fseek(fFile, bytes, SEEK_CUR); return true; } + +bool SSynthFileReader::ReadHeader(uint32& version, uint32& chunks, uint32& nextChunk) { + tag tag; + fseek(fFile, 0, SEEK_SET); + if (Read(tag) && TagEquals(tag, "IREZ") && Read(version) && Read(chunks)) { + nextChunk = ftell(fFile); + return true; + } + return false; +} + + +bool SSynthFileReader::NextChunk(tag& tag, uint32& nextChunk) { + fseek(fFile, nextChunk, SEEK_SET); + return Read(nextChunk) && Read(tag); +} + + +bool SSynthFileReader::ReadInstHeader(uint16& inst, uint16& snd, uint16& snds, BString& name, uint32& size) { + uint8 len; + + if (Skip(2) && Read(inst) && Read(len) && Read(name, len) && Read(size) && Read(snd) && Skip(10) && Read(snds)) { + size -= 14; + return true; + } + return false; +} + + +bool SSynthFileReader::ReadSoundInRange(uint8& start, uint8& end, uint16& snd, uint32& size) { + size -= 4; + return Read(start) && Read(end) && Read(snd) && Skip(4); +} + + +bool SSynthFileReader::ReadSoundHeader(uint16& inst, BString& name, uint32& size) { + uint8 len; + return Skip(2) && Read(inst) && Read(len) && Read(name, len) && Read(size); +} + + +status_t SSynthFileReader::Initialize(SSynthFile* synth) { + uint32 version; + uint32 chunks; + uint32 nextChunk; + tag t; + + if (ReadHeader(version, chunks, nextChunk)) { + for (uint32 chunk = 0; chunk < chunks; chunk ++) { + if (NextChunk(t, nextChunk)) { + if (TagEquals(t, "INST")) { + uint32 offset = Tell(); + uint16 inst; + uint16 snd; + uint16 snds; + BString name; + uint32 size; + if (ReadInstHeader(inst, snd, snds, name, size)) { + SInstrument* instr = synth->GetInstrument(inst); + instr->SetOffset(offset); + instr->SetName(name.String()); + instr->SetDefaultSound(synth->GetSound(snd)); + for (int s = 0; s < snds; s ++) { + uint8 start, end; + if (ReadSoundInRange(start, end, snd, size)) { + instr->Sounds()->AddItem(new SSoundInRange(start, end, synth->GetSound(snd))); + } else { + return B_ERROR; + } + } + } else { + return B_ERROR; + } + } else if (TagEquals(t, "snd ")) { + uint32 offset = Tell(); + uint16 inst; + BString name; + uint32 size; + if (ReadSoundHeader(inst, name, size)) { + SSound* s = synth->GetSound(inst); + s->SetOffset(offset); + s->SetName(name.String()); + } else { + return B_ERROR; + } + } else { + // skip + } + } else { + return B_ERROR; + } + } + return B_OK; + } + return B_ERROR; +} + // debugging -void SynthFileReader::Print(tag tag) { +void SSynthFileReader::Print(tag tag) { printf("%.*s", 4, tag); } -void SynthFileReader::Dump(uint32 bytes) { +void SSynthFileReader::Dump(uint32 bytes) { uint8 byte; int col = 0; const int cols = 16; @@ -141,7 +239,7 @@ void SynthFileReader::Dump(uint32 bytes) { } } -void SynthFileReader::Dump(bool play, uint32 instrOnly) { +void SSynthFileReader::Dump(bool play, uint32 instrOnly) { tag tag; uint32 version; uint32 nEntries; @@ -164,7 +262,7 @@ void SynthFileReader::Dump(bool play, uint32 instrOnly) { cur = ftell(fFile); if (Read(tag)) { Print(tag); - if (TagEquals(tag, "INST")) { + if (!play && TagEquals(tag, "INST")) { uint32 inst; uint8 len; BString name; @@ -207,7 +305,7 @@ void SynthFileReader::Dump(bool play, uint32 instrOnly) { } else if (TagEquals(tag, "LAST")) { s = 0; if (rest > 0) { - SynthFileReader::tag tag2; + SSynthFileReader::tag tag2; long pos = ftell(fFile); Read(tag2); fseek(fFile, pos, SEEK_SET); @@ -291,7 +389,7 @@ void SynthFileReader::Dump(bool play, uint32 instrOnly) { #include #include -void SynthFileReader::Play(uint16 rate, uint32 offset, uint32 size) { +void SSynthFileReader::Play(uint16 rate, uint32 offset, uint32 size) { uint8* samples = new uint8[size]; fseek(fFile, offset, SEEK_CUR); Read((void*)samples, size); diff --git a/src/tests/kits/midi/synth_file_reader/SynthFileReader.h b/src/tests/kits/midi/synth_file_reader/SynthFileReader.h index 3f4ea9488f..c37bcc2ee5 100644 --- a/src/tests/kits/midi/synth_file_reader/SynthFileReader.h +++ b/src/tests/kits/midi/synth_file_reader/SynthFileReader.h @@ -34,8 +34,11 @@ THE SOFTWARE. #include #include -class SynthFileReader { - FILE* fFile; +class SSynthFile; + +class SSynthFileReader { +private: + FILE* fFile; typedef char tag[4]; @@ -48,6 +51,14 @@ class SynthFileReader { bool Read(uint16 &n); bool Read(uint8 &n); bool Skip(uint32 bytes); + uint32 Tell() { return ftell(fFile); } + void Seek(uint32 pos) { fseek(fFile, pos, SEEK_SET); } + + bool ReadHeader(uint32& version, uint32& chunks, uint32& nextChunk); + bool NextChunk(tag& tag, uint32& nextChunk); + bool ReadInstHeader(uint16& inst, uint16& snd, uint16& snds, BString& name, uint32& size); + bool ReadSoundInRange(uint8& start, uint8& end, uint16& snd, uint32& size); + bool ReadSoundHeader(uint16& inst, BString& name, uint32& size); // debugging support void Print(tag tag); @@ -55,9 +66,11 @@ class SynthFileReader { void Play(uint16 rate, uint32 offset, uint32 size); public: - SynthFileReader(const char* synthFile); - ~SynthFileReader(); - bool InitCheck() const; + SSynthFileReader(const char* synthFile); + ~SSynthFileReader(); + status_t InitCheck() const; + + status_t Initialize(SSynthFile* synth); void Dump(bool play, uint32 instrOnly); }; diff --git a/src/tests/kits/midi/synth_file_reader/main.cpp b/src/tests/kits/midi/synth_file_reader/main.cpp index 40dc8a1d8f..a60a337c9b 100644 --- a/src/tests/kits/midi/synth_file_reader/main.cpp +++ b/src/tests/kits/midi/synth_file_reader/main.cpp @@ -28,6 +28,7 @@ THE SOFTWARE. */ #include "SynthFileReader.h" +#include "SynthFile.h" #include #include @@ -38,18 +39,26 @@ void start_be_app() { int main(int argc, char* argv[]) { if (argc < 2) { - printf("%s [play [instr]]\n", argv[0]); + printf("%s [play [instr] | dump]\n", argv[0]); return -1; } const char* fileName = argv[1]; bool play = argc >= 3 ? strcmp(argv[2], "play") == 0 : false; + bool dump = argc >= 3 ? strcmp(argv[2], "dump") == 0 : false; uint32 instr = argc >= 4 ? atol(argv[3]) : 0xffff; - - SynthFileReader reader(fileName); - if (reader.InitCheck()) { - start_be_app(); - reader.Dump(play, instr); + + if (dump) { + SSynthFile synth(fileName); + if (synth.InitCheck() == B_OK) { + synth.Dump(); + } } else { - printf("could not open '%s' or not a valid synth file!\n", fileName); - } + SSynthFileReader reader(fileName); + if (reader.InitCheck() == B_OK) { + start_be_app(); + reader.Dump(play, instr); + } else { + printf("could not open '%s' or not a valid synth file!\n", fileName); + } + } } \ No newline at end of file