fade out experiments - DO NOT COMPILE
This commit is contained in:
parent
d1ba9e2c3e
commit
b6ea8ede86
1
TODO.md
1
TODO.md
|
@ -1,5 +1,6 @@
|
|||
# to-do for 0.6pre1
|
||||
|
||||
- fade out in audio export
|
||||
- rewrite the system name detection function anyway
|
||||
- add another FM editor layout
|
||||
- add ability to move selection by dragging
|
||||
|
|
|
@ -193,6 +193,9 @@ bool DivEngine::isExporting() {
|
|||
|
||||
#ifdef HAVE_SNDFILE
|
||||
void DivEngine::runExportThread() {
|
||||
size_t fadeOutSamples=got.rate*exportFadeOut;
|
||||
size_t curFadeOutSample=0;
|
||||
bool isFadingOut=false;
|
||||
switch (exportMode) {
|
||||
case DIV_EXPORT_MODE_ONE: {
|
||||
SNDFILE* sf;
|
||||
|
@ -220,15 +223,36 @@ void DivEngine::runExportThread() {
|
|||
logI("rendering to file...");
|
||||
|
||||
while (playing) {
|
||||
size_t total=0;
|
||||
nextBuf(NULL,outBuf,0,2,EXPORT_BUFSIZE);
|
||||
for (int i=0; i<EXPORT_BUFSIZE; i++) {
|
||||
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]));
|
||||
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]));
|
||||
}
|
||||
if (totalProcessed>EXPORT_BUFSIZE) {
|
||||
logE("error: total processed is bigger than export bufsize! %d>%d",totalProcessed,EXPORT_BUFSIZE);
|
||||
totalProcessed=EXPORT_BUFSIZE;
|
||||
}
|
||||
if (sf_writef_float(sf,outBuf[2],totalProcessed)!=(int)totalProcessed) {
|
||||
if (totalProcessed!=EXPORT_BUFSIZE) {
|
||||
logW("wait what? %d != %d",totalProcessed,EXPORT_BUFSIZE);
|
||||
}
|
||||
for (int i=0; i<(int)totalProcessed; i++) {
|
||||
total++;
|
||||
if (isFadingOut) {
|
||||
double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples));
|
||||
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]))*mul;
|
||||
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]))*mul;
|
||||
if (++curFadeOutSample>=fadeOutSamples) {
|
||||
playing=false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]));
|
||||
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]));
|
||||
if (lastLoopPos>-1 && i>=lastLoopPos && totalLoops>=exportLoopCount) {
|
||||
logD("start fading out...");
|
||||
isFadingOut=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sf_writef_float(sf,outBuf[2],total)!=(int)total) {
|
||||
logE("error: failed to write entire buffer!");
|
||||
break;
|
||||
}
|
||||
|
@ -382,7 +406,12 @@ void DivEngine::runExportThread() {
|
|||
}
|
||||
|
||||
curOrder=0;
|
||||
remainingLoops=loopCount;
|
||||
prevOrder=0;
|
||||
if (exportFadeOut<=0.01) {
|
||||
remainingLoops=loopCount;
|
||||
} else {
|
||||
remainingLoops=-1;
|
||||
}
|
||||
playSub(false);
|
||||
|
||||
while (playing) {
|
||||
|
@ -448,13 +477,14 @@ void DivEngine::runExportThread() {
|
|||
}
|
||||
#endif
|
||||
|
||||
bool DivEngine::saveAudio(const char* path, int loops, DivAudioExportModes mode) {
|
||||
bool DivEngine::saveAudio(const char* path, int loops, DivAudioExportModes mode, double fadeOutTime) {
|
||||
#ifndef HAVE_SNDFILE
|
||||
logE("Furnace was not compiled with libsndfile. cannot export!");
|
||||
return false;
|
||||
#else
|
||||
exportPath=path;
|
||||
exportMode=mode;
|
||||
exportFadeOut=fadeOutTime;
|
||||
if (exportMode!=DIV_EXPORT_MODE_ONE) {
|
||||
// remove extension
|
||||
String lowerCase=exportPath;
|
||||
|
@ -471,7 +501,12 @@ bool DivEngine::saveAudio(const char* path, int loops, DivAudioExportModes mode)
|
|||
stop();
|
||||
repeatPattern=false;
|
||||
setOrder(0);
|
||||
remainingLoops=loops;
|
||||
if (exportFadeOut<=0.01) {
|
||||
remainingLoops=loops;
|
||||
} else {
|
||||
remainingLoops=-1;
|
||||
}
|
||||
exportLoopCount=loops;
|
||||
exportThread=new std::thread(_runExportThread,this);
|
||||
return true;
|
||||
#endif
|
||||
|
@ -1131,6 +1166,8 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) {
|
|||
totalTicks=0;
|
||||
totalSeconds=0;
|
||||
totalTicksR=0;
|
||||
totalLoops=0;
|
||||
lastLoopPos=-1;
|
||||
}
|
||||
speedAB=false;
|
||||
playing=true;
|
||||
|
|
|
@ -303,7 +303,7 @@ class DivEngine {
|
|||
bool systemsRegistered;
|
||||
bool hasLoadedSomething;
|
||||
int softLockCount;
|
||||
int subticks, ticks, curRow, curOrder, prevRow, prevOrder, remainingLoops, nextSpeed;
|
||||
int subticks, ticks, curRow, curOrder, prevRow, prevOrder, remainingLoops, totalLoops, lastLoopPos, exportLoopCount, nextSpeed;
|
||||
size_t curSubSongIndex;
|
||||
double divider;
|
||||
int cycles;
|
||||
|
@ -318,6 +318,7 @@ class DivEngine {
|
|||
DivChannelState chan[DIV_MAX_CHANS];
|
||||
DivAudioEngines audioEngine;
|
||||
DivAudioExportModes exportMode;
|
||||
double exportFadeOut;
|
||||
std::map<String,String> conf;
|
||||
std::queue<DivNoteEvent> pendingNotes;
|
||||
bool isMuted[DIV_MAX_CHANS];
|
||||
|
@ -463,7 +464,7 @@ class DivEngine {
|
|||
// dump to VGM.
|
||||
SafeWriter* saveVGM(bool* sysToExport=NULL, bool loop=true, int version=0x171);
|
||||
// export to an audio file
|
||||
bool saveAudio(const char* path, int loops, DivAudioExportModes mode);
|
||||
bool saveAudio(const char* path, int loops, DivAudioExportModes mode, double fadeOutTime=0.0);
|
||||
// wait for audio export to finish
|
||||
void waitAudioFile();
|
||||
// stop audio file export
|
||||
|
@ -938,6 +939,9 @@ class DivEngine {
|
|||
prevRow(0),
|
||||
prevOrder(0),
|
||||
remainingLoops(-1),
|
||||
totalLoops(0),
|
||||
lastLoopPos(0),
|
||||
exportLoopCount(0),
|
||||
nextSpeed(3),
|
||||
curSubSongIndex(0),
|
||||
divider(60),
|
||||
|
@ -961,6 +965,7 @@ class DivEngine {
|
|||
haltOn(DIV_HALT_NONE),
|
||||
audioEngine(DIV_AUDIO_NULL),
|
||||
exportMode(DIV_EXPORT_MODE_ONE),
|
||||
exportFadeOut(0.0),
|
||||
midiBaseChan(0),
|
||||
midiPoly(true),
|
||||
midiAgeCounter(0),
|
||||
|
|
|
@ -1096,6 +1096,8 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
}
|
||||
|
||||
void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) {
|
||||
lastLoopPos=-1;
|
||||
|
||||
if (out!=NULL) {
|
||||
memset(out[0],0,size*sizeof(float));
|
||||
memset(out[1],0,size*sizeof(float));
|
||||
|
@ -1287,6 +1289,9 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
}
|
||||
}
|
||||
if (nextTick()) {
|
||||
lastLoopPos=size-(runLeftG>>MASTER_CLOCK_PREC);
|
||||
logD("last loop pos: %d for a size of %d and runLeftG of %d",lastLoopPos,size,runLeftG);
|
||||
totalLoops++;
|
||||
if (remainingLoops>0) {
|
||||
remainingLoops--;
|
||||
if (!remainingLoops) {
|
||||
|
|
|
@ -1676,7 +1676,7 @@ int FurnaceGUI::load(String path) {
|
|||
}
|
||||
|
||||
void FurnaceGUI::exportAudio(String path, DivAudioExportModes mode) {
|
||||
e->saveAudio(path.c_str(),exportLoops+1,mode);
|
||||
e->saveAudio(path.c_str(),exportLoops+1,mode,exportFadeOut);
|
||||
displayExporting=true;
|
||||
}
|
||||
|
||||
|
@ -2827,6 +2827,9 @@ bool FurnaceGUI::loop() {
|
|||
if (ImGui::InputInt("Loops",&exportLoops,1,2)) {
|
||||
if (exportLoops<0) exportLoops=0;
|
||||
}
|
||||
if (ImGui::InputDouble("Fade out (seconds)",&exportFadeOut,1.0,2.0,"%.1f")) {
|
||||
if (exportFadeOut<0.0) exportFadeOut=0.0;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("export VGM...")) {
|
||||
|
@ -4351,6 +4354,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
latchTarget(0),
|
||||
wheelX(0),
|
||||
wheelY(0),
|
||||
exportFadeOut(5.0),
|
||||
editControlsOpen(true),
|
||||
ordersOpen(true),
|
||||
insListOpen(true),
|
||||
|
|
|
@ -1072,6 +1072,8 @@ class FurnaceGUI {
|
|||
int loopOrder, loopRow, loopEnd, isClipping, extraChannelButtons, patNameTarget, newSongCategory, latchTarget;
|
||||
int wheelX, wheelY;
|
||||
|
||||
double exportFadeOut;
|
||||
|
||||
bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
|
||||
bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen;
|
||||
bool mixerOpen, debugOpen, inspectorOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen;
|
||||
|
|
Loading…
Reference in a new issue