Merge branch 'master' into dx9
This commit is contained in:
commit
c9147b5152
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -11,7 +11,7 @@ defaults:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
env:
|
env:
|
||||||
BUILD_TYPE: RelWithDebInfo
|
BUILD_TYPE: Debug
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,6 +5,7 @@ nosdl/
|
||||||
release/
|
release/
|
||||||
t/
|
t/
|
||||||
winbuild/
|
winbuild/
|
||||||
|
winCbuild/
|
||||||
win32build/
|
win32build/
|
||||||
xpbuild/
|
xpbuild/
|
||||||
macbuild/
|
macbuild/
|
||||||
|
|
|
@ -122,6 +122,7 @@ option(WITH_DEMOS "Install demo songs" ON)
|
||||||
option(WITH_INSTRUMENTS "Install instruments" ON)
|
option(WITH_INSTRUMENTS "Install instruments" ON)
|
||||||
option(WITH_WAVETABLES "Install wavetables" ON)
|
option(WITH_WAVETABLES "Install wavetables" ON)
|
||||||
option(SHOW_OPEN_ASSETS_MENU_ENTRY "Show option to open built-in assets directory (on supported platforms)" OFF)
|
option(SHOW_OPEN_ASSETS_MENU_ENTRY "Show option to open built-in assets directory (on supported platforms)" OFF)
|
||||||
|
option(CONSOLE_SUBSYSTEM "Build Furnace with Console subsystem on Windows" OFF)
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
option(FORCE_APPLE_BIN "Force enable binary installation to /bin" OFF)
|
option(FORCE_APPLE_BIN "Force enable binary installation to /bin" OFF)
|
||||||
else()
|
else()
|
||||||
|
@ -1081,7 +1082,7 @@ elseif (APPLE)
|
||||||
find_library(COCOA Cocoa REQUIRED)
|
find_library(COCOA Cocoa REQUIRED)
|
||||||
list(APPEND DEPENDENCIES_LIBRARIES ${COCOA})
|
list(APPEND DEPENDENCIES_LIBRARIES ${COCOA})
|
||||||
else()
|
else()
|
||||||
list(APPEND DEPENDENCIES_LIBRARIES dl)
|
list(APPEND DEPENDENCIES_LIBRARIES ${CMAKE_DL_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
|
@ -1128,9 +1129,13 @@ if (NOT ANDROID OR TERMUX)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (WIN32 AND CONSOLE_SUBSYSTEM)
|
||||||
|
list(APPEND DEPENDENCIES_DEFINES "TA_SUBSYSTEM_CONSOLE")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ANDROID AND NOT TERMUX)
|
if(ANDROID AND NOT TERMUX)
|
||||||
add_library(furnace SHARED ${USED_SOURCES})
|
add_library(furnace SHARED ${USED_SOURCES})
|
||||||
elseif(WIN32)
|
elseif(WIN32 AND NOT CONSOLE_SUBSYSTEM)
|
||||||
add_executable(furnace WIN32 ${USED_SOURCES})
|
add_executable(furnace WIN32 ${USED_SOURCES})
|
||||||
else()
|
else()
|
||||||
add_executable(furnace ${USED_SOURCES})
|
add_executable(furnace ${USED_SOURCES})
|
||||||
|
|
|
@ -280,6 +280,7 @@ Available options:
|
||||||
| `WITH_INSTRUMENTS` | `ON` | Install demo instruments on `make install` |
|
| `WITH_INSTRUMENTS` | `ON` | Install demo instruments on `make install` |
|
||||||
| `WITH_WAVETABLES` | `ON` | Install wavetables on `make install` |
|
| `WITH_WAVETABLES` | `ON` | Install wavetables on `make install` |
|
||||||
| `SHOW_OPEN_ASSETS_MENU_ENTRY` | `OFF` | Show option to open built-in assets directory (on supported platforms) |
|
| `SHOW_OPEN_ASSETS_MENU_ENTRY` | `OFF` | Show option to open built-in assets directory (on supported platforms) |
|
||||||
|
| `CONSOLE_SUBSYSTEM` | `OFF` | Build with subsystem set to Console on Windows |
|
||||||
| `FORCE_APPLE_BIN` | `OFF` | Enable installation of binaries (when doing `make install`) to PREFIX/bin on Apple platforms |
|
| `FORCE_APPLE_BIN` | `OFF` | Enable installation of binaries (when doing `make install`) to PREFIX/bin on Apple platforms |
|
||||||
|
|
||||||
(\*) `ON` if system-installed JACK detected, otherwise `OFF`
|
(\*) `ON` if system-installed JACK detected, otherwise `OFF`
|
||||||
|
|
8
TODO.md
8
TODO.md
|
@ -1,4 +1,12 @@
|
||||||
|
# to-do for 0.6.4
|
||||||
|
|
||||||
|
- revamp audio export dialog
|
||||||
|
- fix possible issues when moving selection
|
||||||
|
- fix Metal intro crash
|
||||||
|
|
||||||
# to-do long term
|
# to-do long term
|
||||||
|
|
||||||
- finish auto-clone
|
- finish auto-clone
|
||||||
- new pattern renderer - performance improvements
|
- new pattern renderer - performance improvements
|
||||||
|
- new info header
|
||||||
|
- unlimited channels and chips
|
||||||
|
|
2
extern/igfd/ImGuiFileDialog.cpp
vendored
2
extern/igfd/ImGuiFileDialog.cpp
vendored
|
@ -54,7 +54,7 @@ SOFTWARE.
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
#define PATH_MAX 260
|
#define PATH_MAX 260
|
||||||
#endif // PATH_MAX
|
#endif // PATH_MAX
|
||||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined (__EMSCRIPTEN__) || defined(__HAIKU__)
|
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined (__EMSCRIPTEN__) || defined(__HAIKU__)
|
||||||
#define UNIX
|
#define UNIX
|
||||||
#define stricmp strcasecmp
|
#define stricmp strcasecmp
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
42
scripts/release-winconsole.sh
Executable file
42
scripts/release-winconsole.sh
Executable file
|
@ -0,0 +1,42 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# make Windows release
|
||||||
|
# this script shall be run from Arch Linux with MinGW installed!
|
||||||
|
|
||||||
|
if [ ! -e /tmp/furnace ]; then
|
||||||
|
ln -s "$PWD" /tmp/furnace || exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd /tmp/furnace
|
||||||
|
|
||||||
|
if [ ! -e winCbuild ]; then
|
||||||
|
mkdir winCbuild || exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd winCbuild
|
||||||
|
|
||||||
|
# TODO: potential Arch-ism?
|
||||||
|
x86_64-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Wno-cast-function-type -Wno-deprecated-declarations -Werror" -DUSE_BACKWARD=ON -DCONSOLE_SUBSYSTEM=ON .. || exit 1
|
||||||
|
make -j8 || exit 1
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
mkdir -p release/winconsole || exit 1
|
||||||
|
cd release/winconsole
|
||||||
|
|
||||||
|
cp ../../LICENSE LICENSE.txt || exit 1
|
||||||
|
cp ../../winCbuild/furnace.exe . || exit 1
|
||||||
|
cp ../../res/releaseReadme/stable-win.txt README.txt || exit 1
|
||||||
|
cp -r ../../papers papers || exit 1
|
||||||
|
cp -r ../../demos demos || exit 1
|
||||||
|
cp -r ../../instruments instruments || exit 1
|
||||||
|
cp -r ../../wavetables wavetables || exit 1
|
||||||
|
|
||||||
|
cp ../../res/docpdf/manual.pdf . || exit 1
|
||||||
|
|
||||||
|
x86_64-w64-mingw32-strip -s furnace.exe || exit 1
|
||||||
|
|
||||||
|
zip -r furnace.zip LICENSE.txt furnace.exe README.txt manual.pdf papers demos instruments wavetables
|
||||||
|
|
||||||
|
furName=$(git describe --tags | sed "s/v0/0/")
|
||||||
|
|
||||||
|
mv furnace.zip furnace-"$furName"-win64-console.zip
|
|
@ -1095,7 +1095,7 @@ bool DivEngine::changeSystem(int index, DivSystem which, bool preserveOrder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivEngine::addSystem(DivSystem which) {
|
bool DivEngine::addSystem(DivSystem which) {
|
||||||
if (song.systemLen>DIV_MAX_CHIPS) {
|
if (song.systemLen>=DIV_MAX_CHIPS) {
|
||||||
lastError=fmt::sprintf("max number of systems is %d",DIV_MAX_CHIPS);
|
lastError=fmt::sprintf("max number of systems is %d",DIV_MAX_CHIPS);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1149,7 +1149,7 @@ bool DivEngine::duplicateSystem(int index, bool pat, bool end) {
|
||||||
lastError="invalid index";
|
lastError="invalid index";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (song.systemLen>DIV_MAX_CHIPS) {
|
if (song.systemLen>=DIV_MAX_CHIPS) {
|
||||||
lastError=fmt::sprintf("max number of systems is %d",DIV_MAX_CHIPS);
|
lastError=fmt::sprintf("max number of systems is %d",DIV_MAX_CHIPS);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,35 @@ enum DivMIDIModes {
|
||||||
DIV_MIDI_MODE_LIGHT_SHOW
|
DIV_MIDI_MODE_LIGHT_SHOW
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DivAudioExportFormats {
|
||||||
|
DIV_EXPORT_FORMAT_S16=0,
|
||||||
|
DIV_EXPORT_FORMAT_F32
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DivAudioExportOptions {
|
||||||
|
DivAudioExportModes mode;
|
||||||
|
DivAudioExportFormats format;
|
||||||
|
int sampleRate;
|
||||||
|
int chans;
|
||||||
|
int loops;
|
||||||
|
double fadeOut;
|
||||||
|
int orderBegin, orderEnd;
|
||||||
|
bool channelMask[DIV_MAX_CHANS];
|
||||||
|
DivAudioExportOptions():
|
||||||
|
mode(DIV_EXPORT_MODE_ONE),
|
||||||
|
format(DIV_EXPORT_FORMAT_S16),
|
||||||
|
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;
|
||||||
|
@ -456,7 +485,10 @@ class DivEngine {
|
||||||
DivChannelState chan[DIV_MAX_CHANS];
|
DivChannelState chan[DIV_MAX_CHANS];
|
||||||
DivAudioEngines audioEngine;
|
DivAudioEngines audioEngine;
|
||||||
DivAudioExportModes exportMode;
|
DivAudioExportModes exportMode;
|
||||||
|
DivAudioExportFormats exportFormat;
|
||||||
double exportFadeOut;
|
double exportFadeOut;
|
||||||
|
int exportOutputs;
|
||||||
|
bool exportChannelMask[DIV_MAX_CHANS];
|
||||||
DivConfig conf;
|
DivConfig conf;
|
||||||
FixedQueue<DivNoteEvent,8192> pendingNotes;
|
FixedQueue<DivNoteEvent,8192> pendingNotes;
|
||||||
// bitfield
|
// bitfield
|
||||||
|
@ -670,7 +702,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
|
||||||
|
@ -1359,7 +1391,9 @@ class DivEngine {
|
||||||
haltOn(DIV_HALT_NONE),
|
haltOn(DIV_HALT_NONE),
|
||||||
audioEngine(DIV_AUDIO_NULL),
|
audioEngine(DIV_AUDIO_NULL),
|
||||||
exportMode(DIV_EXPORT_MODE_ONE),
|
exportMode(DIV_EXPORT_MODE_ONE),
|
||||||
|
exportFormat(DIV_EXPORT_FORMAT_S16),
|
||||||
exportFadeOut(0.0),
|
exportFadeOut(0.0),
|
||||||
|
exportOutputs(2),
|
||||||
cmdStreamInt(NULL),
|
cmdStreamInt(NULL),
|
||||||
midiBaseChan(0),
|
midiBaseChan(0),
|
||||||
midiPoly(true),
|
midiPoly(true),
|
||||||
|
@ -1411,6 +1445,7 @@ class DivEngine {
|
||||||
memset(sysDefs,0,DIV_MAX_CHIP_DEFS*sizeof(void*));
|
memset(sysDefs,0,DIV_MAX_CHIP_DEFS*sizeof(void*));
|
||||||
memset(walked,0,8192);
|
memset(walked,0,8192);
|
||||||
memset(oscBuf,0,DIV_MAX_OUTPUTS*(sizeof(float*)));
|
memset(oscBuf,0,DIV_MAX_OUTPUTS*(sizeof(float*)));
|
||||||
|
memset(exportChannelMask,1,DIV_MAX_CHANS*sizeof(bool));
|
||||||
|
|
||||||
for (int i=0; i<DIV_MAX_CHIP_DEFS; i++) {
|
for (int i=0; i<DIV_MAX_CHIP_DEFS; i++) {
|
||||||
sysFileMapFur[i]=DIV_SYSTEM_NULL;
|
sysFileMapFur[i]=DIV_SYSTEM_NULL;
|
||||||
|
|
|
@ -362,6 +362,29 @@ void DivPlatformAY8930::tick(bool sysTick) {
|
||||||
immWrite(regPeriodL[i],chan[i].envelope.period);
|
immWrite(regPeriodL[i],chan[i].envelope.period);
|
||||||
immWrite(regPeriodH[i],chan[i].envelope.period>>8);
|
immWrite(regPeriodH[i],chan[i].envelope.period>>8);
|
||||||
}
|
}
|
||||||
|
if (chan[i].freqChanged && chan[i].autoNoiseMode) {
|
||||||
|
int noiseFreq=chan[i].freq;
|
||||||
|
switch (chan[i].autoNoiseMode) {
|
||||||
|
case 1: // noise
|
||||||
|
noiseFreq+=chan[i].autoNoiseOff;
|
||||||
|
if (noiseFreq<0) noiseFreq=0;
|
||||||
|
if (noiseFreq>255) noiseFreq=255;
|
||||||
|
rWrite(0x06,noiseFreq);
|
||||||
|
break;
|
||||||
|
case 2: { // noise + OR mask
|
||||||
|
if (noiseFreq<0) noiseFreq=0;
|
||||||
|
int noiseDiv=(noiseFreq>>8)+1;
|
||||||
|
noiseFreq/=noiseDiv;
|
||||||
|
ayNoiseOr=noiseDiv;
|
||||||
|
immWrite(0x1a,ayNoiseOr);
|
||||||
|
noiseFreq+=chan[i].autoNoiseOff;
|
||||||
|
if (noiseFreq<0) noiseFreq=0;
|
||||||
|
if (noiseFreq>255) noiseFreq=255;
|
||||||
|
rWrite(0x06,noiseFreq);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
chan[i].freqChanged=false;
|
chan[i].freqChanged=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,6 +655,12 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
|
||||||
chan[c.chan].autoEnvDen=c.value&15;
|
chan[c.chan].autoEnvDen=c.value&15;
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
case DIV_CMD_AY_AUTO_PWM:
|
||||||
|
chan[c.chan].autoNoiseMode=c.value>>4;
|
||||||
|
chan[c.chan].autoNoiseOff=c.value&15;
|
||||||
|
if (chan[c.chan].autoNoiseOff>=8) chan[c.chan].autoNoiseOff-=16;
|
||||||
|
chan[c.chan].freqChanged=true;
|
||||||
|
break;
|
||||||
case DIV_CMD_AY_IO_WRITE:
|
case DIV_CMD_AY_IO_WRITE:
|
||||||
if (c.value==255) {
|
if (c.value==255) {
|
||||||
immWrite(0x1f,c.value2);
|
immWrite(0x1f,c.value2);
|
||||||
|
|
|
@ -77,8 +77,8 @@ class DivPlatformAY8930: public DivDispatch {
|
||||||
setPos(false) {}
|
setPos(false) {}
|
||||||
} dac;
|
} dac;
|
||||||
|
|
||||||
unsigned char autoEnvNum, autoEnvDen, duty;
|
unsigned char autoEnvNum, autoEnvDen, duty, autoNoiseMode;
|
||||||
signed char konCycles;
|
signed char konCycles, autoNoiseOff;
|
||||||
Channel():
|
Channel():
|
||||||
SharedChannel<int>(31),
|
SharedChannel<int>(31),
|
||||||
envelope(Envelope()),
|
envelope(Envelope()),
|
||||||
|
@ -88,7 +88,9 @@ class DivPlatformAY8930: public DivDispatch {
|
||||||
autoEnvNum(0),
|
autoEnvNum(0),
|
||||||
autoEnvDen(0),
|
autoEnvDen(0),
|
||||||
duty(4),
|
duty(4),
|
||||||
konCycles(0) {}
|
autoNoiseMode(0),
|
||||||
|
konCycles(0),
|
||||||
|
autoNoiseOff(0) {}
|
||||||
};
|
};
|
||||||
Channel chan[3];
|
Channel chan[3];
|
||||||
bool isMuted[3];
|
bool isMuted[3];
|
||||||
|
|
|
@ -437,14 +437,24 @@ void DivEngine::registerSystems() {
|
||||||
{0x2f, {DIV_CMD_AY_IO_WRITE, "2Fxx: Write to I/O port B", constVal<1>, effectVal}},
|
{0x2f, {DIV_CMD_AY_IO_WRITE, "2Fxx: Write to I/O port B", constVal<1>, effectVal}},
|
||||||
};
|
};
|
||||||
|
|
||||||
EffectHandlerMap ay8930PostEffectHandlerMap(ayPostEffectHandlerMap);
|
EffectHandlerMap ay8930PostEffectHandlerMap={
|
||||||
ay8930PostEffectHandlerMap.insert({
|
{0x20, {DIV_CMD_STD_NOISE_MODE, "20xx: Set channel mode (bit 0: square; bit 1: noise; bit 2: envelope)"}},
|
||||||
|
{0x21, {DIV_CMD_STD_NOISE_FREQ, "21xx: Set noise frequency (0 to FF)"}},
|
||||||
|
{0x22, {DIV_CMD_AY_ENVELOPE_SET, "22xy: Set envelope mode (x: shape, y: enable for this channel)"}},
|
||||||
|
{0x23, {DIV_CMD_AY_ENVELOPE_LOW, "23xx: Set envelope period low byte"}},
|
||||||
|
{0x24, {DIV_CMD_AY_ENVELOPE_HIGH, "24xx: Set envelope period high byte"}},
|
||||||
|
{0x25, {DIV_CMD_AY_ENVELOPE_SLIDE, "25xx: Envelope slide up", negEffectVal}},
|
||||||
|
{0x26, {DIV_CMD_AY_ENVELOPE_SLIDE, "26xx: Envelope slide down"}},
|
||||||
|
{0x29, {DIV_CMD_AY_AUTO_ENVELOPE, "29xy: Set auto-envelope (x: numerator; y: denominator)"}},
|
||||||
|
{0x2e, {DIV_CMD_AY_IO_WRITE, "2Exx: Write to I/O port A", constVal<0>, effectVal}},
|
||||||
|
{0x2f, {DIV_CMD_AY_IO_WRITE, "2Fxx: Write to I/O port B", constVal<1>, effectVal}},
|
||||||
{0x12, {DIV_CMD_STD_NOISE_MODE, "12xx: Set duty cycle (0 to 8)",
|
{0x12, {DIV_CMD_STD_NOISE_MODE, "12xx: Set duty cycle (0 to 8)",
|
||||||
[](unsigned char, unsigned char val) -> int { return 0x10+(val&15); }}},
|
[](unsigned char, unsigned char val) -> int { return 0x10+(val&15); }}},
|
||||||
{0x27, {DIV_CMD_AY_NOISE_MASK_AND, "27xx: Set noise AND mask"}},
|
{0x27, {DIV_CMD_AY_NOISE_MASK_AND, "27xx: Set noise AND mask"}},
|
||||||
{0x28, {DIV_CMD_AY_NOISE_MASK_OR, "28xx: Set noise OR mask"}},
|
{0x28, {DIV_CMD_AY_NOISE_MASK_OR, "28xx: Set noise OR mask"}},
|
||||||
|
{0x2c, {DIV_CMD_AY_AUTO_PWM, "2Cxy: Automatic noise frequency (x: mode (0: disable, 1: freq, 2: freq + OR mask); y: offset"}},
|
||||||
{0x2d, {DIV_CMD_AY_IO_WRITE, "2Dxx: NOT TO BE EMPLOYED BY THE COMPOSER", constVal<255>, effectVal}},
|
{0x2d, {DIV_CMD_AY_IO_WRITE, "2Dxx: NOT TO BE EMPLOYED BY THE COMPOSER", constVal<255>, effectVal}},
|
||||||
});
|
};
|
||||||
|
|
||||||
EffectHandlerMap fmEffectHandlerMap={
|
EffectHandlerMap fmEffectHandlerMap={
|
||||||
{0x30, {DIV_CMD_FM_HARD_RESET, "30xx: Toggle hard envelope reset on new notes"}},
|
{0x30, {DIV_CMD_FM_HARD_RESET, "30xx: Toggle hard envelope reset on new notes"}},
|
||||||
|
|
|
@ -45,8 +45,12 @@ 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;
|
if (exportFormat==DIV_EXPORT_FORMAT_S16) {
|
||||||
|
si.format=SF_FORMAT_WAV|SF_FORMAT_PCM_16;
|
||||||
|
} else {
|
||||||
|
si.format=SF_FORMAT_WAV|SF_FORMAT_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
sf=sfWrap.doOpen(exportPath.c_str(),SFM_WRITE,&si);
|
sf=sfWrap.doOpen(exportPath.c_str(),SFM_WRITE,&si);
|
||||||
if (sf==NULL) {
|
if (sf==NULL) {
|
||||||
|
@ -55,10 +59,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 +74,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 +103,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!");
|
||||||
|
@ -237,22 +247,29 @@ void DivEngine::runExportThread() {
|
||||||
// take control of audio output
|
// take control of audio output
|
||||||
deinitAudioBackend();
|
deinitAudioBackend();
|
||||||
|
|
||||||
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];
|
||||||
|
|
||||||
logI("rendering to files...");
|
logI("rendering to files...");
|
||||||
|
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
|
if (!exportChannelMask[i]) continue;
|
||||||
SNDFILE* sf;
|
SNDFILE* sf;
|
||||||
SF_INFO si;
|
SF_INFO si;
|
||||||
SFWrapper sfWrap;
|
SFWrapper sfWrap;
|
||||||
String fname=fmt::sprintf("%s_c%02d.wav",exportPath,i+1);
|
String fname=fmt::sprintf("%s_c%02d.wav",exportPath,i+1);
|
||||||
logI("- %s",fname.c_str());
|
logI("- %s",fname.c_str());
|
||||||
si.samplerate=got.rate;
|
si.samplerate=got.rate;
|
||||||
si.channels=2;
|
si.channels=exportOutputs;
|
||||||
si.format=SF_FORMAT_WAV|SF_FORMAT_PCM_16;
|
if (exportFormat==DIV_EXPORT_FORMAT_S16) {
|
||||||
|
si.format=SF_FORMAT_WAV|SF_FORMAT_PCM_16;
|
||||||
|
} else {
|
||||||
|
si.format=SF_FORMAT_WAV|SF_FORMAT_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
sf=sfWrap.doOpen(fname.c_str(),SFM_WRITE,&si);
|
sf=sfWrap.doOpen(fname.c_str(),SFM_WRITE,&si);
|
||||||
if (sf==NULL) {
|
if (sf==NULL) {
|
||||||
|
@ -287,24 +304,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 j=0; j<(int)totalProcessed; j++) {
|
for (int j=0; j<(int)totalProcessed; j++) {
|
||||||
total++;
|
total++;
|
||||||
if (isFadingOut) {
|
if (isFadingOut) {
|
||||||
double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples));
|
double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples));
|
||||||
outBuf[2][j<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][j]))*mul;
|
for (int k=0; k<exportOutputs; k++) {
|
||||||
outBuf[2][1+(j<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][j]))*mul;
|
outBufFinal[fi++]=MAX(-1.0f,MIN(1.0f,outBuf[k][j]))*mul;
|
||||||
|
}
|
||||||
if (++curFadeOutSample>=fadeOutSamples) {
|
if (++curFadeOutSample>=fadeOutSamples) {
|
||||||
playing=false;
|
playing=false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outBuf[2][j<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][j]));
|
for (int k=0; k<exportOutputs; k++) {
|
||||||
outBuf[2][1+(j<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][j]));
|
outBufFinal[fi++]=MAX(-1.0f,MIN(1.0f,outBuf[k][j]));
|
||||||
|
}
|
||||||
if (lastLoopPos>-1 && j>=lastLoopPos && totalLoops>=exportLoopCount) {
|
if (lastLoopPos>-1 && j>=lastLoopPos && totalLoops>=exportLoopCount) {
|
||||||
logD("start fading out...");
|
logD("start fading out...");
|
||||||
isFadingOut=true;
|
isFadingOut=true;
|
||||||
|
@ -312,7 +332,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -335,9 +355,10 @@ void DivEngine::runExportThread() {
|
||||||
if (stopExport) break;
|
if (stopExport) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] outBuf[0];
|
delete[] outBufFinal;
|
||||||
delete[] outBuf[1];
|
for (int i=0; i<exportOutputs; i++) {
|
||||||
delete[] outBuf[2];
|
delete[] outBuf[i];
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
isMuted[i]=false;
|
isMuted[i]=false;
|
||||||
|
@ -369,18 +390,19 @@ 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;
|
exportFormat=options.format;
|
||||||
|
exportFadeOut=options.fadeOut;
|
||||||
|
memcpy(exportChannelMask,options.channelMask,DIV_MAX_CHANS*sizeof(bool));
|
||||||
if (exportMode!=DIV_EXPORT_MODE_ONE) {
|
if (exportMode!=DIV_EXPORT_MODE_ONE) {
|
||||||
// remove extension
|
// remove extension
|
||||||
String lowerCase=exportPath;
|
String lowerCase=exportPath;
|
||||||
|
@ -398,6 +420,7 @@ bool DivEngine::saveAudio(const char* path, int loops, DivAudioExportModes mode,
|
||||||
repeatPattern=false;
|
repeatPattern=false;
|
||||||
setOrder(0);
|
setOrder(0);
|
||||||
remainingLoops=-1;
|
remainingLoops=-1;
|
||||||
|
got.rate=options.sampleRate;
|
||||||
|
|
||||||
if (shallSwitchCores()) {
|
if (shallSwitchCores()) {
|
||||||
bool isMutedBefore[DIV_MAX_CHANS];
|
bool isMutedBefore[DIV_MAX_CHANS];
|
||||||
|
@ -412,7 +435,11 @@ bool DivEngine::saveAudio(const char* path, int loops, DivAudioExportModes mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exportLoopCount=loops;
|
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
|
||||||
|
|
|
@ -196,6 +196,10 @@ void FurnaceGUI::drawCompatFlags() {
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip("behavior changed in 0.6.1\nthis flag will be removed if I find out that none of the songs break after disabling it.");
|
ImGui::SetTooltip("behavior changed in 0.6.1\nthis flag will be removed if I find out that none of the songs break after disabling it.");
|
||||||
}
|
}
|
||||||
|
ImGui::Checkbox("Old sample offset effect",&e->song.oldSampleOffset);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("behavior changed in 0.6.3");
|
||||||
|
}
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
}
|
}
|
||||||
if (ImGui::BeginTabItem(".mod import")) {
|
if (ImGui::BeginTabItem(".mod import")) {
|
||||||
|
|
|
@ -555,6 +555,18 @@ void FurnaceGUI::doAction(int what) {
|
||||||
case GUI_ACTION_PAT_SELECTION_DOWN_COARSE:
|
case GUI_ACTION_PAT_SELECTION_DOWN_COARSE:
|
||||||
moveCursor(0,editStepCoarse,true);
|
moveCursor(0,editStepCoarse,true);
|
||||||
break;
|
break;
|
||||||
|
case GUI_ACTION_PAT_MOVE_UP:
|
||||||
|
moveSelected(0,-1);
|
||||||
|
break;
|
||||||
|
case GUI_ACTION_PAT_MOVE_DOWN:
|
||||||
|
moveSelected(0,1);
|
||||||
|
break;
|
||||||
|
case GUI_ACTION_PAT_MOVE_LEFT_CHANNEL:
|
||||||
|
moveSelected(-1,0);
|
||||||
|
break;
|
||||||
|
case GUI_ACTION_PAT_MOVE_RIGHT_CHANNEL:
|
||||||
|
moveSelected(1,0);
|
||||||
|
break;
|
||||||
case GUI_ACTION_PAT_DELETE:
|
case GUI_ACTION_PAT_DELETE:
|
||||||
doDelete();
|
doDelete();
|
||||||
if (settings.stepOnDelete) {
|
if (settings.stepOnDelete) {
|
||||||
|
|
|
@ -1842,6 +1842,25 @@ void FurnaceGUI::doDrag() {
|
||||||
makeUndo(GUI_UNDO_PATTERN_DRAG);
|
makeUndo(GUI_UNDO_PATTERN_DRAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FurnaceGUI::moveSelected(int x, int y) {
|
||||||
|
prepareUndo(GUI_UNDO_PATTERN_DRAG);
|
||||||
|
|
||||||
|
// copy and clear
|
||||||
|
String c=doCopy(true,false,selStart,selEnd);
|
||||||
|
|
||||||
|
logV("copy: %s",c);
|
||||||
|
|
||||||
|
// replace
|
||||||
|
selStart.xCoarse+=x;
|
||||||
|
selEnd.xCoarse+=x;
|
||||||
|
selStart.y+=y;
|
||||||
|
selEnd.y+=y;
|
||||||
|
cursor=selStart;
|
||||||
|
doPaste(GUI_PASTE_MODE_NORMAL,0,false,c);
|
||||||
|
|
||||||
|
makeUndo(GUI_UNDO_PATTERN_DRAG);
|
||||||
|
}
|
||||||
|
|
||||||
void FurnaceGUI::doUndo() {
|
void FurnaceGUI::doUndo() {
|
||||||
if (undoHist.empty()) return;
|
if (undoHist.empty()) return;
|
||||||
UndoStep& us=undoHist.back();
|
UndoStep& us=undoHist.back();
|
||||||
|
|
|
@ -26,14 +26,83 @@
|
||||||
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 (audioExportOptions.mode!=DIV_EXPORT_MODE_MANY_SYS) {
|
||||||
|
ImGui::Text("Bit depth:");
|
||||||
|
ImGui::Indent();
|
||||||
|
if (ImGui::RadioButton("16-bit integer",audioExportOptions.format==DIV_EXPORT_FORMAT_S16)) {
|
||||||
|
audioExportOptions.format=DIV_EXPORT_FORMAT_S16;
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("32-bit float",audioExportOptions.format==DIV_EXPORT_FORMAT_F32)) {
|
||||||
|
audioExportOptions.format=DIV_EXPORT_FORMAT_F32;
|
||||||
|
}
|
||||||
|
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 (audioExportOptions.mode!=DIV_EXPORT_MODE_MANY_SYS) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOneOn=false;
|
||||||
|
if (audioExportOptions.mode==DIV_EXPORT_MODE_MANY_CHAN) {
|
||||||
|
ImGui::Text("Channels to export:");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::SmallButton("All")) {
|
||||||
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
|
audioExportOptions.channelMask[i]=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::SmallButton("None")) {
|
||||||
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
|
audioExportOptions.channelMask[i]=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::SmallButton("Invert")) {
|
||||||
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
|
audioExportOptions.channelMask[i]=!audioExportOptions.channelMask[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginChild("Channel Selection",ImVec2(0,200.0f*dpiScale))) {
|
||||||
|
for (int i=0; i<e->getTotalChannelCount(); i++) {
|
||||||
|
String name=fmt::sprintf("%d. %s##_CE%d",i+1,e->getChannelName(i),i);
|
||||||
|
ImGui::Checkbox(name.c_str(),&audioExportOptions.channelMask[i]);
|
||||||
|
if (audioExportOptions.channelMask[i]) isOneOn=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
} else {
|
||||||
|
isOneOn=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onWindow) {
|
if (onWindow) {
|
||||||
|
@ -42,19 +111,23 @@ void FurnaceGUI::drawExportAudio(bool onWindow) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
|
if (isOneOn) {
|
||||||
switch (audioExportType) {
|
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
|
||||||
case 0:
|
switch (audioExportOptions.mode) {
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
|
case DIV_EXPORT_MODE_ONE:
|
||||||
break;
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
|
||||||
case 1:
|
break;
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
|
case DIV_EXPORT_MODE_MANY_SYS:
|
||||||
break;
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
|
||||||
case 2:
|
break;
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
|
case DIV_EXPORT_MODE_MANY_CHAN:
|
||||||
break;
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
} else {
|
||||||
|
ImGui::Text("select at least one channel");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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++) {
|
||||||
|
@ -6982,12 +6982,19 @@ bool FurnaceGUI::init() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rend->preInit();
|
rend->preInit(e->getConfObject());
|
||||||
|
|
||||||
logD("creating window...");
|
logD("creating window...");
|
||||||
sdlWin=SDL_CreateWindow("Furnace",scrX,scrY,scrW,scrH,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI|(scrMax?SDL_WINDOW_MAXIMIZED:0)|(fullScreen?SDL_WINDOW_FULLSCREEN_DESKTOP:0)|rend->getWindowFlags());
|
sdlWin=SDL_CreateWindow("Furnace",scrX,scrY,scrW,scrH,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI|(scrMax?SDL_WINDOW_MAXIMIZED:0)|(fullScreen?SDL_WINDOW_FULLSCREEN_DESKTOP:0)|rend->getWindowFlags());
|
||||||
if (sdlWin==NULL) {
|
if (sdlWin==NULL) {
|
||||||
lastError=fmt::sprintf("could not open window! %s",SDL_GetError());
|
const char* sdlErr=SDL_GetError();
|
||||||
|
lastError=fmt::sprintf("could not open window! %s",sdlErr);
|
||||||
|
if (settings.renderBackend!="Software" && strcmp(sdlErr,"No matching GL pixel format available")==0) {
|
||||||
|
settings.renderBackend="Software";
|
||||||
|
e->setConf("renderBackend","Software");
|
||||||
|
e->saveConf();
|
||||||
|
lastError+="\r\nfalling back to software renderer. please restart Furnace.";
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7313,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
|
||||||
|
@ -7574,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),
|
||||||
|
@ -7597,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),
|
||||||
|
@ -7948,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
|
||||||
|
|
|
@ -778,6 +778,10 @@ enum FurnaceGUIActions {
|
||||||
GUI_ACTION_PAT_SELECTION_END,
|
GUI_ACTION_PAT_SELECTION_END,
|
||||||
GUI_ACTION_PAT_SELECTION_UP_COARSE,
|
GUI_ACTION_PAT_SELECTION_UP_COARSE,
|
||||||
GUI_ACTION_PAT_SELECTION_DOWN_COARSE,
|
GUI_ACTION_PAT_SELECTION_DOWN_COARSE,
|
||||||
|
GUI_ACTION_PAT_MOVE_UP,
|
||||||
|
GUI_ACTION_PAT_MOVE_DOWN,
|
||||||
|
GUI_ACTION_PAT_MOVE_LEFT_CHANNEL,
|
||||||
|
GUI_ACTION_PAT_MOVE_RIGHT_CHANNEL,
|
||||||
GUI_ACTION_PAT_DELETE,
|
GUI_ACTION_PAT_DELETE,
|
||||||
GUI_ACTION_PAT_PULL_DELETE,
|
GUI_ACTION_PAT_PULL_DELETE,
|
||||||
GUI_ACTION_PAT_INSERT,
|
GUI_ACTION_PAT_INSERT,
|
||||||
|
@ -1505,7 +1509,7 @@ class FurnaceGUIRender {
|
||||||
virtual const char* getDeviceName();
|
virtual const char* getDeviceName();
|
||||||
virtual const char* getAPIVersion();
|
virtual const char* getAPIVersion();
|
||||||
virtual void setSwapInterval(int swapInterval);
|
virtual void setSwapInterval(int swapInterval);
|
||||||
virtual void preInit();
|
virtual void preInit(const DivConfig& conf);
|
||||||
virtual bool init(SDL_Window* win, int swapInterval);
|
virtual bool init(SDL_Window* win, int swapInterval);
|
||||||
virtual void initGUI(SDL_Window* win);
|
virtual void initGUI(SDL_Window* win);
|
||||||
virtual void quitGUI();
|
virtual void quitGUI();
|
||||||
|
@ -1892,6 +1896,12 @@ class FurnaceGUI {
|
||||||
int frameRateLimit;
|
int frameRateLimit;
|
||||||
int displayRenderTime;
|
int displayRenderTime;
|
||||||
int inputRepeat;
|
int inputRepeat;
|
||||||
|
int glRedSize;
|
||||||
|
int glGreenSize;
|
||||||
|
int glBlueSize;
|
||||||
|
int glAlphaSize;
|
||||||
|
int glDepthSize;
|
||||||
|
int glDoubleBuffer;
|
||||||
unsigned int maxUndoSteps;
|
unsigned int maxUndoSteps;
|
||||||
float vibrationStrength;
|
float vibrationStrength;
|
||||||
int vibrationLength;
|
int vibrationLength;
|
||||||
|
@ -2135,6 +2145,12 @@ class FurnaceGUI {
|
||||||
frameRateLimit(60),
|
frameRateLimit(60),
|
||||||
displayRenderTime(0),
|
displayRenderTime(0),
|
||||||
inputRepeat(0),
|
inputRepeat(0),
|
||||||
|
glRedSize(8),
|
||||||
|
glGreenSize(8),
|
||||||
|
glBlueSize(8),
|
||||||
|
glAlphaSize(0),
|
||||||
|
glDepthSize(24),
|
||||||
|
glDoubleBuffer(1),
|
||||||
maxUndoSteps(100),
|
maxUndoSteps(100),
|
||||||
vibrationStrength(0.5f),
|
vibrationStrength(0.5f),
|
||||||
vibrationLength(20),
|
vibrationLength(20),
|
||||||
|
@ -2178,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;
|
||||||
|
|
||||||
|
@ -2587,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;
|
||||||
|
|
||||||
|
@ -2665,6 +2679,7 @@ class FurnaceGUI {
|
||||||
void drawMacros(std::vector<FurnaceGUIMacroDesc>& macros, FurnaceGUIMacroEditState& state);
|
void drawMacros(std::vector<FurnaceGUIMacroDesc>& macros, FurnaceGUIMacroEditState& state);
|
||||||
void alterSampleMap(int column, int val);
|
void alterSampleMap(int column, int val);
|
||||||
|
|
||||||
|
void insTabFM(DivInstrument* ins);
|
||||||
void insTabSample(DivInstrument* ins);
|
void insTabSample(DivInstrument* ins);
|
||||||
|
|
||||||
void drawOrderButtons();
|
void drawOrderButtons();
|
||||||
|
@ -2782,6 +2797,7 @@ class FurnaceGUI {
|
||||||
void doDelete();
|
void doDelete();
|
||||||
void doPullDelete();
|
void doPullDelete();
|
||||||
void doInsert();
|
void doInsert();
|
||||||
|
void moveSelected(int x, int y);
|
||||||
void doTranspose(int amount, OperationMask& mask);
|
void doTranspose(int amount, OperationMask& mask);
|
||||||
String doCopy(bool cut, bool writeClipboard, const SelectionPoint& sStart, const SelectionPoint& sEnd);
|
String doCopy(bool cut, bool writeClipboard, const SelectionPoint& sStart, const SelectionPoint& sEnd);
|
||||||
void doPasteFurnace(PasteMode mode, int arg, bool readClipboard, String clipb, std::vector<String> data, int startOff, bool invalidData, UndoRegion ur);
|
void doPasteFurnace(PasteMode mode, int arg, bool readClipboard, String clipb, std::vector<String> data, int startOff, bool invalidData, UndoRegion ur);
|
||||||
|
|
|
@ -659,6 +659,10 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={
|
||||||
D("PAT_SELECTION_END", "Expand selection to end of pattern", 0),
|
D("PAT_SELECTION_END", "Expand selection to end of pattern", 0),
|
||||||
D("PAT_SELECTION_UP_COARSE", "Expand selection upwards (coarse)", FURKMOD_SHIFT|SDLK_PAGEUP),
|
D("PAT_SELECTION_UP_COARSE", "Expand selection upwards (coarse)", FURKMOD_SHIFT|SDLK_PAGEUP),
|
||||||
D("PAT_SELECTION_DOWN_COARSE", "Expand selection downwards (coarse)", FURKMOD_SHIFT|SDLK_PAGEDOWN),
|
D("PAT_SELECTION_DOWN_COARSE", "Expand selection downwards (coarse)", FURKMOD_SHIFT|SDLK_PAGEDOWN),
|
||||||
|
D("PAT_MOVE_UP", "Move selection up", FURKMOD_ALT|SDLK_UP),
|
||||||
|
D("PAT_MOVE_DOWN", "Move selection down", FURKMOD_ALT|SDLK_DOWN),
|
||||||
|
D("PAT_MOVE_LEFT_CHANNEL", "Move selection to previous channel", FURKMOD_ALT|SDLK_LEFT),
|
||||||
|
D("PAT_MOVE_RIGHT_CHANNEL", "Move selection to next channel", FURKMOD_ALT|SDLK_RIGHT),
|
||||||
D("PAT_DELETE", "Delete", SDLK_DELETE),
|
D("PAT_DELETE", "Delete", SDLK_DELETE),
|
||||||
D("PAT_PULL_DELETE", "Pull delete", SDLK_BACKSPACE),
|
D("PAT_PULL_DELETE", "Pull delete", SDLK_BACKSPACE),
|
||||||
D("PAT_INSERT", "Insert", SDLK_INSERT),
|
D("PAT_INSERT", "Insert", SDLK_INSERT),
|
||||||
|
|
5449
src/gui/insEdit.cpp
5449
src/gui/insEdit.cpp
File diff suppressed because it is too large
Load diff
|
@ -128,7 +128,7 @@ const char* FurnaceGUIRender::getAPIVersion() {
|
||||||
void FurnaceGUIRender::setSwapInterval(int swapInterval) {
|
void FurnaceGUIRender::setSwapInterval(int swapInterval) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUIRender::preInit() {
|
void FurnaceGUIRender::preInit(const DivConfig& conf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FurnaceGUIRender::init(SDL_Window* win, int swapInterval) {
|
bool FurnaceGUIRender::init(SDL_Window* win, int swapInterval) {
|
||||||
|
|
|
@ -397,7 +397,7 @@ void FurnaceGUIRenderDX11::setSwapInterval(int swapInt) {
|
||||||
swapInterval=swapInt;
|
swapInterval=swapInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUIRenderDX11::preInit() {
|
void FurnaceGUIRenderDX11::preInit(const DivConfig& conf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const float wipeVertices[4][4]={
|
const float wipeVertices[4][4]={
|
||||||
|
|
|
@ -89,7 +89,7 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender {
|
||||||
const char* getDeviceName();
|
const char* getDeviceName();
|
||||||
const char* getAPIVersion();
|
const char* getAPIVersion();
|
||||||
void setSwapInterval(int swapInterval);
|
void setSwapInterval(int swapInterval);
|
||||||
void preInit();
|
void preInit(const DivConfig& conf);
|
||||||
bool init(SDL_Window* win, int swapInterval);
|
bool init(SDL_Window* win, int swapInterval);
|
||||||
void initGUI(SDL_Window* win);
|
void initGUI(SDL_Window* win);
|
||||||
void quitGUI();
|
void quitGUI();
|
||||||
|
|
|
@ -580,7 +580,7 @@ void FurnaceGUIRenderGL::setSwapInterval(int swapInterval) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUIRenderGL::preInit() {
|
void FurnaceGUIRenderGL::preInit(const DivConfig& conf) {
|
||||||
#if defined(USE_GLES)
|
#if defined(USE_GLES)
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS,0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS,0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_ES);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_ES);
|
||||||
|
@ -603,12 +603,12 @@ void FurnaceGUIRenderGL::preInit() {
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8);
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE,conf.getInt("glRedSize",8));
|
||||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,conf.getInt("glGreenSize",8));
|
||||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8);
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,conf.getInt("glBlueSize",8));
|
||||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,0);
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,conf.getInt("glAlphaSize",0));
|
||||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,conf.getInt("glDoubleBuffer",1));
|
||||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,24);
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,conf.getInt("glDepthSize",24));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOAD_PROC_MANDATORY(_v,_t,_s) \
|
#define LOAD_PROC_MANDATORY(_v,_t,_s) \
|
||||||
|
|
|
@ -82,7 +82,7 @@ class FurnaceGUIRenderGL: public FurnaceGUIRender {
|
||||||
const char* getDeviceName();
|
const char* getDeviceName();
|
||||||
const char* getAPIVersion();
|
const char* getAPIVersion();
|
||||||
void setSwapInterval(int swapInterval);
|
void setSwapInterval(int swapInterval);
|
||||||
void preInit();
|
void preInit(const DivConfig& conf);
|
||||||
bool init(SDL_Window* win, int swapInterval);
|
bool init(SDL_Window* win, int swapInterval);
|
||||||
void initGUI(SDL_Window* win);
|
void initGUI(SDL_Window* win);
|
||||||
void quitGUI();
|
void quitGUI();
|
||||||
|
|
|
@ -245,18 +245,18 @@ void FurnaceGUIRenderGL1::setSwapInterval(int swapInterval) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUIRenderGL1::preInit() {
|
void FurnaceGUIRenderGL1::preInit(const DivConfig& conf) {
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS,0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS,0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,1);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,1);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,1);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,1);
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8);
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE,conf.getInt("glRedSize",8));
|
||||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,conf.getInt("glGreenSize",8));
|
||||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8);
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,conf.getInt("glBlueSize",8));
|
||||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,0);
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,conf.getInt("glAlphaSize",0));
|
||||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,conf.getInt("glDoubleBuffer",1));
|
||||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,24);
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,conf.getInt("glDepthSize",24));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOAD_PROC_MANDATORY(_v,_t,_s) \
|
#define LOAD_PROC_MANDATORY(_v,_t,_s) \
|
||||||
|
@ -334,4 +334,4 @@ void FurnaceGUIRenderGL1::quitGUI() {
|
||||||
// sadly, OpenGL 1.1 doesn't have the ability to recover from death...
|
// sadly, OpenGL 1.1 doesn't have the ability to recover from death...
|
||||||
bool FurnaceGUIRenderGL1::isDead() {
|
bool FurnaceGUIRenderGL1::isDead() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ class FurnaceGUIRenderGL1: public FurnaceGUIRender {
|
||||||
const char* getDeviceName();
|
const char* getDeviceName();
|
||||||
const char* getAPIVersion();
|
const char* getAPIVersion();
|
||||||
void setSwapInterval(int swapInterval);
|
void setSwapInterval(int swapInterval);
|
||||||
void preInit();
|
void preInit(const DivConfig& conf);
|
||||||
bool init(SDL_Window* win, int swapInterval);
|
bool init(SDL_Window* win, int swapInterval);
|
||||||
void initGUI(SDL_Window* win);
|
void initGUI(SDL_Window* win);
|
||||||
void quitGUI();
|
void quitGUI();
|
||||||
|
|
|
@ -52,7 +52,7 @@ class FurnaceGUIRenderMetal: public FurnaceGUIRender {
|
||||||
const char* getDeviceName();
|
const char* getDeviceName();
|
||||||
const char* getAPIVersion();
|
const char* getAPIVersion();
|
||||||
void setSwapInterval(int swapInterval);
|
void setSwapInterval(int swapInterval);
|
||||||
void preInit();
|
void preInit(const DivConfig& conf);
|
||||||
bool init(SDL_Window* win, int swapInterval);
|
bool init(SDL_Window* win, int swapInterval);
|
||||||
void initGUI(SDL_Window* win);
|
void initGUI(SDL_Window* win);
|
||||||
void quitGUI();
|
void quitGUI();
|
||||||
|
|
|
@ -218,7 +218,7 @@ void FurnaceGUIRenderMetal::setSwapInterval(int swapInterval) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUIRenderMetal::preInit() {
|
void FurnaceGUIRenderMetal::preInit(const DivConfig& conf) {
|
||||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER,"metal");
|
SDL_SetHint(SDL_HINT_RENDER_DRIVER,"metal");
|
||||||
priv=new FurnaceGUIRenderMetalPrivate;
|
priv=new FurnaceGUIRenderMetalPrivate;
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,7 @@ void FurnaceGUIRenderSDL::setSwapInterval(int swapInterval) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUIRenderSDL::preInit() {
|
void FurnaceGUIRenderSDL::preInit(const DivConfig& conf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FurnaceGUIRenderSDL::init(SDL_Window* win, int swapInterval) {
|
bool FurnaceGUIRenderSDL::init(SDL_Window* win, int swapInterval) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ class FurnaceGUIRenderSDL: public FurnaceGUIRender {
|
||||||
const char* getDeviceName();
|
const char* getDeviceName();
|
||||||
const char* getAPIVersion();
|
const char* getAPIVersion();
|
||||||
void setSwapInterval(int swapInterval);
|
void setSwapInterval(int swapInterval);
|
||||||
void preInit();
|
void preInit(const DivConfig& conf);
|
||||||
bool init(SDL_Window* win, int swapInterval);
|
bool init(SDL_Window* win, int swapInterval);
|
||||||
void initGUI(SDL_Window* win);
|
void initGUI(SDL_Window* win);
|
||||||
void quitGUI();
|
void quitGUI();
|
||||||
|
|
|
@ -160,7 +160,7 @@ const char* FurnaceGUIRenderSoftware::getAPIVersion() {
|
||||||
void FurnaceGUIRenderSoftware::setSwapInterval(int swapInterval) {
|
void FurnaceGUIRenderSoftware::setSwapInterval(int swapInterval) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUIRenderSoftware::preInit() {
|
void FurnaceGUIRenderSoftware::preInit(const DivConfig& conf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FurnaceGUIRenderSoftware::init(SDL_Window* win, int swapInterval) {
|
bool FurnaceGUIRenderSoftware::init(SDL_Window* win, int swapInterval) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ class FurnaceGUIRenderSoftware: public FurnaceGUIRender {
|
||||||
const char* getDeviceName();
|
const char* getDeviceName();
|
||||||
const char* getAPIVersion();
|
const char* getAPIVersion();
|
||||||
void setSwapInterval(int swapInterval);
|
void setSwapInterval(int swapInterval);
|
||||||
void preInit();
|
void preInit(const DivConfig& conf);
|
||||||
bool init(SDL_Window* win, int swapInterval);
|
bool init(SDL_Window* win, int swapInterval);
|
||||||
void initGUI(SDL_Window* win);
|
void initGUI(SDL_Window* win);
|
||||||
void quitGUI();
|
void quitGUI();
|
||||||
|
|
|
@ -449,23 +449,61 @@ void FurnaceGUI::drawSettings() {
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip("you may need to restart Furnace for this setting to take effect.");
|
ImGui::SetTooltip("you may need to restart Furnace for this setting to take effect.");
|
||||||
}
|
}
|
||||||
if (curRenderBackend=="SDL") {
|
|
||||||
if (ImGui::BeginCombo("Render driver",settings.renderDriver.empty()?"Automatic":settings.renderDriver.c_str())) {
|
if (ImGui::TreeNode("Advanced render backend settings")) {
|
||||||
if (ImGui::Selectable("Automatic",settings.renderDriver.empty())) {
|
if (curRenderBackend=="SDL") {
|
||||||
settings.renderDriver="";
|
if (ImGui::BeginCombo("Render driver",settings.renderDriver.empty()?"Automatic":settings.renderDriver.c_str())) {
|
||||||
settingsChanged=true;
|
if (ImGui::Selectable("Automatic",settings.renderDriver.empty())) {
|
||||||
}
|
settings.renderDriver="";
|
||||||
for (String& i: availRenderDrivers) {
|
|
||||||
if (ImGui::Selectable(i.c_str(),i==settings.renderDriver)) {
|
|
||||||
settings.renderDriver=i;
|
|
||||||
settingsChanged=true;
|
settingsChanged=true;
|
||||||
}
|
}
|
||||||
|
for (String& i: availRenderDrivers) {
|
||||||
|
if (ImGui::Selectable(i.c_str(),i==settings.renderDriver)) {
|
||||||
|
settings.renderDriver=i;
|
||||||
|
settingsChanged=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
ImGui::EndCombo();
|
if (ImGui::IsItemHovered()) {
|
||||||
}
|
ImGui::SetTooltip("you may need to restart Furnace for this setting to take effect.");
|
||||||
if (ImGui::IsItemHovered()) {
|
}
|
||||||
ImGui::SetTooltip("you may need to restart Furnace for this setting to take effect.");
|
} else if (curRenderBackend.find("OpenGL")==0) {
|
||||||
|
ImGui::TextWrapped("beware: changing these settings may render Furnace unusable! do so at your own risk.\nstart Furnace with -safemode if you mess something up.");
|
||||||
|
if (ImGui::InputInt("Red bits",&settings.glRedSize)) {
|
||||||
|
if (settings.glRedSize<0) settings.glRedSize=0;
|
||||||
|
if (settings.glRedSize>32) settings.glRedSize=32;
|
||||||
|
settingsChanged=true;
|
||||||
|
}
|
||||||
|
if (ImGui::InputInt("Green bits",&settings.glGreenSize)) {
|
||||||
|
if (settings.glGreenSize<0) settings.glGreenSize=0;
|
||||||
|
if (settings.glGreenSize>32) settings.glGreenSize=32;
|
||||||
|
settingsChanged=true;
|
||||||
|
}
|
||||||
|
if (ImGui::InputInt("Blue bits",&settings.glBlueSize)) {
|
||||||
|
if (settings.glBlueSize<0) settings.glBlueSize=0;
|
||||||
|
if (settings.glBlueSize>32) settings.glBlueSize=32;
|
||||||
|
settingsChanged=true;
|
||||||
|
}
|
||||||
|
if (ImGui::InputInt("Alpha bits",&settings.glAlphaSize)) {
|
||||||
|
if (settings.glAlphaSize<0) settings.glAlphaSize=0;
|
||||||
|
if (settings.glAlphaSize>32) settings.glAlphaSize=32;
|
||||||
|
settingsChanged=true;
|
||||||
|
}
|
||||||
|
if (ImGui::InputInt("Color depth",&settings.glDepthSize)) {
|
||||||
|
if (settings.glDepthSize<0) settings.glDepthSize=0;
|
||||||
|
if (settings.glDepthSize>128) settings.glDepthSize=128;
|
||||||
|
settingsChanged=true;
|
||||||
|
}
|
||||||
|
bool glDoubleBufferB=settings.glDoubleBuffer;
|
||||||
|
if (ImGui::Checkbox("Double buffer",&glDoubleBufferB)) {
|
||||||
|
settings.glDoubleBuffer=glDoubleBufferB;
|
||||||
|
settingsChanged=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextWrapped("the following values are common (in red, green, blue, alpha order):\n- 24 bits: 8, 8, 8, 0\n- 16 bits: 5, 6, 5, 0\n- 32 bits (with alpha): 8, 8, 8, 8\n- 30 bits (deep): 10, 10, 10, 0");
|
||||||
}
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TextWrapped("current backend: %s\n%s\n%s\n%s",rend->getBackendName(),rend->getVendorName(),rend->getDeviceName(),rend->getAPIVersion());
|
ImGui::TextWrapped("current backend: %s\n%s\n%s\n%s",rend->getBackendName(),rend->getVendorName(),rend->getDeviceName(),rend->getAPIVersion());
|
||||||
|
@ -667,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();
|
||||||
|
@ -2106,6 +2144,10 @@ void FurnaceGUI::drawSettings() {
|
||||||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_SELECTION_END);
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_SELECTION_END);
|
||||||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_SELECTION_UP_COARSE);
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_SELECTION_UP_COARSE);
|
||||||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_SELECTION_DOWN_COARSE);
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_SELECTION_DOWN_COARSE);
|
||||||
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_MOVE_UP);
|
||||||
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_MOVE_DOWN);
|
||||||
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_MOVE_LEFT_CHANNEL);
|
||||||
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_MOVE_RIGHT_CHANNEL);
|
||||||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_DELETE);
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_DELETE);
|
||||||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_PULL_DELETE);
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_PULL_DELETE);
|
||||||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_INSERT);
|
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_INSERT);
|
||||||
|
@ -4119,6 +4161,13 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
settings.renderBackend=conf.getString("renderBackend",GUI_BACKEND_DEFAULT_NAME);
|
settings.renderBackend=conf.getString("renderBackend",GUI_BACKEND_DEFAULT_NAME);
|
||||||
settings.renderClearPos=conf.getInt("renderClearPos",0);
|
settings.renderClearPos=conf.getInt("renderClearPos",0);
|
||||||
|
|
||||||
|
settings.glRedSize=conf.getInt("glRedSize",8);
|
||||||
|
settings.glGreenSize=conf.getInt("glGreenSize",8);
|
||||||
|
settings.glBlueSize=conf.getInt("glBlueSize",8);
|
||||||
|
settings.glAlphaSize=conf.getInt("glAlphaSize",0);
|
||||||
|
settings.glDepthSize=conf.getInt("glDepthSize",24);
|
||||||
|
settings.glDoubleBuffer=conf.getInt("glDoubleBuffer",1);
|
||||||
|
|
||||||
settings.vsync=conf.getInt("vsync",1);
|
settings.vsync=conf.getInt("vsync",1);
|
||||||
settings.frameRateLimit=conf.getInt("frameRateLimit",100);
|
settings.frameRateLimit=conf.getInt("frameRateLimit",100);
|
||||||
settings.displayRenderTime=conf.getInt("displayRenderTime",0);
|
settings.displayRenderTime=conf.getInt("displayRenderTime",0);
|
||||||
|
@ -4653,6 +4702,12 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
clampSetting(settings.vibrationStrength,0.0f,1.0f);
|
clampSetting(settings.vibrationStrength,0.0f,1.0f);
|
||||||
clampSetting(settings.vibrationLength,10,500);
|
clampSetting(settings.vibrationLength,10,500);
|
||||||
clampSetting(settings.inputRepeat,0,1);
|
clampSetting(settings.inputRepeat,0,1);
|
||||||
|
clampSetting(settings.glRedSize,0,32);
|
||||||
|
clampSetting(settings.glGreenSize,0,32);
|
||||||
|
clampSetting(settings.glBlueSize,0,32);
|
||||||
|
clampSetting(settings.glAlphaSize,0,32);
|
||||||
|
clampSetting(settings.glDepthSize,0,128);
|
||||||
|
clampSetting(settings.glDoubleBuffer,0,1);
|
||||||
|
|
||||||
if (settings.exportLoops<0.0) settings.exportLoops=0.0;
|
if (settings.exportLoops<0.0) settings.exportLoops=0.0;
|
||||||
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
|
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
|
||||||
|
@ -4676,6 +4731,13 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
conf.set("renderBackend",settings.renderBackend);
|
conf.set("renderBackend",settings.renderBackend);
|
||||||
conf.set("renderClearPos",settings.renderClearPos);
|
conf.set("renderClearPos",settings.renderClearPos);
|
||||||
|
|
||||||
|
conf.set("glRedSize",settings.glRedSize);
|
||||||
|
conf.set("glGreenSize",settings.glGreenSize);
|
||||||
|
conf.set("glBlueSize",settings.glBlueSize);
|
||||||
|
conf.set("glAlphaSize",settings.glAlphaSize);
|
||||||
|
conf.set("glDepthSize",settings.glDepthSize);
|
||||||
|
conf.set("glDoubleBuffer",settings.glDoubleBuffer);
|
||||||
|
|
||||||
conf.set("vsync",settings.vsync);
|
conf.set("vsync",settings.vsync);
|
||||||
conf.set("frameRateLimit",settings.frameRateLimit);
|
conf.set("frameRateLimit",settings.frameRateLimit);
|
||||||
conf.set("displayRenderTime",settings.displayRenderTime);
|
conf.set("displayRenderTime",settings.displayRenderTime);
|
||||||
|
|
20
src/main.cpp
20
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)"));
|
||||||
|
@ -451,12 +450,13 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
// Windows console thing - thanks dj.tuBIG/MaliceX
|
// Windows console thing - thanks dj.tuBIG/MaliceX
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#ifndef TA_SUBSYSTEM_CONSOLE
|
||||||
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
freopen("CONOUT$", "w", stdout);
|
freopen("CONOUT$", "w", stdout);
|
||||||
freopen("CONOUT$", "w", stderr);
|
freopen("CONOUT$", "w", stderr);
|
||||||
freopen("CONIN$", "r", stdin);
|
freopen("CONIN$", "r", stdin);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
@ -715,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