| /* |
| * MilkdropWaveform.cpp |
| * |
| * Created on: Jun 25, 2008 |
| * Author: pete |
| */ |
| #include <iostream> |
| |
| #ifdef LINUX |
| #include <GL/gl.h> |
| #endif |
| #ifdef WIN32 |
| #include "glew.h" |
| #endif |
| #ifdef __APPLE__ |
| #include <OpenGL/gl.h> |
| #endif |
| |
| #include <cmath> |
| |
| #include "MilkdropWaveform.hpp" |
| #include "math.h" |
| #include "BeatDetect.hpp" |
| |
| MilkdropWaveform::MilkdropWaveform(): RenderItem(), |
| x(0.5), y(0.5), r(1), g(0), b(0), a(1), mystery(0), mode(Line), scale(10), smoothing(0), rot(0), samples(0),modOpacityStart(0),modOpacityEnd(1), |
| modulateAlphaByVolume(false), maximizeColors(false), additive(false), dots(false), thick(false), loop(false) {} |
| |
| void MilkdropWaveform::Draw(RenderContext &context) |
| { |
| WaveformMath(context); |
| |
| glMatrixMode( GL_MODELVIEW ); |
| glPushMatrix(); |
| glLoadIdentity(); |
| |
| if(modulateAlphaByVolume) ModulateOpacityByVolume(context); |
| else temp_a = a; |
| MaximizeColors(context); |
| |
| #ifndef USE_GLES1 |
| if(dots==1) glEnable(GL_LINE_STIPPLE); |
| #endif |
| |
| //Thick wave drawing |
| if (thick==1) glLineWidth( (context.texsize < 512 ) ? 2 : 2*context.texsize/512); |
| else glLineWidth( (context.texsize < 512 ) ? 1 : context.texsize/512); |
| |
| //Additive wave drawing (vice overwrite) |
| if (additive==1)glBlendFunc(GL_SRC_ALPHA, GL_ONE); |
| else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| |
| |
| glTranslatef(.5, .5, 0); |
| glRotatef(rot, 0, 0, 1); |
| glScalef(aspectScale, 1.0, 1.0); |
| glTranslatef(-.5, -.5, 0); |
| |
| |
| glEnableClientState(GL_VERTEX_ARRAY); |
| glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
| glDisableClientState(GL_COLOR_ARRAY); |
| glVertexPointer(2,GL_FLOAT,0,wavearray); |
| |
| if (loop) |
| glDrawArrays(GL_LINE_LOOP,0,samples); |
| else |
| glDrawArrays(GL_LINE_STRIP,0,samples); |
| |
| |
| if (two_waves) |
| { |
| glVertexPointer(2,GL_FLOAT,0,wavearray2); |
| if (loop) |
| glDrawArrays(GL_LINE_LOOP,0,samples); |
| else |
| glDrawArrays(GL_LINE_STRIP,0,samples); |
| } |
| |
| |
| #ifndef USE_GLES1 |
| if(dots==1) glDisable(GL_LINE_STIPPLE); |
| #endif |
| |
| glPopMatrix(); |
| } |
| |
| void MilkdropWaveform::ModulateOpacityByVolume(RenderContext &context) |
| { |
| |
| //modulate volume by opacity |
| // |
| //set an upper and lower bound and linearly |
| //calculate the opacity from 0=lower to 1=upper |
| //based on current volume |
| |
| if (context.beatDetect->vol<= modOpacityStart) temp_a=0.0; |
| else if (context.beatDetect->vol>=modOpacityEnd) temp_a=a; |
| else temp_a=a*((context.beatDetect->vol-modOpacityStart)/(modOpacityEnd-modOpacityStart)); |
| |
| } |
| |
| void MilkdropWaveform::MaximizeColors(RenderContext &context) |
| { |
| |
| float wave_r_switch=0, wave_g_switch=0, wave_b_switch=0; |
| //wave color brightening |
| // |
| //forces max color value to 1.0 and scales |
| // the rest accordingly |
| if(mode==Blob2 || mode==Blob5) |
| switch(context.texsize) |
| { |
| case 256: temp_a *= 0.07f; break; |
| case 512: temp_a *= 0.09f; break; |
| case 1024: temp_a *= 0.11f; break; |
| case 2048: temp_a *= 0.13f; break; |
| } |
| else if(mode==Blob3) |
| { |
| switch(context.texsize) |
| { |
| case 256: temp_a *= 0.075f; break; |
| case 512: temp_a *= 0.15f; break; |
| case 1024: temp_a *= 0.22f; break; |
| case 2048: temp_a *= 0.33f; break; |
| } |
| temp_a*=1.3f; |
| temp_a*=std::pow(context.beatDetect->treb , 2.0f); |
| } |
| |
| if (maximizeColors==true) |
| { |
| if(r>=g && r>=b) //red brightest |
| { |
| wave_b_switch=b*(1/r); |
| wave_g_switch=g*(1/r); |
| wave_r_switch=1.0; |
| } |
| else if (b>=g && b>=r) //blue brightest |
| { |
| wave_r_switch=r*(1/b); |
| wave_g_switch=g*(1/b); |
| wave_b_switch=1.0; |
| |
| } |
| |
| else if (g>=b && g>=r) //green brightest |
| { |
| wave_b_switch=b*(1/g); |
| wave_r_switch=r*(1/g); |
| wave_g_switch=1.0; |
| } |
| |
| |
| glColor4f(wave_r_switch, wave_g_switch, wave_b_switch, temp_a * masterAlpha); |
| } |
| else |
| { |
| glColor4f(r, g, b, temp_a * masterAlpha); |
| } |
| } |
| |
| |
| void MilkdropWaveform::WaveformMath(RenderContext &context) |
| { |
| |
| int i; |
| |
| float r, theta; |
| |
| float offset; |
| |
| float wave_x_temp=0; |
| float wave_y_temp=0; |
| |
| float cos_rot; |
| float sin_rot; |
| |
| offset=x-.5; |
| float temp_y; |
| |
| two_waves = false; |
| loop = false; |
| |
| switch(mode) |
| { |
| |
| case Circle: |
| { |
| loop = true; |
| rot = 0; |
| aspectScale=1.0; |
| temp_y=-1*(y-1.0); |
| |
| |
| samples = 0? 512-32 : context.beatDetect->pcm->numsamples; |
| |
| float inv_nverts_minus_one = 1.0f/(float)(samples); |
| |
| float last_value = context.beatDetect->pcm->pcmdataR[samples-1]+context.beatDetect->pcm->pcmdataL[samples-1]; |
| float first_value = context.beatDetect->pcm->pcmdataR[0]+context.beatDetect->pcm->pcmdataL[0]; |
| float offset = first_value-last_value; |
| |
| for ( int i=0;i<samples;i++) |
| { |
| |
| float value = context.beatDetect->pcm->pcmdataR[i]+context.beatDetect->pcm->pcmdataL[i]; |
| value += offset * (i/(float)samples); |
| |
| r=(0.5 + 0.4f*.12*value*scale + mystery)*.5; |
| theta=i*inv_nverts_minus_one*6.28f + context.time*0.2f; |
| |
| wavearray[i][0]=(r*cos(theta)*(context.aspectCorrect? context.aspectRatio : 1.0)+x); |
| wavearray[i][1]=(r*sin(theta)+temp_y); |
| } |
| } |
| |
| break; |
| |
| case RadialBlob://circularly moving waveform |
| |
| rot = 0; |
| aspectScale = context.aspectRatio; |
| |
| temp_y=-1*(y-1.0); |
| |
| samples = 512-32; |
| for ( int i=0;i<512-32;i++) |
| { |
| theta=context.beatDetect->pcm->pcmdataL[i+32]*0.06*scale * 1.57 + context.time*2.3; |
| r=(0.53 + 0.43*context.beatDetect->pcm->pcmdataR[i]*0.12*scale+ mystery)*.5; |
| |
| wavearray[i][0]=(r*cos(theta)*(context.aspectCorrect ? context.aspectRatio : 1.0)+x); |
| wavearray[i][1]=(r*sin(theta)+temp_y); |
| } |
| |
| break; |
| |
| case Blob2://EXPERIMENTAL |
| |
| temp_y=-1*(y-1.0); |
| rot = 0; |
| aspectScale =1.0; |
| samples = 512-32; |
| |
| for ( int i=0;i<512-32;i++) |
| { |
| wavearray[i][0]=(context.beatDetect->pcm->pcmdataR[i]*scale*0.5*(context.aspectCorrect ? context.aspectRatio : 1.0) + x); |
| wavearray[i][1]=(context.beatDetect->pcm->pcmdataL[i+32]*scale*0.5 + temp_y); |
| } |
| |
| break; |
| |
| case Blob3://EXPERIMENTAL |
| |
| temp_y=-1*(y-1.0); |
| |
| rot = 0; |
| aspectScale =1.0; |
| |
| samples = 512-32; |
| |
| for ( int i=0;i<512-32;i++) |
| { |
| wavearray[i][0]=(context.beatDetect->pcm->pcmdataR[i] * scale*0.5 + x); |
| wavearray[i][1]=( (context.beatDetect->pcm->pcmdataL[i+32]*scale*0.5 + temp_y)); |
| } |
| |
| break; |
| |
| case DerivativeLine://single x-axis derivative waveform |
| { |
| rot =-mystery*90; |
| aspectScale=1.0; |
| |
| temp_y=-1*(y-1.0); |
| |
| float w1 = 0.45f + 0.5f*(mystery*0.5f + 0.5f); |
| float w2 = 1.0f - w1; |
| float xx[512], yy[512]; |
| samples = 512-32; |
| |
| for (int i=0; i<512-32; i++) |
| { |
| xx[i] = -1.0f + 2.0f*(i/(512.0-32.0)) + x; |
| yy[i] =0.4* context.beatDetect->pcm->pcmdataL[i]*0.47f*scale + temp_y; |
| xx[i] += 0.4*context.beatDetect->pcm->pcmdataR[i]*0.44f*scale; |
| |
| if (i>1) |
| { |
| xx[i] = xx[i]*w2 + w1*(xx[i-1]*2.0f - xx[i-2]); |
| yy[i] = yy[i]*w2 + w1*(yy[i-1]*2.0f - yy[i-2]); |
| } |
| wavearray[i][0]=xx[i]; |
| wavearray[i][1]=yy[i]; |
| } } |
| break; |
| |
| case Blob5://EXPERIMENTAL |
| |
| rot = 0; |
| aspectScale =1.0; |
| |
| temp_y=-1*(y-1.0); |
| |
| cos_rot = cosf(context.time*0.3f); |
| sin_rot = sinf(context.time*0.3f); |
| samples = 512-32; |
| |
| for ( int i=0;i<512-32;i++) |
| { |
| float x0 = (context.beatDetect->pcm->pcmdataR[i]*context.beatDetect->pcm->pcmdataL[i+32] + context.beatDetect->pcm->pcmdataL[i+32]*context.beatDetect->pcm->pcmdataR[i]); |
| float y0 = (context.beatDetect->pcm->pcmdataR[i]*context.beatDetect->pcm->pcmdataR[i] - context.beatDetect->pcm->pcmdataL[i+32]*context.beatDetect->pcm->pcmdataL[i+32]); |
| wavearray[i][0]=((x0*cos_rot - y0*sin_rot)*scale*0.5*(context.aspectCorrect ? context.aspectRatio : 1.0) + x); |
| wavearray[i][1]=( (x0*sin_rot + y0*cos_rot)*scale*0.5 + temp_y); |
| } |
| break; |
| |
| case Line://single waveform |
| |
| |
| wave_x_temp=-2*0.4142*(fabs(fabs(mystery)-.5)-.5); |
| |
| rot = -mystery*90; |
| aspectScale =1.0+wave_x_temp; |
| wave_x_temp=-1*(x-1.0); |
| samples = 0 ? 512-32 : context.beatDetect->pcm->numsamples; |
| |
| for ( int i=0;i< samples;i++) |
| { |
| |
| wavearray[i][0]=i/(float) samples; |
| wavearray[i][1]=context.beatDetect->pcm->pcmdataR[i]*.04*scale+wave_x_temp; |
| |
| } |
| // printf("%f %f\n",renderTarget->texsize*wave_y_temp,wave_y_temp); |
| |
| break; |
| |
| case DoubleLine://dual waveforms |
| |
| |
| wave_x_temp=-2*0.4142*(fabs(fabs(mystery)-.5)-.5); |
| |
| rot = -mystery*90; |
| aspectScale =1.0+wave_x_temp; |
| |
| |
| samples = 0 ? 512-32 : context.beatDetect->pcm->numsamples; |
| two_waves = true; |
| |
| double y_adj = y*y*.5; |
| |
| wave_y_temp=-1*(x-1); |
| |
| for ( int i=0;i<samples;i++) |
| { |
| wavearray[i][0]=i/((float) samples); |
| wavearray[i][1]= context.beatDetect->pcm->pcmdataL[i]*.04*scale+(wave_y_temp+y_adj); |
| } |
| |
| for ( int i=0;i<samples;i++) |
| { |
| wavearray2[i][0]=i/((float) samples); |
| wavearray2[i][1]=context.beatDetect->pcm->pcmdataR[i]*.04*scale+(wave_y_temp-y_adj); |
| } |
| |
| break; |
| |
| } |
| } |