diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 1d697cfd0..accf06c38 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1,3 +1,4 @@ +#include #define _USE_MATH_DEFINES #include "engine.h" #include "instrument.h" @@ -1431,14 +1432,10 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { delete[] file; return false; } - reader.readI(); DivWavetable* wave=new DivWavetable; + reader.seek(wavePtr[i],SEEK_SET); - reader.readString(); // ignored for now - wave->len=reader.readI(); - wave->min=reader.readI(); - wave->max=reader.readI(); - reader.read(wave->data,4*wave->len); + wave->readWaveData(reader,ds.version); ds.wave.push_back(wave); } @@ -3079,8 +3076,113 @@ int DivEngine::addWave() { } bool DivEngine::addWaveFromFile(const char* path) { + FILE* f=ps_fopen(path,"rb"); + if (f==NULL) { + return false; + } + unsigned char* buf; + ssize_t len; + if (fseek(f,0,SEEK_END)!=0) { + fclose(f); + return false; + } + len=ftell(f); + if (len<0) { + fclose(f); + return false; + } + if (len==0) { + fclose(f); + return false; + } + if (fseek(f,0,SEEK_SET)!=0) { + fclose(f); + return false; + } + buf=new unsigned char[len]; + if (fread(buf,1,len,f)!=(size_t)len) { + logW("did not read entire wavetable file buffer!\n"); + delete[] buf; + return false; + } + fclose(f); + + SafeReader reader=SafeReader(buf,len); + + unsigned char magic[16]; + bool isFurnaceTable=false; + try { + reader.read(magic,16); + if (memcmp("-Furnace waveta-",magic,16)==0) { + isFurnaceTable=true; + } + } catch (EndOfFileException e) { + reader.seek(0,SEEK_SET); + } + + DivWavetable* wave=new DivWavetable; + try { + if (isFurnaceTable) { + reader.seek(16,SEEK_SET); + short version=reader.readS(); + reader.readS(); // reserved + reader.read(magic,4); + if (memcmp(magic,"WAVE",4)!=0) { + logE("invalid wavetable header!\n"); + lastError="invalid wavetable header!"; + delete[] buf; + return false; + } + reader.seek(20,SEEK_SET); + wave->readWaveData(reader,version); + } else { + try { + // read as .dmw + reader.seek(0,SEEK_SET); + int len=reader.readI(); + wave->max=(unsigned char)reader.readC(); + if (reader.size()==(size_t)(len+5)) { + // read as .dmw + logI("reading .dmw...\n"); + if (len>256) len=256; + for (int i=0; idata[i]=(unsigned char)reader.readC(); + } + } else { + // read as binary + logI("reading binary...\n"); + len=reader.size(); + if (len>256) len=256; + reader.seek(0,SEEK_SET); + for (int i=0; idata[i]=(unsigned char)reader.readC(); + if (wave->maxdata[i]) wave->max=wave->data[i]; + } + wave->len=len; + } + } catch (EndOfFileException e) { + // read as binary + len=reader.size(); + logI("reading binary for being too small...\n"); + if (len>256) len=256; + reader.seek(0,SEEK_SET); + for (int i=0; idata[i]=(unsigned char)reader.readC(); + if (wave->maxdata[i]) wave->max=wave->data[i]; + } + wave->len=len; + } + } + } catch (EndOfFileException e) { + delete wave; + delete[] buf; + return false; + } + isBusy.lock(); - // TODO + int waveCount=(int)song.wave.size(); + song.wave.push_back(wave); + song.waveLen=waveCount+1; isBusy.unlock(); return true; } diff --git a/src/engine/engine.h b/src/engine/engine.h index 061281865..f42b1d695 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -11,7 +11,7 @@ #include #define DIV_VERSION "0.4.6" -#define DIV_ENGINE_VERSION 27 +#define DIV_ENGINE_VERSION 28 enum DivStatusView { DIV_STATUS_NOTHING=0, diff --git a/src/engine/wavetable.cpp b/src/engine/wavetable.cpp index 8e3c76135..5bfa540f3 100644 --- a/src/engine/wavetable.cpp +++ b/src/engine/wavetable.cpp @@ -16,6 +16,17 @@ void DivWavetable::putWaveData(SafeWriter* w) { } } +void DivWavetable::readWaveData(SafeReader& reader, short version) { + reader.readI(); + reader.readI(); + + reader.readString(); // ignored for now + len=reader.readI(); + min=reader.readI(); + max=reader.readI(); + reader.read(data,4*len); +} + bool DivWavetable::save(const char* path) { SafeWriter* w=new SafeWriter(); w->init(); diff --git a/src/engine/wavetable.h b/src/engine/wavetable.h index 4ff48baef..cba38d7c2 100644 --- a/src/engine/wavetable.h +++ b/src/engine/wavetable.h @@ -7,6 +7,7 @@ struct DivWavetable { int data[256]; void putWaveData(SafeWriter* w); + void readWaveData(SafeReader& reader, short version); bool save(const char* path); DivWavetable(): len(32), diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index e21227cda..9b5e6ef28 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3964,7 +3964,11 @@ bool FurnaceGUI::loop() { exportAudio(copyOfName,DIV_EXPORT_MODE_MANY_CHAN); break; case GUI_FILE_INS_OPEN: + break; case GUI_FILE_WAVE_OPEN: + e->addWaveFromFile(copyOfName.c_str()); + modified=true; + break; case GUI_FILE_EXPORT_VGM: case GUI_FILE_EXPORT_ROM: showError("Coming soon!");