import ddf.minim.analysis.*; import ddf.minim.*; import processing.opengl.*; Minim minim; AudioPlayer audioPlayer; FFT fft; int iNumAverages = 256; int iNumSheets = iNumAverages; Sheet[] aSheets = new Sheet[iNumSheets]; float fMaxPos = 40; float fColourFadeDepth = 25; float fMaxDepthOffset = 30; float fEnergyScale = 0.5; float fTriggerEnergy = 0.95; float fMinFov = PI / 10.5; float fMaxFov = PI / 1.2; float fFovScaler = 0; //////////////////////////////////////////////////////////////////////// void setup() { size(720,450, OPENGL); minim = new Minim(this); audioPlayer = minim.loadFile("4mat-MyBeautifulEmptyHeart.mp3", 1024); audioPlayer.loop(); fft = new FFT(audioPlayer.bufferSize(), audioPlayer.sampleRate()); fft.linAverages(iNumAverages); frameRate(30); for (int i = 0; i < iNumSheets; i++) { aSheets[i] = new Sheet(i); } rectMode(CENTER); strokeWeight(2); } //////////////////////////////////////////////////////////////////////// void draw() { fft.forward(audioPlayer.mix); int iSheetsActive = 0; for (int i = 0; i < iNumSheets; i++) { if (aSheets[i].m_bIsActive) { iSheetsActive++; } } float fSheetsScaler = constrain((float)iSheetsActive / (float)iNumSheets * 2, 0, 1); fFovScaler = (fFovScaler * 0.99) + (fSheetsScaler * 0.01); perspective(lerp(fMinFov, fMaxFov, fFovScaler), float(width)/float(height), 0.1, 500); camera(0,0,15, 0,0,0, 0,1,0); background(0,0,0); for (int i = 0; i < iNumSheets; i++) { aSheets[i].Draw(); } } //////////////////////////////////////////////////////////////////////// class Sheet { Sheet(int iFreq) { m_iFreq = iFreq; m_vecPos = new PVector(0,0,0); m_vecColour = new PVector(0,0,0); m_bIsActive = false; } void Start(float fScale) { m_bIsActive = true; m_vecPos.x = -30; m_vecPos.y = (int)random(-15, 15); m_vecPos.z = (int)random(0, fMaxDepthOffset); switch ((int)random(0, 2)) { case 0: m_vecColour.x = 225; m_vecColour.y = 227; m_vecColour.z = 255; break; case 1: m_vecColour.x = 250; m_vecColour.y = 23; m_vecColour.z = 20; break; default: m_vecColour.x = 255; m_vecColour.y = 0; m_vecColour.z = 255; break; } m_fSpeed = random(0.1, 2 + 2 * fScale); m_fWidth = (int)random(1, 5 + 5 * fScale); m_fHeight = (int)random(1, 5 + 5 * fScale); m_iMode = (int)random(0,2); } void Draw() { if (!m_bIsActive) { float fFreq = constrain(fft.getAvg(m_iFreq) * fEnergyScale, 0, 1); if (fFreq > fTriggerEnergy) { Start((fFreq - fTriggerEnergy) * (1 / fTriggerEnergy)); } } else { // Move m_vecPos.x += m_fSpeed; if (m_vecPos.x > fMaxPos) { m_bIsActive = false; } // Colour float fRGB; if (m_vecPos.x < fColourFadeDepth) { fRGB = 1; } else { fRGB = 1 - ((m_vecPos.x - fColourFadeDepth) / (fMaxPos - fColourFadeDepth)); } fRGB *= 1 - (( m_vecPos.z / fMaxDepthOffset) * 0.75); fill(m_vecColour.x * fRGB, m_vecColour.y * fRGB, m_vecColour.z * fRGB); stroke(m_vecColour.x * fRGB * 5, m_vecColour.y * fRGB * 5, m_vecColour.z * fRGB * 5); // Position and draw pushMatrix(); if (m_iMode == 0) { rotateY(PI/4); translate(m_vecPos.x,m_vecPos.y,-m_vecPos.z); } else { rotateY(-PI/4); translate(-m_vecPos.x,m_vecPos.y,-m_vecPos.z); } rect(0, 0, m_fWidth, m_fHeight); popMatrix(); } } int m_iFreq; boolean m_bIsActive; PVector m_vecPos; PVector m_vecColour; float m_fSpeed; float m_fWidth, m_fHeight; int m_iMode; }