GUI: prepare for FM preview

This commit is contained in:
tildearrow 2023-03-17 19:12:09 -05:00
parent d58270efed
commit 57f4cc8561
4 changed files with 101 additions and 0 deletions

View File

@ -624,6 +624,7 @@ src/gui/editing.cpp
src/gui/editControls.cpp
src/gui/effectList.cpp
src/gui/findReplace.cpp
src/gui/fmPreview.cpp
src/gui/gradient.cpp
src/gui/grooves.cpp
src/gui/insEdit.cpp

View File

@ -519,6 +519,18 @@ void FurnaceGUI::drawDebug() {
ImGui::InputFloat("maxRr",&maxRr);
ImGui::TreePop();
}
if (ImGui::TreeNode("FM Preview")) {
if (ImGui::Button("Generate")) {
DivInstrument* ins=e->getIns(curIns);
if (ins!=NULL) renderFMPreview(ins->fm);
}
float asFloat[FM_PREVIEW_SIZE];
for (int i=0; i<FM_PREVIEW_SIZE; i++) {
asFloat[i]=(float)fmPreview[i]/8192.0f;
}
ImGui::PlotLines("##DebugFMPreview",asFloat,FM_PREVIEW_SIZE,0,"Preview",-1.0,1.0,ImVec2(300.0f*dpiScale,150.0f*dpiScale));
ImGui::TreePop();
}
if (ImGui::TreeNode("User Interface")) {
if (ImGui::Button("Inspect")) {
inspectorOpen=!inspectorOpen;

84
src/gui/fmPreview.cpp Normal file
View File

@ -0,0 +1,84 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define _USE_MATH_DEFINES
#include "gui.h"
#include "../../extern/opn/ym3438.h"
#define FM_WRITE(addr,val) \
OPN2_Write(&fm,0,(addr)); \
do { \
OPN2_Clock(&fm,out); \
} while (fm.write_busy); \
OPN2_Write(&fm,1,(val)); \
do { \
OPN2_Clock(&fm,out); \
} while (fm.write_busy); \
void FurnaceGUI::renderFMPreview(const DivInstrumentFM& params, int pos) {
ym3438_t fm;
short out[2];
int aOut=0;
OPN2_Reset(&fm);
OPN2_SetChipType(&fm,ym3438_mode_opn);
// set params
FM_WRITE(0x50,31); // AR
FM_WRITE(0x54,31);
FM_WRITE(0x58,31);
FM_WRITE(0x5c,31);
FM_WRITE(0x60,0); // DR
FM_WRITE(0x64,0);
FM_WRITE(0x68,0);
FM_WRITE(0x6c,0);
FM_WRITE(0x70,0); // D2R
FM_WRITE(0x74,0);
FM_WRITE(0x78,0);
FM_WRITE(0x7c,0);
FM_WRITE(0x80,0); // SL/RR
FM_WRITE(0x84,0);
FM_WRITE(0x88,0);
FM_WRITE(0x8c,0);
FM_WRITE(0xa4,0x0c); // frequency
FM_WRITE(0xa0,0);
FM_WRITE(0xb0,(params.alg&7)|((params.fb&7)<<3)); // ALG/FB
FM_WRITE(0xb4,0xc0); // pan
FM_WRITE(0x30,params.op[0].mult&15); // MULT
FM_WRITE(0x34,params.op[1].mult&15);
FM_WRITE(0x38,params.op[2].mult&15);
FM_WRITE(0x3c,params.op[3].mult&15);
FM_WRITE(0x40,params.op[0].tl&127); // TL
FM_WRITE(0x44,params.op[1].tl&127);
FM_WRITE(0x48,params.op[2].tl&127);
FM_WRITE(0x4c,params.op[3].tl&127);
FM_WRITE(0x28,0xf0); // key on
// render
for (int i=0; i<FM_PREVIEW_SIZE; i++) {
aOut=0;
for (int j=0; j<24; j++) {
OPN2_Clock(&fm,out);
}
aOut+=fm.ch_out[0];
if (aOut<-32768) aOut=-32768;
if (aOut>32767) aOut=32767;
fmPreview[i]=aOut;
}
}

View File

@ -68,6 +68,8 @@
#define BIND_FOR(x) getKeyName(actionKeys[x],true).c_str()
#define FM_PREVIEW_SIZE 1024
// TODO:
// - add colors for FM envelope and waveform
// - maybe add "alternate" color for FM modulators/carriers (a bit difficult)
@ -1192,6 +1194,7 @@ class FurnaceGUI {
ImVec2 mobileEditButtonPos, mobileEditButtonSize;
const int* curSysSection;
DivInstrumentFM opllPreview;
short fmPreview[FM_PREVIEW_SIZE];
String pendingRawSample;
int pendingRawSampleDepth, pendingRawSampleChannels;
@ -1887,6 +1890,7 @@ class FurnaceGUI {
void drawGBEnv(unsigned char vol, unsigned char len, unsigned char sLen, bool dir, const ImVec2& size);
bool drawSysConf(int chan, DivSystem type, DivConfig& flags, bool modifyOnChange);
void kvsConfig(DivInstrument* ins);
void renderFMPreview(const DivInstrumentFM& params, int pos=0);
// these ones offer ctrl-wheel fine value changes.
bool CWSliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format=NULL, ImGuiSliderFlags flags=0);