mirror of
https://github.com/tildearrow/furnace.git
synced 2025-01-03 14:11:11 +00:00
add early code for saving instruments
This commit is contained in:
parent
a989fa8920
commit
dce289a5a0
5 changed files with 184 additions and 132 deletions
|
@ -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
|
||||
|
|
|
@ -1712,137 +1712,7 @@ SafeWriter* DivEngine::saveFur() {
|
|||
for (int i=0; i<song.insLen; i++) {
|
||||
DivInstrument* ins=song.ins[i];
|
||||
insPtr[i]=w->tell();
|
||||
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; j<ins->std.volMacroLen; j++) {
|
||||
w->writeI(ins->std.volMacro[j]);
|
||||
}
|
||||
for (int j=0; j<ins->std.arpMacroLen; j++) {
|
||||
w->writeI(ins->std.arpMacro[j]);
|
||||
}
|
||||
for (int j=0; j<ins->std.dutyMacroLen; j++) {
|
||||
w->writeI(ins->std.dutyMacro[j]);
|
||||
}
|
||||
for (int j=0; j<ins->std.waveMacroLen; j++) {
|
||||
w->writeI(ins->std.waveMacro[j]);
|
||||
}
|
||||
for (int j=0; j<ins->std.pitchMacroLen; j++) {
|
||||
w->writeI(ins->std.pitchMacro[j]);
|
||||
}
|
||||
for (int j=0; j<ins->std.ex1MacroLen; j++) {
|
||||
w->writeI(ins->std.ex1Macro[j]);
|
||||
}
|
||||
for (int j=0; j<ins->std.ex2MacroLen; j++) {
|
||||
w->writeI(ins->std.ex2Macro[j]);
|
||||
}
|
||||
for (int j=0; j<ins->std.ex3MacroLen; j++) {
|
||||
w->writeI(ins->std.ex3Macro[j]);
|
||||
}
|
||||
ins->putInsData(w);
|
||||
}
|
||||
|
||||
/// WAVETABLE
|
||||
|
|
174
src/engine/instrument.cpp
Normal file
174
src/engine/instrument.cpp
Normal file
|
@ -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; j<std.volMacroLen; j++) {
|
||||
w->writeI(std.volMacro[j]);
|
||||
}
|
||||
for (int j=0; j<std.arpMacroLen; j++) {
|
||||
w->writeI(std.arpMacro[j]);
|
||||
}
|
||||
for (int j=0; j<std.dutyMacroLen; j++) {
|
||||
w->writeI(std.dutyMacro[j]);
|
||||
}
|
||||
for (int j=0; j<std.waveMacroLen; j++) {
|
||||
w->writeI(std.waveMacro[j]);
|
||||
}
|
||||
for (int j=0; j<std.pitchMacroLen; j++) {
|
||||
w->writeI(std.pitchMacro[j]);
|
||||
}
|
||||
for (int j=0; j<std.ex1MacroLen; j++) {
|
||||
w->writeI(std.ex1Macro[j]);
|
||||
}
|
||||
for (int j=0; j<std.ex2MacroLen; j++) {
|
||||
w->writeI(std.ex2Macro[j]);
|
||||
}
|
||||
for (int j=0; j<std.ex3MacroLen; j++) {
|
||||
w->writeI(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;
|
||||
}
|
|
@ -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),
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue