aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2020-02-14 00:30:42 +0800
committerGravatar Chris Xiong <chirs241097@gmail.com> 2020-02-15 18:44:07 +0800
commit59b0a4f74fd358d44c65137e41594fc7dc8a106e (patch)
treecfc218d5e0b75123f6635d9e8609558a859ff4e5
parent002baf9367417604412ed19d283835c23454349e (diff)
downloadQMidiPlayer-59b0a4f74fd358d44c65137e41594fc7dc8a106e.tar.xz
New scheme for visualizing note velocity.
Updated default color scheme for better results. New class smColor, which is going to replace smColorHSVA & smColorRGBA in the future.
-rw-r--r--visualization/extrasmeltutils.cpp171
-rw-r--r--visualization/extrasmeltutils.hpp38
-rw-r--r--visualization/qmpvisualization.cpp17
3 files changed, 219 insertions, 7 deletions
diff --git a/visualization/extrasmeltutils.cpp b/visualization/extrasmeltutils.cpp
index c8b3446..2d0a807 100644
--- a/visualization/extrasmeltutils.cpp
+++ b/visualization/extrasmeltutils.cpp
@@ -196,3 +196,174 @@ void smParticleSystem::updatePS()
}
void smParticleSystem::renderPS()
{for(unsigned i=0;i<particles.size();++i)particles[i]->render();}
+
+smColor::smColor()
+{r=g=b=h=s=v=a=0;}
+
+void smColor::update_rgb()
+{
+ auto f=[this](float n){
+ float k=fmodf(n+6.0f*this->h,6.0f);
+ return this->v-this->v*this->s*max(0.0f,min(1.0f,min(k,4.0f-k)));
+ };
+ r=f(5);
+ g=f(3);
+ b=f(1);
+}
+void smColor::update_hsv()
+{
+ v=max(r,max(g,b));
+ float vm=min(r,min(g,b));
+ float chroma=v-vm;
+ if(v-vm<EPSF)h=0;
+ else if(v-r<EPSF)h=(0.0f+(g-b)/chroma)/6.0f;
+ else if(v-g<EPSF)h=(2.0f+(b-r)/chroma)/6.0f;
+ else if(v-b<EPSF)h=(4.0f+(r-g)/chroma)/6.0f;
+ if(v<EPSF)s=0;else s=chroma/v;
+}
+
+void smColor::clamp(bool hsv)
+{
+ if(hsv)
+ {
+ h=min(1.0f,max(0.0f,h));
+ s=min(1.0f,max(0.0f,s));
+ v=min(1.0f,max(0.0f,v));
+ update_rgb();
+ }
+ else
+ {
+ r=min(1.0f,max(0.0f,r));
+ g=min(1.0f,max(0.0f,g));
+ b=min(1.0f,max(0.0f,b));
+ update_hsv();
+ }
+}
+float smColor::alpha()const
+{return a;}
+float smColor::red()const
+{return r;}
+float smColor::green()const
+{return g;}
+float smColor::blue()const
+{return b;}
+float smColor::hue()const
+{return h;}
+float smColor::saturation()const
+{return s;}
+float smColor::hslSaturation()const
+{
+ float l=lightness();
+ if(fabsf(l)<EPSF||fabsf(l-1)<EPSF)return 0;
+ return (v-l)/min(l,1-l);
+}
+float smColor::value()const
+{return v;}
+float smColor::lightness()const
+{return v-v*s/2;}
+
+void smColor::setAlpha(float alpha)
+{a=alpha;}
+void smColor::setRed(float red)
+{
+ if(fabsf(r-red)>EPSF)
+ {
+ r=red;
+ update_hsv();
+ }
+}
+void smColor::setGreen(float green)
+{
+ if(fabsf(g-green)>EPSF)
+ {
+ g=green;
+ update_hsv();
+ }
+}
+void smColor::setBlue(float blue)
+{
+ if(fabsf(b-blue)>EPSF)
+ {
+ b=blue;
+ update_hsv();
+ }
+}
+void smColor::setHue(float hue)
+{
+ if(fabsf(h-hue)>EPSF)
+ {
+ h=hue;
+ update_rgb();
+ }
+}
+void smColor::setSaturation(float saturation)
+{
+ if(fabsf(s-saturation)>EPSF)
+ {
+ s=saturation;
+ update_rgb();
+ }
+}
+void smColor::setHSLSaturation(float saturation)
+{
+ float ss=hslSaturation();
+ float l=lightness();
+ if(fabsf(ss-saturation)>EPSF)
+ {
+ ss=saturation;
+ v=l+ss*min(l,1-l);
+ if(v<EPSF)s=0;
+ else s=2-2*l/v;
+ update_rgb();
+ }
+}
+void smColor::setValue(float value)
+{
+ if(fabsf(v-value)>EPSF)
+ {
+ v=value;
+ update_rgb();
+ }
+}
+void smColor::setLightness(float lightness)
+{
+ float ss=hslSaturation();
+ float l=this->lightness();
+ if(fabsf(l-lightness)>EPSF)
+ {
+ l=lightness;
+ v=l+ss*min(l,1-l);
+ if(v<EPSF)s=0;
+ else s=2-2*l/v;
+ update_rgb();
+ }
+}
+smColor smColor::lighter(int factor)
+{
+ smColor ret(*this);
+ ret.setValue(v*(factor/100.0f));
+ ret.clamp(true);
+ return ret;
+}
+smColor smColor::darker(int factor)
+{
+ smColor ret(*this);
+ ret.setValue(factor?(v/(factor/100.0f)):1.);
+ ret.clamp(true);
+ return ret;
+}
+
+uint32_t smColor::toHWColor()
+{
+ return RGBA(r*255,g*255,b*255,a*255);
+}
+smColor smColor::fromHWColor(uint32_t color)
+{
+ smColor ret;
+ ret.r=GETR(color)/255.0f;
+ ret.g=GETG(color)/255.0f;
+ ret.b=GETB(color)/255.0f;
+ ret.a=GETA(color)/255.0f;
+ ret.update_hsv();
+ return ret;
+}
diff --git a/visualization/extrasmeltutils.hpp b/visualization/extrasmeltutils.hpp
index d827567..3cea3fc 100644
--- a/visualization/extrasmeltutils.hpp
+++ b/visualization/extrasmeltutils.hpp
@@ -1,3 +1,8 @@
+//Extra utilities for SMELT
+//Chris Xiong, 2016-2020
+//License: LGPL v3
+//This file contains staging extensions for SMELT,
+//which will be moved into SMELT once they are mature.
#ifndef EXTRASMELTUTILS_H
#define EXTRASMELTUTILS_H
#include <ctime>
@@ -5,6 +10,7 @@
#include <smelt.hpp>
#include <smmath.hpp>
#include <smrandom.hpp>
+#define EPSF 1e-6f
class smEntity3D
{
friend class smEntity3DBuffer;
@@ -34,6 +40,38 @@ class smEntity3DBuffer
void drawBatch();
};
+class smColor
+{
+ private:
+ float r,g,b,h,s,v,a;
+ void update_rgb();
+ void update_hsv();
+ public:
+ smColor();
+ void clamp(bool hsv);
+ float alpha()const;
+ float red()const;
+ float green()const;
+ float blue()const;
+ float hue()const;
+ float saturation()const;
+ float hslSaturation()const;
+ float value()const;
+ float lightness()const;
+ void setAlpha(float alpha);
+ void setRed(float red);
+ void setGreen(float green);
+ void setBlue(float blue);
+ void setHue(float hue);
+ void setSaturation(float saturation);
+ void setHSLSaturation(float saturation);
+ void setValue(float value);
+ void setLightness(float lightness);
+ smColor lighter(int factor);
+ smColor darker(int factor);
+ uint32_t toHWColor();
+ static smColor fromHWColor(uint32_t color);
+};
class smPSEmissionPositionGenerator
{
public:
diff --git a/visualization/qmpvisualization.cpp b/visualization/qmpvisualization.cpp
index e725263..5ada18f 100644
--- a/visualization/qmpvisualization.cpp
+++ b/visualization/qmpvisualization.cpp
@@ -18,13 +18,13 @@ const wchar_t* minors=L"abebbbf c g d a e b f#c#g#d#a#";
const wchar_t* majors=L"CbGbDbAbEbBbF C G D A E B F#C#";
double fpoffsets[]={1,18,28,50,55,82,98,109,130,137,161,164,191};
double froffsets[]={0,18,33,50,65,82,98,113,130,145,161,176,191};
-DWORD iccolors[]={0XFFFF0000,0XFFFF8000,0XFFFFBF00,0XFFFFFF00,
- 0XFFBFFF00,0XFF80FF00,0XFF00FF00,0XFF00FFBF,
- 0XFF00FFFF,0XFF333333,0XFF00BFFF,0XFF007FFF,
+DWORD iccolors[]={0XFFFF0000,0XFFFF8000,0XFFFFBF00,0XFFF0F000,
+ 0XFFB2EE00,0XFF80FF00,0XFF00FF00,0XFF00EEB2,
+ 0XFF00EEEE,0XFF333333,0XFF00BFFF,0XFF007FFF,
0XFF0000FF,0XFF7F00FF,0XFFBF00FF,0XFFFF00BF};
-DWORD accolors[]={0XFFFF9999,0XFFFFCC99,0XFFFFEE99,0XFFFFFF99,
- 0XFFEEFF99,0XFFCCFF99,0XFF99FF99,0XFF99FFCC,
- 0XFF99FFFF,0XFF999999,0XFF99EEFF,0XFF99CCFF,
+DWORD accolors[]={0XFFFF9999,0XFFFFCC99,0XFFFFF4D4,0XFFFFFFDD,
+ 0XFFF0FFC2,0XFFDDFFBB,0XFFBBFFBB,0XFFAAFFEA,
+ 0XFFBBFFFF,0XFF999999,0XFF99EEFF,0XFF99CCFF,
0XFF9999FF,0XFFCC99FF,0XFFEE99FF,0XFFFF99EE};
std::set<BYTE> sustaininst={16,17,18,19,20,21,22,23,
@@ -329,7 +329,10 @@ void qmpVisualization::updateVisualization3D()
spectra[pool[i]->ch][pool[i]->key]=pool[i]->vel*(api->getChannelCC(pool[i]->ch,7)/127.);
}
else
- drawCube(a,b,SETA(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch],int(pool[i]->vel*1.6+(isnoteon?52:32))),0);
+ {
+ smColor col=smColor::fromHWColor(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch]);
+ drawCube(a,b,col.lighter(37+pool[i]->vel/2).toHWColor(),0);
+ }
}
}
if(usespectrum&&playing)