improve audio export options - UNTESTED/UNFINISHED
This commit is contained in:
parent
e5026e43aa
commit
008fe4b6b8
3
TODO.md
3
TODO.md
|
@ -1,5 +1,6 @@
|
||||||
# to-do for 0.6.4
|
# to-do for 0.6.4
|
||||||
|
|
||||||
|
- revamp audio export dialog
|
||||||
- fix possible issues when moving selection
|
- fix possible issues when moving selection
|
||||||
- fix Metal intro crash
|
- fix Metal intro crash
|
||||||
|
|
||||||
|
@ -7,3 +8,5 @@
|
||||||
|
|
||||||
- finish auto-clone
|
- finish auto-clone
|
||||||
- new pattern renderer - performance improvements
|
- new pattern renderer - performance improvements
|
||||||
|
- new info header
|
||||||
|
- unlimited channels and chips
|
||||||
|
|
|
@ -98,6 +98,28 @@ enum DivMIDIModes {
|
||||||
DIV_MIDI_MODE_LIGHT_SHOW
|
DIV_MIDI_MODE_LIGHT_SHOW
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DivAudioExportOptions {
|
||||||
|
DivAudioExportModes mode;
|
||||||
|
int sampleRate;
|
||||||
|
int chans;
|
||||||
|
int loops;
|
||||||
|
double fadeOut;
|
||||||
|
int orderBegin, orderEnd;
|
||||||
|
bool channelMask[DIV_MAX_CHANS];
|
||||||
|
DivAudioExportOptions():
|
||||||
|
mode(DIV_EXPORT_MODE_ONE),
|
||||||
|
sampleRate(44100),
|
||||||
|
chans(2),
|
||||||
|
loops(0),
|
||||||
|
fadeOut(0.0),
|
||||||
|
orderBegin(-1),
|
||||||
|
orderEnd(-1) {
|
||||||
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
|
channelMask[i]=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct DivChannelState {
|
struct DivChannelState {
|
||||||
std::vector<DivDelayedCommand> delayed;
|
std::vector<DivDelayedCommand> delayed;
|
||||||
int note, oldNote, lastIns, pitch, portaSpeed, portaNote;
|
int note, oldNote, lastIns, pitch, portaSpeed, portaNote;
|
||||||
|
@ -457,6 +479,7 @@ class DivEngine {
|
||||||
DivAudioEngines audioEngine;
|
DivAudioEngines audioEngine;
|
||||||
DivAudioExportModes exportMode;
|
DivAudioExportModes exportMode;
|
||||||
double exportFadeOut;
|
double exportFadeOut;
|
||||||
|
int exportOutputs;
|
||||||
DivConfig conf;
|
DivConfig conf;
|
||||||
FixedQueue<DivNoteEvent,8192> pendingNotes;
|
FixedQueue<DivNoteEvent,8192> pendingNotes;
|
||||||
// bitfield
|
// bitfield
|
||||||
|
@ -670,7 +693,7 @@ class DivEngine {
|
||||||
// export to text
|
// export to text
|
||||||
SafeWriter* saveText(bool separatePatterns=true);
|
SafeWriter* saveText(bool separatePatterns=true);
|
||||||
// export to an audio file
|
// export to an audio file
|
||||||
bool saveAudio(const char* path, int loops, DivAudioExportModes mode, double fadeOutTime=0.0);
|
bool saveAudio(const char* path, DivAudioExportOptions options);
|
||||||
// wait for audio export to finish
|
// wait for audio export to finish
|
||||||
void waitAudioFile();
|
void waitAudioFile();
|
||||||
// stop audio file export
|
// stop audio file export
|
||||||
|
@ -1360,6 +1383,7 @@ class DivEngine {
|
||||||
audioEngine(DIV_AUDIO_NULL),
|
audioEngine(DIV_AUDIO_NULL),
|
||||||
exportMode(DIV_EXPORT_MODE_ONE),
|
exportMode(DIV_EXPORT_MODE_ONE),
|
||||||
exportFadeOut(0.0),
|
exportFadeOut(0.0),
|
||||||
|
exportOutputs(2),
|
||||||
cmdStreamInt(NULL),
|
cmdStreamInt(NULL),
|
||||||
midiBaseChan(0),
|
midiBaseChan(0),
|
||||||
midiPoly(true),
|
midiPoly(true),
|
||||||
|
|
|
@ -45,7 +45,7 @@ void DivEngine::runExportThread() {
|
||||||
SF_INFO si;
|
SF_INFO si;
|
||||||
SFWrapper sfWrap;
|
SFWrapper sfWrap;
|
||||||
si.samplerate=got.rate;
|
si.samplerate=got.rate;
|
||||||
si.channels=2;
|
si.channels=exportOutputs;
|
||||||
si.format=SF_FORMAT_WAV|SF_FORMAT_PCM_16;
|
si.format=SF_FORMAT_WAV|SF_FORMAT_PCM_16;
|
||||||
|
|
||||||
sf=sfWrap.doOpen(exportPath.c_str(),SFM_WRITE,&si);
|
sf=sfWrap.doOpen(exportPath.c_str(),SFM_WRITE,&si);
|
||||||
|
@ -55,10 +55,12 @@ void DivEngine::runExportThread() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float* outBuf[3];
|
float* outBuf[DIV_MAX_OUTPUTS];
|
||||||
outBuf[0]=new float[EXPORT_BUFSIZE];
|
float* outBufFinal;
|
||||||
outBuf[1]=new float[EXPORT_BUFSIZE];
|
for (int i=0; i<exportOutputs; i++) {
|
||||||
outBuf[2]=new float[EXPORT_BUFSIZE*2];
|
outBuf[i]=new float[EXPORT_BUFSIZE];
|
||||||
|
}
|
||||||
|
outBufFinal=new float[EXPORT_BUFSIZE*exportOutputs];
|
||||||
|
|
||||||
// take control of audio output
|
// take control of audio output
|
||||||
deinitAudioBackend();
|
deinitAudioBackend();
|
||||||
|
@ -68,24 +70,27 @@ void DivEngine::runExportThread() {
|
||||||
|
|
||||||
while (playing) {
|
while (playing) {
|
||||||
size_t total=0;
|
size_t total=0;
|
||||||
nextBuf(NULL,outBuf,0,2,EXPORT_BUFSIZE);
|
nextBuf(NULL,outBuf,0,exportOutputs,EXPORT_BUFSIZE);
|
||||||
if (totalProcessed>EXPORT_BUFSIZE) {
|
if (totalProcessed>EXPORT_BUFSIZE) {
|
||||||
logE("error: total processed is bigger than export bufsize! %d>%d",totalProcessed,EXPORT_BUFSIZE);
|
logE("error: total processed is bigger than export bufsize! %d>%d",totalProcessed,EXPORT_BUFSIZE);
|
||||||
totalProcessed=EXPORT_BUFSIZE;
|
totalProcessed=EXPORT_BUFSIZE;
|
||||||
}
|
}
|
||||||
|
int fi=0;
|
||||||
for (int i=0; i<(int)totalProcessed; i++) {
|
for (int i=0; i<(int)totalProcessed; i++) {
|
||||||
total++;
|
total++;
|
||||||
if (isFadingOut) {
|
if (isFadingOut) {
|
||||||
double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples));
|
double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples));
|
||||||
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]))*mul;
|
for (int j=0; j<exportOutputs; j++) {
|
||||||
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]))*mul;
|
outBufFinal[fi++]=MAX(-1.0f,MIN(1.0f,outBuf[j][i]))*mul;
|
||||||
|
}
|
||||||
if (++curFadeOutSample>=fadeOutSamples) {
|
if (++curFadeOutSample>=fadeOutSamples) {
|
||||||
playing=false;
|
playing=false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]));
|
for (int j=0; j<exportOutputs; j++) {
|
||||||
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]));
|
outBufFinal[fi++]=MAX(-1.0f,MIN(1.0f,outBuf[j][i]));
|
||||||
|
}
|
||||||
if (lastLoopPos>-1 && i>=lastLoopPos && totalLoops>=exportLoopCount) {
|
if (lastLoopPos>-1 && i>=lastLoopPos && totalLoops>=exportLoopCount) {
|
||||||
logD("start fading out...");
|
logD("start fading out...");
|
||||||
isFadingOut=true;
|
isFadingOut=true;
|
||||||
|
@ -94,15 +99,16 @@ void DivEngine::runExportThread() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sf_writef_float(sf,outBuf[2],total)!=(int)total) {
|
if (sf_writef_float(sf,outBufFinal,total)!=(int)total) {
|
||||||
logE("error: failed to write entire buffer!");
|
logE("error: failed to write entire buffer!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] outBuf[0];
|
delete[] outBufFinal;
|
||||||
delete[] outBuf[1];
|
for (int i=0; i<exportOutputs; i++) {
|
||||||
delete[] outBuf[2];
|
delete[] outBuf[i];
|
||||||
|
}
|
||||||
|
|
||||||
if (sfWrap.doClose()!=0) {
|
if (sfWrap.doClose()!=0) {
|
||||||
logE("could not close audio file!");
|
logE("could not close audio file!");
|
||||||
|
@ -369,18 +375,17 @@ void DivEngine::runExportThread() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool DivEngine::shallSwitchCores() {
|
bool DivEngine::shallSwitchCores() {
|
||||||
// TODO: detect whether we should
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivEngine::saveAudio(const char* path, int loops, DivAudioExportModes mode, double fadeOutTime) {
|
bool DivEngine::saveAudio(const char* path, DivAudioExportOptions options) {
|
||||||
#ifndef HAVE_SNDFILE
|
#ifndef HAVE_SNDFILE
|
||||||
logE("Furnace was not compiled with libsndfile. cannot export!");
|
logE("Furnace was not compiled with libsndfile. cannot export!");
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
exportPath=path;
|
exportPath=path;
|
||||||
exportMode=mode;
|
exportMode=options.mode;
|
||||||
exportFadeOut=fadeOutTime;
|
exportFadeOut=options.fadeOut;
|
||||||
if (exportMode!=DIV_EXPORT_MODE_ONE) {
|
if (exportMode!=DIV_EXPORT_MODE_ONE) {
|
||||||
// remove extension
|
// remove extension
|
||||||
String lowerCase=exportPath;
|
String lowerCase=exportPath;
|
||||||
|
@ -412,7 +417,12 @@ bool DivEngine::saveAudio(const char* path, int loops, DivAudioExportModes mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exportLoopCount=loops;
|
got.rate=options.sampleRate;
|
||||||
|
exportOutputs=options.chans;
|
||||||
|
if (exportOutputs<1) exportOutputs=1;
|
||||||
|
if (exportOutputs>DIV_MAX_OUTPUTS) exportOutputs=DIV_MAX_OUTPUTS;
|
||||||
|
|
||||||
|
exportLoopCount=options.loops+1;
|
||||||
exportThread=new std::thread(_runExportThread,this);
|
exportThread=new std::thread(_runExportThread,this);
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,14 +26,35 @@
|
||||||
void FurnaceGUI::drawExportAudio(bool onWindow) {
|
void FurnaceGUI::drawExportAudio(bool onWindow) {
|
||||||
exitDisabledTimer=1;
|
exitDisabledTimer=1;
|
||||||
|
|
||||||
ImGui::RadioButton("one file",&audioExportType,0);
|
ImGui::Text("Export type:");
|
||||||
ImGui::RadioButton("multiple files (one per chip)",&audioExportType,1);
|
|
||||||
ImGui::RadioButton("multiple files (one per channel)",&audioExportType,2);
|
ImGui::Indent();
|
||||||
if (ImGui::InputInt("Loops",&exportLoops,1,2)) {
|
if (ImGui::RadioButton("one file",audioExportOptions.mode==DIV_EXPORT_MODE_ONE)) {
|
||||||
if (exportLoops<0) exportLoops=0;
|
audioExportOptions.mode=DIV_EXPORT_MODE_ONE;
|
||||||
}
|
}
|
||||||
if (ImGui::InputDouble("Fade out (seconds)",&exportFadeOut,1.0,2.0,"%.1f")) {
|
if (ImGui::RadioButton("multiple files (one per chip)",audioExportOptions.mode==DIV_EXPORT_MODE_MANY_SYS)) {
|
||||||
if (exportFadeOut<0.0) exportFadeOut=0.0;
|
audioExportOptions.mode=DIV_EXPORT_MODE_MANY_SYS;
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("multiple files (one per channel)",audioExportOptions.mode==DIV_EXPORT_MODE_MANY_CHAN)) {
|
||||||
|
audioExportOptions.mode=DIV_EXPORT_MODE_MANY_CHAN;
|
||||||
|
}
|
||||||
|
ImGui::Unindent();
|
||||||
|
|
||||||
|
if (ImGui::InputInt("Sample rate",&audioExportOptions.sampleRate,100,10000)) {
|
||||||
|
if (audioExportOptions.sampleRate<8000) audioExportOptions.sampleRate=8000;
|
||||||
|
if (audioExportOptions.sampleRate>384000) audioExportOptions.sampleRate=384000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::InputInt("Channels in file",&audioExportOptions.chans,1,1)) {
|
||||||
|
if (audioExportOptions.chans<1) audioExportOptions.chans=1;
|
||||||
|
if (audioExportOptions.chans>16) audioExportOptions.chans=16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::InputInt("Loops",&audioExportOptions.loops,1,2)) {
|
||||||
|
if (audioExportOptions.loops<0) audioExportOptions.loops=0;
|
||||||
|
}
|
||||||
|
if (ImGui::InputDouble("Fade out (seconds)",&audioExportOptions.fadeOut,1.0,2.0,"%.1f")) {
|
||||||
|
if (audioExportOptions.fadeOut<0.0) audioExportOptions.fadeOut=0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onWindow) {
|
if (onWindow) {
|
||||||
|
@ -43,14 +64,14 @@ void FurnaceGUI::drawExportAudio(bool onWindow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
|
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
|
||||||
switch (audioExportType) {
|
switch (audioExportOptions.mode) {
|
||||||
case 0:
|
case DIV_EXPORT_MODE_ONE:
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case DIV_EXPORT_MODE_MANY_SYS:
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case DIV_EXPORT_MODE_MANY_CHAN:
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2436,7 +2436,7 @@ int FurnaceGUI::loadStream(String path) {
|
||||||
|
|
||||||
|
|
||||||
void FurnaceGUI::exportAudio(String path, DivAudioExportModes mode) {
|
void FurnaceGUI::exportAudio(String path, DivAudioExportModes mode) {
|
||||||
e->saveAudio(path.c_str(),exportLoops+1,mode,exportFadeOut);
|
e->saveAudio(path.c_str(),audioExportOptions);
|
||||||
displayExporting=true;
|
displayExporting=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6761,10 +6761,10 @@ bool FurnaceGUI::init() {
|
||||||
followOrders=e->getConfBool("followOrders",true);
|
followOrders=e->getConfBool("followOrders",true);
|
||||||
followPattern=e->getConfBool("followPattern",true);
|
followPattern=e->getConfBool("followPattern",true);
|
||||||
noteInputPoly=e->getConfBool("noteInputPoly",true);
|
noteInputPoly=e->getConfBool("noteInputPoly",true);
|
||||||
exportLoops=e->getConfInt("exportLoops",0);
|
audioExportOptions.loops=e->getConfInt("exportLoops",0);
|
||||||
if (exportLoops<0) exportLoops=0;
|
if (audioExportOptions.loops<0) audioExportOptions.loops=0;
|
||||||
exportFadeOut=e->getConfDouble("exportFadeOut",0.0);
|
audioExportOptions.fadeOut=e->getConfDouble("exportFadeOut",0.0);
|
||||||
if (exportFadeOut<0.0) exportFadeOut=0.0;
|
if (audioExportOptions.fadeOut<0.0) audioExportOptions.fadeOut=0.0;
|
||||||
orderEditMode=e->getConfInt("orderEditMode",0);
|
orderEditMode=e->getConfInt("orderEditMode",0);
|
||||||
if (orderEditMode<0) orderEditMode=0;
|
if (orderEditMode<0) orderEditMode=0;
|
||||||
if (orderEditMode>3) orderEditMode=3;
|
if (orderEditMode>3) orderEditMode=3;
|
||||||
|
@ -6826,8 +6826,8 @@ bool FurnaceGUI::init() {
|
||||||
syncTutorial();
|
syncTutorial();
|
||||||
|
|
||||||
if (!settings.persistFadeOut) {
|
if (!settings.persistFadeOut) {
|
||||||
exportLoops=settings.exportLoops;
|
audioExportOptions.loops=settings.exportLoops;
|
||||||
exportFadeOut=settings.exportFadeOut;
|
audioExportOptions.fadeOut=settings.exportFadeOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<settings.maxRecentFile; i++) {
|
for (int i=0; i<settings.maxRecentFile; i++) {
|
||||||
|
@ -7320,8 +7320,8 @@ void FurnaceGUI::commitState() {
|
||||||
e->setConf("orderEditMode",orderEditMode);
|
e->setConf("orderEditMode",orderEditMode);
|
||||||
e->setConf("noteInputPoly",noteInputPoly);
|
e->setConf("noteInputPoly",noteInputPoly);
|
||||||
if (settings.persistFadeOut) {
|
if (settings.persistFadeOut) {
|
||||||
e->setConf("exportLoops",exportLoops);
|
e->setConf("exportLoops",audioExportOptions.loops);
|
||||||
e->setConf("exportFadeOut",exportFadeOut);
|
e->setConf("exportFadeOut",audioExportOptions.fadeOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
// commit oscilloscope state
|
// commit oscilloscope state
|
||||||
|
@ -7581,7 +7581,6 @@ FurnaceGUI::FurnaceGUI():
|
||||||
oldRow(0),
|
oldRow(0),
|
||||||
editStep(1),
|
editStep(1),
|
||||||
editStepCoarse(16),
|
editStepCoarse(16),
|
||||||
exportLoops(0),
|
|
||||||
soloChan(-1),
|
soloChan(-1),
|
||||||
orderEditMode(0),
|
orderEditMode(0),
|
||||||
orderCursor(-1),
|
orderCursor(-1),
|
||||||
|
@ -7604,7 +7603,6 @@ FurnaceGUI::FurnaceGUI():
|
||||||
curPaletteChoice(0),
|
curPaletteChoice(0),
|
||||||
curPaletteType(0),
|
curPaletteType(0),
|
||||||
soloTimeout(0.0f),
|
soloTimeout(0.0f),
|
||||||
exportFadeOut(5.0),
|
|
||||||
patExtraButtons(false),
|
patExtraButtons(false),
|
||||||
patChannelNames(false),
|
patChannelNames(false),
|
||||||
patChannelPairs(true),
|
patChannelPairs(true),
|
||||||
|
@ -7955,7 +7953,6 @@ FurnaceGUI::FurnaceGUI():
|
||||||
introStopped(false),
|
introStopped(false),
|
||||||
curTutorial(-1),
|
curTutorial(-1),
|
||||||
curTutorialStep(0),
|
curTutorialStep(0),
|
||||||
audioExportType(0),
|
|
||||||
dmfExportVersion(0),
|
dmfExportVersion(0),
|
||||||
curExportType(GUI_EXPORT_NONE) {
|
curExportType(GUI_EXPORT_NONE) {
|
||||||
// value keys
|
// value keys
|
||||||
|
|
|
@ -2194,15 +2194,13 @@ class FurnaceGUI {
|
||||||
int pendingLayoutImportStep;
|
int pendingLayoutImportStep;
|
||||||
FixedQueue<bool*,64> pendingLayoutImportReopen;
|
FixedQueue<bool*,64> pendingLayoutImportReopen;
|
||||||
|
|
||||||
int curIns, curWave, curSample, curOctave, curOrder, playOrder, prevIns, oldRow, editStep, editStepCoarse, exportLoops, soloChan, orderEditMode, orderCursor;
|
int curIns, curWave, curSample, curOctave, curOrder, playOrder, prevIns, oldRow, editStep, editStepCoarse, soloChan, orderEditMode, orderCursor;
|
||||||
int loopOrder, loopRow, loopEnd, isClipping, newSongCategory, latchTarget;
|
int loopOrder, loopRow, loopEnd, isClipping, newSongCategory, latchTarget;
|
||||||
int wheelX, wheelY, dragSourceX, dragSourceXFine, dragSourceY, dragDestinationX, dragDestinationXFine, dragDestinationY, oldBeat, oldBar;
|
int wheelX, wheelY, dragSourceX, dragSourceXFine, dragSourceY, dragDestinationX, dragDestinationXFine, dragDestinationY, oldBeat, oldBar;
|
||||||
int curGroove, exitDisabledTimer;
|
int curGroove, exitDisabledTimer;
|
||||||
int curPaletteChoice, curPaletteType;
|
int curPaletteChoice, curPaletteType;
|
||||||
float soloTimeout;
|
float soloTimeout;
|
||||||
|
|
||||||
double exportFadeOut;
|
|
||||||
|
|
||||||
bool patExtraButtons, patChannelNames, patChannelPairs;
|
bool patExtraButtons, patChannelNames, patChannelPairs;
|
||||||
unsigned char patChannelHints;
|
unsigned char patChannelHints;
|
||||||
|
|
||||||
|
@ -2603,7 +2601,7 @@ class FurnaceGUI {
|
||||||
ImGuiListClipper csClipper;
|
ImGuiListClipper csClipper;
|
||||||
|
|
||||||
// export options
|
// export options
|
||||||
int audioExportType;
|
DivAudioExportOptions audioExportOptions;
|
||||||
int dmfExportVersion;
|
int dmfExportVersion;
|
||||||
FurnaceGUIExportTypes curExportType;
|
FurnaceGUIExportTypes curExportType;
|
||||||
|
|
||||||
|
|
|
@ -705,13 +705,13 @@ void FurnaceGUI::drawSettings() {
|
||||||
ImGui::BeginDisabled(settings.persistFadeOut);
|
ImGui::BeginDisabled(settings.persistFadeOut);
|
||||||
ImGui::Indent();
|
ImGui::Indent();
|
||||||
if (ImGui::InputInt("Loops",&settings.exportLoops,1,2)) {
|
if (ImGui::InputInt("Loops",&settings.exportLoops,1,2)) {
|
||||||
if (exportLoops<0) exportLoops=0;
|
if (settings.exportLoops<0) settings.exportLoops=0;
|
||||||
exportLoops=settings.exportLoops;
|
audioExportOptions.loops=settings.exportLoops;
|
||||||
settingsChanged=true;
|
settingsChanged=true;
|
||||||
}
|
}
|
||||||
if (ImGui::InputDouble("Fade out (seconds)",&settings.exportFadeOut,1.0,2.0,"%.1f")) {
|
if (ImGui::InputDouble("Fade out (seconds)",&settings.exportFadeOut,1.0,2.0,"%.1f")) {
|
||||||
if (exportFadeOut<0.0) exportFadeOut=0.0;
|
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
|
||||||
exportFadeOut=settings.exportFadeOut;
|
audioExportOptions.fadeOut=settings.exportFadeOut;
|
||||||
settingsChanged=true;
|
settingsChanged=true;
|
||||||
}
|
}
|
||||||
ImGui::Unindent();
|
ImGui::Unindent();
|
||||||
|
|
17
src/main.cpp
17
src/main.cpp
|
@ -66,10 +66,9 @@ String outName;
|
||||||
String vgmOutName;
|
String vgmOutName;
|
||||||
String zsmOutName;
|
String zsmOutName;
|
||||||
String cmdOutName;
|
String cmdOutName;
|
||||||
int loops=1;
|
|
||||||
int benchMode=0;
|
int benchMode=0;
|
||||||
int subsong=-1;
|
int subsong=-1;
|
||||||
DivAudioExportModes outMode=DIV_EXPORT_MODE_ONE;
|
DivAudioExportOptions exportOptions;
|
||||||
|
|
||||||
#ifdef HAVE_GUI
|
#ifdef HAVE_GUI
|
||||||
bool consoleMode=false;
|
bool consoleMode=false;
|
||||||
|
@ -299,9 +298,9 @@ TAParamResult pLoops(String val) {
|
||||||
try {
|
try {
|
||||||
int count=std::stoi(val);
|
int count=std::stoi(val);
|
||||||
if (count<0) {
|
if (count<0) {
|
||||||
loops=0;
|
exportOptions.loops=0;
|
||||||
} else {
|
} else {
|
||||||
loops=count+1;
|
exportOptions.loops=count;
|
||||||
}
|
}
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
logE("loop count shall be a number.");
|
logE("loop count shall be a number.");
|
||||||
|
@ -327,11 +326,11 @@ TAParamResult pSubSong(String val) {
|
||||||
|
|
||||||
TAParamResult pOutMode(String val) {
|
TAParamResult pOutMode(String val) {
|
||||||
if (val=="one") {
|
if (val=="one") {
|
||||||
outMode=DIV_EXPORT_MODE_ONE;
|
exportOptions.mode=DIV_EXPORT_MODE_ONE;
|
||||||
} else if (val=="persys") {
|
} else if (val=="persys") {
|
||||||
outMode=DIV_EXPORT_MODE_MANY_SYS;
|
exportOptions.mode=DIV_EXPORT_MODE_MANY_SYS;
|
||||||
} else if (val=="perchan") {
|
} else if (val=="perchan") {
|
||||||
outMode=DIV_EXPORT_MODE_MANY_CHAN;
|
exportOptions.mode=DIV_EXPORT_MODE_MANY_CHAN;
|
||||||
} else {
|
} else {
|
||||||
logE("invalid value for outmode! valid values are: one, persys and perchan.");
|
logE("invalid value for outmode! valid values are: one, persys and perchan.");
|
||||||
return TA_PARAM_ERROR;
|
return TA_PARAM_ERROR;
|
||||||
|
@ -401,7 +400,7 @@ void initParams() {
|
||||||
params.push_back(TAParam("n","nostatus",false,pNoStatus,"","disable playback status in console mode"));
|
params.push_back(TAParam("n","nostatus",false,pNoStatus,"","disable playback status in console mode"));
|
||||||
params.push_back(TAParam("N","nocontrols",false,pNoControls,"","disable standard input controls in console mode"));
|
params.push_back(TAParam("N","nocontrols",false,pNoControls,"","disable standard input controls in console mode"));
|
||||||
|
|
||||||
params.push_back(TAParam("l","loops",true,pLoops,"<count>","set number of loops (-1 means loop forever)"));
|
params.push_back(TAParam("l","loops",true,pLoops,"<count>","set number of loops"));
|
||||||
params.push_back(TAParam("s","subsong",true,pSubSong,"<number>","set sub-song"));
|
params.push_back(TAParam("s","subsong",true,pSubSong,"<number>","set sub-song"));
|
||||||
params.push_back(TAParam("o","outmode",true,pOutMode,"one|persys|perchan","set file output mode"));
|
params.push_back(TAParam("o","outmode",true,pOutMode,"one|persys|perchan","set file output mode"));
|
||||||
params.push_back(TAParam("S","safemode",false,pSafeMode,"","enable safe mode (software rendering and no audio)"));
|
params.push_back(TAParam("S","safemode",false,pSafeMode,"","enable safe mode (software rendering and no audio)"));
|
||||||
|
@ -716,7 +715,7 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
if (outName!="") {
|
if (outName!="") {
|
||||||
e.setConsoleMode(true);
|
e.setConsoleMode(true);
|
||||||
e.saveAudio(outName.c_str(),loops,outMode);
|
e.saveAudio(outName.c_str(),exportOptions);
|
||||||
e.waitAudioFile();
|
e.waitAudioFile();
|
||||||
}
|
}
|
||||||
finishLogFile();
|
finishLogFile();
|
||||||
|
|
Loading…
Reference in a new issue