audio export: more stuff
This commit is contained in:
parent
68383869d3
commit
56a3cfe13d
|
@ -98,8 +98,14 @@ 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 {
|
struct DivAudioExportOptions {
|
||||||
DivAudioExportModes mode;
|
DivAudioExportModes mode;
|
||||||
|
DivAudioExportFormats format;
|
||||||
int sampleRate;
|
int sampleRate;
|
||||||
int chans;
|
int chans;
|
||||||
int loops;
|
int loops;
|
||||||
|
@ -108,6 +114,7 @@ struct DivAudioExportOptions {
|
||||||
bool channelMask[DIV_MAX_CHANS];
|
bool channelMask[DIV_MAX_CHANS];
|
||||||
DivAudioExportOptions():
|
DivAudioExportOptions():
|
||||||
mode(DIV_EXPORT_MODE_ONE),
|
mode(DIV_EXPORT_MODE_ONE),
|
||||||
|
format(DIV_EXPORT_FORMAT_S16),
|
||||||
sampleRate(44100),
|
sampleRate(44100),
|
||||||
chans(2),
|
chans(2),
|
||||||
loops(0),
|
loops(0),
|
||||||
|
@ -478,8 +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;
|
int exportOutputs;
|
||||||
|
bool exportChannelMask[DIV_MAX_CHANS];
|
||||||
DivConfig conf;
|
DivConfig conf;
|
||||||
FixedQueue<DivNoteEvent,8192> pendingNotes;
|
FixedQueue<DivNoteEvent,8192> pendingNotes;
|
||||||
// bitfield
|
// bitfield
|
||||||
|
@ -1382,6 +1391,7 @@ 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),
|
exportOutputs(2),
|
||||||
cmdStreamInt(NULL),
|
cmdStreamInt(NULL),
|
||||||
|
@ -1435,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;
|
||||||
|
|
|
@ -46,7 +46,11 @@ void DivEngine::runExportThread() {
|
||||||
SFWrapper sfWrap;
|
SFWrapper sfWrap;
|
||||||
si.samplerate=got.rate;
|
si.samplerate=got.rate;
|
||||||
si.channels=exportOutputs;
|
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) {
|
||||||
|
@ -253,6 +257,7 @@ void DivEngine::runExportThread() {
|
||||||
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;
|
||||||
|
@ -260,7 +265,11 @@ void DivEngine::runExportThread() {
|
||||||
logI("- %s",fname.c_str());
|
logI("- %s",fname.c_str());
|
||||||
si.samplerate=got.rate;
|
si.samplerate=got.rate;
|
||||||
si.channels=exportOutputs;
|
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) {
|
||||||
|
@ -391,7 +400,9 @@ bool DivEngine::saveAudio(const char* path, DivAudioExportOptions options) {
|
||||||
#else
|
#else
|
||||||
exportPath=path;
|
exportPath=path;
|
||||||
exportMode=options.mode;
|
exportMode=options.mode;
|
||||||
|
exportFormat=options.format;
|
||||||
exportFadeOut=options.fadeOut;
|
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;
|
||||||
|
|
|
@ -34,12 +34,24 @@ void FurnaceGUI::drawExportAudio(bool onWindow) {
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("multiple files (one per chip)",audioExportOptions.mode==DIV_EXPORT_MODE_MANY_SYS)) {
|
if (ImGui::RadioButton("multiple files (one per chip)",audioExportOptions.mode==DIV_EXPORT_MODE_MANY_SYS)) {
|
||||||
audioExportOptions.mode=DIV_EXPORT_MODE_MANY_SYS;
|
audioExportOptions.mode=DIV_EXPORT_MODE_MANY_SYS;
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("multiple files (one per channel)",audioExportOptions.mode==DIV_EXPORT_MODE_MANY_CHAN)) {
|
if (ImGui::RadioButton("multiple files (one per channel)",audioExportOptions.mode==DIV_EXPORT_MODE_MANY_CHAN)) {
|
||||||
audioExportOptions.mode=DIV_EXPORT_MODE_MANY_CHAN;
|
audioExportOptions.mode=DIV_EXPORT_MODE_MANY_CHAN;
|
||||||
}
|
}
|
||||||
ImGui::Unindent();
|
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 (ImGui::InputInt("Sample rate",&audioExportOptions.sampleRate,100,10000)) {
|
||||||
if (audioExportOptions.sampleRate<8000) audioExportOptions.sampleRate=8000;
|
if (audioExportOptions.sampleRate<8000) audioExportOptions.sampleRate=8000;
|
||||||
if (audioExportOptions.sampleRate>384000) audioExportOptions.sampleRate=384000;
|
if (audioExportOptions.sampleRate>384000) audioExportOptions.sampleRate=384000;
|
||||||
|
@ -59,25 +71,63 @@ void FurnaceGUI::drawExportAudio(bool onWindow) {
|
||||||
if (audioExportOptions.fadeOut<0.0) audioExportOptions.fadeOut=0.0;
|
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) {
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::Button("Cancel",ImVec2(200.0f*dpiScale,0))) ImGui::CloseCurrentPopup();
|
if (ImGui::Button("Cancel",ImVec2(200.0f*dpiScale,0))) ImGui::CloseCurrentPopup();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
|
if (isOneOn) {
|
||||||
switch (audioExportOptions.mode) {
|
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
|
||||||
case DIV_EXPORT_MODE_ONE:
|
switch (audioExportOptions.mode) {
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
|
case DIV_EXPORT_MODE_ONE:
|
||||||
break;
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
|
||||||
case DIV_EXPORT_MODE_MANY_SYS:
|
break;
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
|
case DIV_EXPORT_MODE_MANY_SYS:
|
||||||
break;
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
|
||||||
case DIV_EXPORT_MODE_MANY_CHAN:
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue