audio export: more stuff

This commit is contained in:
tildearrow 2024-05-11 14:25:53 -05:00
parent 68383869d3
commit 56a3cfe13d
3 changed files with 87 additions and 15 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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");
} }
} }