From 2ea0f60bb2ca981ff1e72575dd92c4ab906fd1c7 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Fri, 2 Nov 2012 17:19:17 +0000 Subject: syncing and drawing notes --- vfg/src/music.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 93 insertions(+), 16 deletions(-) (limited to 'vfg/src/music.cpp') diff --git a/vfg/src/music.cpp b/vfg/src/music.cpp index 82e953e..74c5c0b 100755 --- a/vfg/src/music.cpp +++ b/vfg/src/music.cpp @@ -1,12 +1,19 @@ #include "music.h" //event times & durations are absolute integer milliseconds - +//--------------------------------------------------------------------------------------------------------------------------------------------- note::note(int n,int v,int d){ num=n; velocity=v; duration=d; } +//--------------------------------------------------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------------------------------------------------- +musicscore::musicscore() { + timeframe=10000; + flake.loadImage("flake.png"); + flake.setAnchorPercent(0.5,0.5); +} void musicscore::parseMidi(string filename){ // millis = 60000 / (BPM * PPQ) // BPM = 60000000 / MQPN (last 3 bytes of midi tempoSet) @@ -21,11 +28,11 @@ void musicscore::parseMidi(string filename){ //input:: MPQN :: default 500000 float MPQN=60000000.0f/BPM; //unknown:: ticks per quarter note - int TPQN=96; + int TPQN=480; //want:: seconds per tick in float float SPT =(MPQN/1000000.0f)/TPQN; - float time=0; //counts up in float seconds but converts to millis for map index + float time=0; //counts up in float seconds to avoid rounding errors but converts to millis for map index map events; @@ -65,27 +72,97 @@ void musicscore::parseMidi(string filename){ //iterate events and compute durations now the absolute times are established: extract to notes map::iterator iter1; map::iterator iter2; - + int note; + bool started=false; for (iter1 = events.begin(); iter1 != events.end(); ++iter1) { - if (iter1->second->duration==144) { + if (iter1->second->duration==144) { + if (!started) { + note=iter1->second->num; + started=true; + } iter1->second->duration=0; iter2=iter1; while (++iter2 != events.end()) { - if ((iter1->second->num==iter2->second->num)&&(iter2->second->duration==128)) { - iter1->second->duration=iter2->first-iter1->first; - notes[iter1->first]=iter1->second; - //printf("%i: noteon %i %i\n",iter1->first,iter1->second->num,iter1->second->duration); - break; - } - } + if ((iter1->second->num==iter2->second->num)&&(iter2->second->duration==128)) { + iter1->second->duration=iter2->first-iter1->first; + iter1->second->updown=iter1->second->numsecond->num==note?0:1; + note=iter1->second->num; + notes[iter1->first]=iter1->second; + printf("%i: noteon %i %i %i\n",iter1->first,iter1->second->num,iter1->second->duration,iter1->second->updown); + break; + } + } } - } - printf("processed %s: %i notes in %f seconds\n",filename.c_str(),notes.size(),ofGetElapsedTimef()-wt); -} + } + iter1 = notes.end(); + iter1--; + printf("processed %s: length %f, %i notes in %f seconds\n",filename.c_str(),((float)(iter1->first+iter1->second->duration)*.001f),notes.size(),ofGetElapsedTimef()-wt); + //decimate notes to generate flakes that can be interacted with + +} +void musicscore::setTimeframe(int millis) {timeframe=millis;} +void musicscore::draw() { + ofEnableAlphaBlending(); + int scoreStart=ofGetElapsedTimeMillis()-startTime; + int scoreEnd=scoreStart+timeframe; + //temporary drawing method 46h - 52h + int numnotes=16; + int firstnote=70; + float widthStep=((float)ofGetWidth())/numnotes; + float heightStep=((float)ofGetHeight())/timeframe; + map::iterator iter; + for (iter = notes.lower_bound(scoreStart); iter != notes.upper_bound(scoreEnd); ++iter) { + int thisnote=iter->second->num-firstnote; + int thisstart=iter->first-scoreStart; + int thislength=iter->second->duration; + ofSetColor(ofColor::fromHsb(((float)thisnote*255)/numnotes,200,100)); + ofRect(thisnote*widthStep,ofGetHeight()-(thisstart*heightStep),widthStep,-(thislength*heightStep)); + ofSetColor(ofColor::fromHsb(((float)thisnote*255)/numnotes,200,255)); + + //different methods for generating flakes + //ideally theres a variable clumping factor, this means pre-processing the flakes though + + //flake.draw((thisnote+0.5f)*widthStep,ofGetHeight()-(thisstart*heightStep)); + //flake.draw((iter->second->updown*ofGetWidth()*0.33)+(ofGetWidth()*0.5),ofGetHeight()-(thisstart*heightStep)); + flake.draw((((thisnote/5)*5)+3.5f)*widthStep,ofGetHeight()-(thisstart*heightStep)); + } + ofDisableAlphaBlending(); +} +//--------------------------------------------------------------------------------------------------------------------------------------------- song::song(string backfile,string melfile,string notefile) { backing.loadSound(backfile); melody.loadSound(melfile); notes.parseMidi(notefile); - bpm=bpm; //can be used to set tempo eventually? keeps everything simple to do it this way + isPlaying=false; +} +void song::setTimeframe(int millis) {notes.setTimeframe(millis);} +void song::play() { + backing.play(); + melody.play(); + startTime=ofGetElapsedTimeMillis(); + notes.startTime=startTime; + isPlaying=true; +} +void song::stop() { + backing.stop(); + melody.stop(); + isPlaying=false; +} +void song::preRoll(long preroll) { + startTime=ofGetElapsedTimeMillis()+preroll; + notes.startTime=startTime; + isPreroll=true; + isPlaying=true; +} +void song::draw(){ + //how to deal with end/ track length/ part of game? + if (isPreroll) { + if (startTime