diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 55a9c472c..ecc335c0a 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -7260,6 +7260,10 @@ bool FurnaceGUI::finish() { oscValues[i]=NULL; } } + if (oscValuesAverage) { + delete[] oscValuesAverage; + oscValuesAverage=NULL; + } if (backupTask.valid()) { backupTask.get(); @@ -7700,6 +7704,7 @@ FurnaceGUI::FurnaceGUI(): subPortPos(0.0f,0.0f), oscTotal(0), oscWidth(512), + oscValuesAverage(NULL), oscZoom(0.5f), oscWindowSize(20.0f), oscInput(0.0f), diff --git a/src/gui/gui.h b/src/gui/gui.h index 4e3cdffb9..a821530c0 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1435,7 +1435,7 @@ class FurnaceGUIRender { virtual void destroyFontsTexture(); virtual void renderGUI(); virtual void wipe(float alpha); - virtual void drawOsc(float* data, size_t len, ImVec2 pos0, ImVec2 pos1, ImVec4 color); + virtual void drawOsc(float* data, size_t len, ImVec2 pos0, ImVec2 pos1, ImVec4 color, ImVec2 canvasSize, float lineWidth); virtual void present(); virtual bool getOutputSize(int& w, int& h); virtual int getWindowFlags(); @@ -1448,6 +1448,22 @@ class FurnaceGUIRender { virtual ~FurnaceGUIRender(); }; +struct PendingDrawOsc { + void* gui; + float* data; + size_t len; + ImVec2 pos0; + ImVec2 pos1; + ImVec4 color; + PendingDrawOsc(): + gui(NULL), + data(NULL), + len(0), + pos0(0,0), + pos1(0,0), + color(0,0,0,0) {} +}; + class FurnaceGUI { DivEngine* e; @@ -2256,6 +2272,7 @@ class FurnaceGUI { // oscilloscope int oscTotal, oscWidth; float* oscValues[DIV_MAX_OUTPUTS]; + float* oscValuesAverage; float oscZoom; float oscWindowSize; float oscInput, oscInput1; @@ -2670,6 +2687,7 @@ class FurnaceGUI { void runBackupThread(); void pushPartBlend(); void popPartBlend(); + void runPendingDrawOsc(PendingDrawOsc* which); bool detectOutOfBoundsWindow(SDL_Rect& failing); int processEvent(SDL_Event* ev); bool loop(); diff --git a/src/gui/osc.cpp b/src/gui/osc.cpp index 8ebbc98dd..906e02e02 100644 --- a/src/gui/osc.cpp +++ b/src/gui/osc.cpp @@ -100,6 +100,19 @@ void FurnaceGUI::readOsc() { } } + if (oscValuesAverage==NULL) { + oscValuesAverage=new float[2048]; + } + memset(oscValuesAverage,0,2048*sizeof(float)); + for (int i=0; igetAudioDescGot().outChans; j++) { + avg+=oscValues[j][i]; + } + avg/=e->getAudioDescGot().outChans; + oscValuesAverage[i]=avg; + } + /*for (int i=0; ioscReadPos=readPos; } -void _pushPartBlend(const ImDrawList* drawList, const ImDrawCmd* cmd) { +PendingDrawOsc _do; + +void _drawOsc(const ImDrawList* drawList, const ImDrawCmd* cmd) { if (cmd!=NULL) { if (cmd->UserCallbackData!=NULL) { - ((FurnaceGUI*)cmd->UserCallbackData)->pushPartBlend(); + ((FurnaceGUI*)(((PendingDrawOsc*)cmd->UserCallbackData)->gui))->runPendingDrawOsc((PendingDrawOsc*)cmd->UserCallbackData); } } } +void FurnaceGUI::runPendingDrawOsc(PendingDrawOsc* which) { + rend->drawOsc(which->data,which->len,which->pos0,which->pos1,which->color,ImVec2(canvasW,canvasH),dpiScale); +} + void FurnaceGUI::drawOsc() { if (nextWindow==GUI_WINDOW_OSCILLOSCOPE) { oscOpen=true; @@ -191,7 +210,7 @@ void FurnaceGUI::drawOsc() { inRect.Max.x-=dpiScale; inRect.Max.y-=dpiScale; ImGuiStyle& style=ImGui::GetStyle(); - //ImU32 color=ImGui::GetColorU32(isClipping?uiColors[GUI_COLOR_OSC_WAVE_PEAK]:uiColors[GUI_COLOR_OSC_WAVE]); + ImU32 color=ImGui::GetColorU32(isClipping?uiColors[GUI_COLOR_OSC_WAVE_PEAK]:uiColors[GUI_COLOR_OSC_WAVE]); ImU32 borderColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_BORDER]); ImU32 refColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_REF]); ImU32 guideColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_GUIDE]); @@ -276,13 +295,7 @@ void FurnaceGUI::drawOsc() { if (settings.oscMono) { for (int i=0; igetAudioDescGot().outChans; j++) { - avg+=oscValues[j][i+12]; - } - avg/=e->getAudioDescGot().outChans; - - float y=avg*oscZoom; + float y=oscValuesAverage[i+12]*oscZoom; if (!settings.oscEscapesBoundary) { if (y<-0.5f) y=-0.5f; if (y>0.5f) y=0.5f; @@ -290,7 +303,6 @@ void FurnaceGUI::drawOsc() { waveform[i]=ImLerp(inRect.Min,inRect.Max,ImVec2(x,0.5f-y)); } - /* if (settings.oscEscapesBoundary) { dl->PushClipRectFullScreen(); dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale); @@ -298,8 +310,15 @@ void FurnaceGUI::drawOsc() { } else { dl->AddPolyline(waveform,oscWidth-24,color,ImDrawFlags_None,dpiScale); } - */ - //dl->AddCallback(_renderOsc,this); + + _do.gui=this; + _do.data=&oscValuesAverage[12]; + _do.len=oscWidth-24; + _do.pos0=inRect.Min; + _do.pos1=inRect.Max; + _do.color=isClipping?uiColors[GUI_COLOR_OSC_WAVE_PEAK]:uiColors[GUI_COLOR_OSC_WAVE]; + + dl->AddCallback(_drawOsc,&_do); } else { for (int ch=0; chgetAudioDescGot().outChans; ch++) { for (int i=0; i2048) len=2048; memcpy(oscData,data,len*sizeof(float)); @@ -385,31 +393,32 @@ void FurnaceGUIRenderGL::drawOsc(float* data, size_t len, ImVec2 pos0, ImVec2 po C(glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)); C(glEnable(GL_BLEND)); + pos0.x=(2.0f*pos0.x/canvasSize.x)-1.0f; + pos0.y=(2.0f*pos0.y/canvasSize.y)-1.0f; + pos1.x=(2.0f*pos1.x/canvasSize.x)-1.0f; + pos1.y=(2.0f*pos1.y/canvasSize.y)-1.0f; + oscVertex[0][0]=pos0.x; oscVertex[0][1]=pos1.y; oscVertex[0][2]=0.0f; - oscVertex[0][3]=0.0f; - oscVertex[0][4]=1.0f; + oscVertex[0][3]=1.0f; oscVertex[1][0]=pos1.x; oscVertex[1][1]=pos1.y; - oscVertex[1][2]=0.0f; + oscVertex[1][2]=1.0f; oscVertex[1][3]=1.0f; - oscVertex[1][4]=1.0f; oscVertex[2][0]=pos0.x; oscVertex[2][1]=pos0.y; oscVertex[2][2]=0.0f; oscVertex[2][3]=0.0f; - oscVertex[2][4]=0.0f; oscVertex[3][0]=pos1.x; oscVertex[3][1]=pos0.y; - oscVertex[3][2]=0.0f; - oscVertex[3][3]=1.0f; - oscVertex[3][4]=0.0f; + oscVertex[3][2]=1.0f; + oscVertex[3][3]=0.0f; C(furBindBuffer(GL_ARRAY_BUFFER,oscVertexBuf)); C(furBufferData(GL_ARRAY_BUFFER,sizeof(oscVertex),oscVertex,GL_STATIC_DRAW)); - C(furVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5,NULL)); - C(furVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5,(void*)3)); + C(furVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,4*sizeof(float),NULL)); + C(furVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,4*sizeof(float),(void*)(2*sizeof(float)))); C(furEnableVertexAttribArray(0)); C(furEnableVertexAttribArray(1)); C(furActiveTexture(GL_TEXTURE0)); @@ -417,11 +426,13 @@ void FurnaceGUIRenderGL::drawOsc(float* data, size_t len, ImVec2 pos0, ImVec2 po C(furUseProgram(sh_oscRender_program)); C(furUniform4fv(sh_oscRender_uColor,1,(float*)&color)); - C(furUniform1f(sh_oscRender_uLineWidth,2.0f)); + C(furUniform1f(sh_oscRender_uLineWidth,lineWidth)); C(furUniform2f(sh_oscRender_uResolution,1.0f,1.0f)); C(furUniform1i(sh_oscRender_oscVal,0)); C(glDrawArrays(GL_TRIANGLE_STRIP,0,4)); + C(furDisableVertexAttribArray(1)); + C(furUseProgram(0)); C(glBindTexture(GL_TEXTURE_2D,0)); } @@ -493,6 +504,7 @@ bool FurnaceGUIRenderGL::init(SDL_Window* win) { LOAD_PROC_MANDATORY(furBufferData,PFNGLBUFFERDATAPROC,"glBufferData"); LOAD_PROC_MANDATORY(furVertexAttribPointer,PFNGLVERTEXATTRIBPOINTERPROC,"glVertexAttribPointer"); LOAD_PROC_MANDATORY(furEnableVertexAttribArray,PFNGLENABLEVERTEXATTRIBARRAYPROC,"glEnableVertexAttribArray"); + LOAD_PROC_MANDATORY(furDisableVertexAttribArray,PFNGLDISABLEVERTEXATTRIBARRAYPROC,"glDisableVertexAttribArray"); LOAD_PROC_MANDATORY(furActiveTexture,PFNGLACTIVETEXTUREPROC,"glActiveTexture"); LOAD_PROC_OPTIONAL(furCreateShader,PFNGLCREATESHADERPROC,"glCreateShader"); diff --git a/src/gui/render/renderGL.h b/src/gui/render/renderGL.h index be7949813..c4d8da83d 100644 --- a/src/gui/render/renderGL.h +++ b/src/gui/render/renderGL.h @@ -24,7 +24,7 @@ class FurnaceGUIRenderGL: public FurnaceGUIRender { SDL_Window* sdlWin; float quadVertex[4][3]; unsigned int quadBuf; - float oscVertex[4][5]; + float oscVertex[4][4]; unsigned int oscVertexBuf; unsigned int oscDataTex; float oscData[2048]; @@ -61,7 +61,7 @@ class FurnaceGUIRenderGL: public FurnaceGUIRender { void destroyFontsTexture(); void renderGUI(); void wipe(float alpha); - void drawOsc(float* data, size_t len, ImVec2 pos0, ImVec2 pos1, ImVec4 color); + void drawOsc(float* data, size_t len, ImVec2 pos0, ImVec2 pos1, ImVec4 color, ImVec2 canvasSize, float lineWidth); void present(); bool getOutputSize(int& w, int& h); int getWindowFlags();