From dce289a5a06684c733d4767c3b1877349cd65715 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 19 Jan 2022 03:28:29 -0500 Subject: [PATCH] add early code for saving instruments --- CMakeLists.txt | 1 + src/engine/engine.cpp | 132 +---------------------------- src/engine/instrument.cpp | 174 ++++++++++++++++++++++++++++++++++++++ src/engine/instrument.h | 3 + src/gui/gui.cpp | 6 +- 5 files changed, 184 insertions(+), 132 deletions(-) create mode 100644 src/engine/instrument.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ec131f38..858e1c82d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,6 +122,7 @@ src/engine/safeReader.cpp src/engine/safeWriter.cpp src/engine/dispatchContainer.cpp src/engine/engine.cpp +src/engine/instrument.cpp src/engine/macroInt.cpp src/engine/pattern.cpp src/engine/playback.cpp diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 6423d0c80..5a217627d 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1712,137 +1712,7 @@ SafeWriter* DivEngine::saveFur() { for (int i=0; itell(); - w->write("INST",4); - w->writeI(0); - - w->writeS(DIV_ENGINE_VERSION); - - w->writeC(ins->type); - w->writeC(0); - - w->writeString(ins->name,false); - - // FM - w->writeC(ins->fm.alg); - w->writeC(ins->fm.fb); - w->writeC(ins->fm.fms); - w->writeC(ins->fm.ams); - w->writeC(4); // operator count; always 4 - w->writeC(0); // reserved - w->writeC(0); - w->writeC(0); - - for (int j=0; j<4; j++) { - DivInstrumentFM::Operator& op=ins->fm.op[j]; - w->writeC(op.am); - w->writeC(op.ar); - w->writeC(op.dr); - w->writeC(op.mult); - w->writeC(op.rr); - w->writeC(op.sl); - w->writeC(op.tl); - w->writeC(op.dt2); - w->writeC(op.rs); - w->writeC(op.dt); - w->writeC(op.d2r); - w->writeC(op.ssgEnv); - - w->writeC(op.dam); - w->writeC(op.dvb); - w->writeC(op.egt); - w->writeC(op.ksl); - w->writeC(op.sus); - w->writeC(op.vib); - w->writeC(op.ws); - w->writeC(op.ksr); - - // reserved - for (int k=0; k<12; k++) { - w->writeC(0); - } - } - - // GB - w->writeC(ins->gb.envVol); - w->writeC(ins->gb.envDir); - w->writeC(ins->gb.envLen); - w->writeC(ins->gb.soundLen); - - // C64 - w->writeC(ins->c64.triOn); - w->writeC(ins->c64.sawOn); - w->writeC(ins->c64.pulseOn); - w->writeC(ins->c64.noiseOn); - w->writeC(ins->c64.a); - w->writeC(ins->c64.d); - w->writeC(ins->c64.s); - w->writeC(ins->c64.r); - w->writeS(ins->c64.duty); - w->writeC(ins->c64.ringMod); - w->writeC(ins->c64.oscSync); - w->writeC(ins->c64.toFilter); - w->writeC(ins->c64.initFilter); - w->writeC(ins->c64.volIsCutoff); - w->writeC(ins->c64.res); - w->writeC(ins->c64.lp); - w->writeC(ins->c64.bp); - w->writeC(ins->c64.hp); - w->writeC(ins->c64.ch3off); - w->writeS(ins->c64.cut); - w->writeC(ins->c64.dutyIsAbs); - w->writeC(ins->c64.filterIsAbs); - - // Amiga - w->writeS(ins->amiga.initSample); - for (int j=0; j<14; j++) { // reserved - w->writeC(0); - } - - // standard - w->writeI(ins->std.volMacroLen); - w->writeI(ins->std.arpMacroLen); - w->writeI(ins->std.dutyMacroLen); - w->writeI(ins->std.waveMacroLen); - w->writeI(ins->std.pitchMacroLen); - w->writeI(ins->std.ex1MacroLen); - w->writeI(ins->std.ex2MacroLen); - w->writeI(ins->std.ex3MacroLen); - w->writeI(ins->std.volMacroLoop); - w->writeI(ins->std.arpMacroLoop); - w->writeI(ins->std.dutyMacroLoop); - w->writeI(ins->std.waveMacroLoop); - w->writeI(ins->std.pitchMacroLoop); - w->writeI(ins->std.ex1MacroLoop); - w->writeI(ins->std.ex2MacroLoop); - w->writeI(ins->std.ex3MacroLoop); - w->writeC(ins->std.arpMacroMode); - w->writeC(0); // reserved - w->writeC(0); - w->writeC(0); - for (int j=0; jstd.volMacroLen; j++) { - w->writeI(ins->std.volMacro[j]); - } - for (int j=0; jstd.arpMacroLen; j++) { - w->writeI(ins->std.arpMacro[j]); - } - for (int j=0; jstd.dutyMacroLen; j++) { - w->writeI(ins->std.dutyMacro[j]); - } - for (int j=0; jstd.waveMacroLen; j++) { - w->writeI(ins->std.waveMacro[j]); - } - for (int j=0; jstd.pitchMacroLen; j++) { - w->writeI(ins->std.pitchMacro[j]); - } - for (int j=0; jstd.ex1MacroLen; j++) { - w->writeI(ins->std.ex1Macro[j]); - } - for (int j=0; jstd.ex2MacroLen; j++) { - w->writeI(ins->std.ex2Macro[j]); - } - for (int j=0; jstd.ex3MacroLen; j++) { - w->writeI(ins->std.ex3Macro[j]); - } + ins->putInsData(w); } /// WAVETABLE diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp new file mode 100644 index 000000000..d81216c5c --- /dev/null +++ b/src/engine/instrument.cpp @@ -0,0 +1,174 @@ +#include "engine.h" +#include "instrument.h" +#include "../ta-log.h" + +void DivInstrument::putInsData(SafeWriter* w) { + w->write("INST",4); + w->writeI(0); + + w->writeS(DIV_ENGINE_VERSION); + + w->writeC(type); + w->writeC(0); + + w->writeString(name,false); + + // FM + w->writeC(fm.alg); + w->writeC(fm.fb); + w->writeC(fm.fms); + w->writeC(fm.ams); + w->writeC(4); // operator count; always 4 + w->writeC(0); // reserved + w->writeC(0); + w->writeC(0); + + for (int j=0; j<4; j++) { + DivInstrumentFM::Operator& op=fm.op[j]; + w->writeC(op.am); + w->writeC(op.ar); + w->writeC(op.dr); + w->writeC(op.mult); + w->writeC(op.rr); + w->writeC(op.sl); + w->writeC(op.tl); + w->writeC(op.dt2); + w->writeC(op.rs); + w->writeC(op.dt); + w->writeC(op.d2r); + w->writeC(op.ssgEnv); + + w->writeC(op.dam); + w->writeC(op.dvb); + w->writeC(op.egt); + w->writeC(op.ksl); + w->writeC(op.sus); + w->writeC(op.vib); + w->writeC(op.ws); + w->writeC(op.ksr); + + // reserved + for (int k=0; k<12; k++) { + w->writeC(0); + } + } + + // GB + w->writeC(gb.envVol); + w->writeC(gb.envDir); + w->writeC(gb.envLen); + w->writeC(gb.soundLen); + + // C64 + w->writeC(c64.triOn); + w->writeC(c64.sawOn); + w->writeC(c64.pulseOn); + w->writeC(c64.noiseOn); + w->writeC(c64.a); + w->writeC(c64.d); + w->writeC(c64.s); + w->writeC(c64.r); + w->writeS(c64.duty); + w->writeC(c64.ringMod); + w->writeC(c64.oscSync); + w->writeC(c64.toFilter); + w->writeC(c64.initFilter); + w->writeC(c64.volIsCutoff); + w->writeC(c64.res); + w->writeC(c64.lp); + w->writeC(c64.bp); + w->writeC(c64.hp); + w->writeC(c64.ch3off); + w->writeS(c64.cut); + w->writeC(c64.dutyIsAbs); + w->writeC(c64.filterIsAbs); + + // Amiga + w->writeS(amiga.initSample); + for (int j=0; j<14; j++) { // reserved + w->writeC(0); + } + + // standard + w->writeI(std.volMacroLen); + w->writeI(std.arpMacroLen); + w->writeI(std.dutyMacroLen); + w->writeI(std.waveMacroLen); + w->writeI(std.pitchMacroLen); + w->writeI(std.ex1MacroLen); + w->writeI(std.ex2MacroLen); + w->writeI(std.ex3MacroLen); + w->writeI(std.volMacroLoop); + w->writeI(std.arpMacroLoop); + w->writeI(std.dutyMacroLoop); + w->writeI(std.waveMacroLoop); + w->writeI(std.pitchMacroLoop); + w->writeI(std.ex1MacroLoop); + w->writeI(std.ex2MacroLoop); + w->writeI(std.ex3MacroLoop); + w->writeC(std.arpMacroMode); + w->writeC(0); // reserved + w->writeC(0); + w->writeC(0); + for (int j=0; jwriteI(std.volMacro[j]); + } + for (int j=0; jwriteI(std.arpMacro[j]); + } + for (int j=0; jwriteI(std.dutyMacro[j]); + } + for (int j=0; jwriteI(std.waveMacro[j]); + } + for (int j=0; jwriteI(std.pitchMacro[j]); + } + for (int j=0; jwriteI(std.ex1Macro[j]); + } + for (int j=0; jwriteI(std.ex2Macro[j]); + } + for (int j=0; jwriteI(std.ex3Macro[j]); + } +} + +bool DivInstrument::save(const char* path) { + SafeWriter* w=new SafeWriter(); + w->init(); + + // write magic + w->write("-Furnace instr.-",16); + + // write version + w->writeS(DIV_ENGINE_VERSION); + + // reserved + w->writeS(0); + + // pointer to data + w->writeI(32); + + // currently reserved (TODO; wavetable and sample here) + w->writeS(0); + w->writeS(0); + w->writeI(0); + + putInsData(w); + + FILE* outFile=fopen(path,"wb"); + if (outFile==NULL) { + logE("could not save instrument: %s!\n",strerror(errno)); + w->finish(); + return false; + } + if (fwrite(w->getFinalBuf(),1,w->size(),outFile)!=w->size()) { + logW("did not write entire instrument!\n"); + } + fclose(outFile); + w->finish(); + return true; +} \ No newline at end of file diff --git a/src/engine/instrument.h b/src/engine/instrument.h index b4ddc8a81..01b2d6f67 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -1,5 +1,6 @@ #ifndef _INSTRUMENT_H #define _INSTRUMENT_H +#include "safeWriter.h" #include "../ta-utils.h" enum DivInstrumentType { @@ -246,6 +247,8 @@ struct DivInstrument { DivInstrumentGB gb; DivInstrumentC64 c64; DivInstrumentAmiga amiga; + void putInsData(SafeWriter* w); + bool save(const char* path); DivInstrument(): name(""), mode(false), diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 1a42d9feb..55798182f 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3412,6 +3412,11 @@ bool FurnaceGUI::loop() { showError(fmt::sprintf("Error while saving file! (%s)",lastError)); } break; + case GUI_FILE_INS_SAVE: + if (curIns>=0 && curIns<(int)e->song.ins.size()) { + e->song.ins[curIns]->save(copyOfName.c_str()); + } + break; case GUI_FILE_SAMPLE_OPEN: e->addSampleFromFile(copyOfName.c_str()); modified=true; @@ -3431,7 +3436,6 @@ bool FurnaceGUI::loop() { exportAudio(copyOfName,DIV_EXPORT_MODE_MANY_CHAN); break; case GUI_FILE_INS_OPEN: - case GUI_FILE_INS_SAVE: case GUI_FILE_WAVE_OPEN: case GUI_FILE_WAVE_SAVE: case GUI_FILE_EXPORT_VGM: