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/bin/data/flake.png | Bin 0 -> 4570 bytes vfg/src/music.cpp | 109 +++++++++++++++++++++++++++++++++++++++++-------- vfg/src/music.h | 37 ++++++++++------- vfg/src/testApp.cpp | 11 ++++- vfg/vfg.cbp | 76 ++++++++++++++++++---------------- vfg/vfg.layout | 12 ++++++ 6 files changed, 178 insertions(+), 67 deletions(-) create mode 100755 vfg/bin/data/flake.png (limited to 'vfg') diff --git a/vfg/bin/data/flake.png b/vfg/bin/data/flake.png new file mode 100755 index 0000000..b609837 Binary files /dev/null and b/vfg/bin/data/flake.png differ 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 notes; + int timeframe; + ofImage flake; }; - +//--------------------------------------------------------------------------------------------------------------------------------------------- class song { public: song(string backfile,string melfile,string musfile); + void play(); + void stop(); + void preRoll(long preroll); + void setTimeframe(int millis); + void draw(); + bool isPlaying; private: ofSoundPlayer backing; ofSoundPlayer melody; lyricscore lyrics; musicscore notes; - int bpm; + long startTime; + bool isPreroll; }; - +//--------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/vfg/src/testApp.cpp b/vfg/src/testApp.cpp index 7710326..675baef 100755 --- a/vfg/src/testApp.cpp +++ b/vfg/src/testApp.cpp @@ -3,6 +3,11 @@ //-------------------------------------------------------------- void testApp::setup(){ testsong=new song("VODA_MUS_DeckTheHalls-Backing_v.1.3.mp3","VODA_MUS_DeckTheHalls-Melody_v.1.3.mp3","MIDI_DeckTheHalls_Test.1.3.xml"); + testsong->setTimeframe(1500); + testsong->preRoll(250); + + ofSetBackgroundAuto(false); + ofBackground(0,0,0); } void testApp::exit(){ @@ -15,7 +20,11 @@ void testApp::update(){ //-------------------------------------------------------------- void testApp::draw(){ - + ofEnableAlphaBlending(); + //ofBackground(0,0,0,0.1); + ofSetColor(0,0,0,100); + ofRect(0,0,ofGetWidth(),ofGetHeight()); + if (testsong->isPlaying) testsong->draw(); } //-------------------------------------------------------------- diff --git a/vfg/vfg.cbp b/vfg/vfg.cbp index f982225..18e5af4 100755 --- a/vfg/vfg.cbp +++ b/vfg/vfg.cbp @@ -1,4 +1,4 @@ - + @@ -6,7 +6,7 @@ diff --git a/vfg/vfg.layout b/vfg/vfg.layout index 1053280..9b5ee28 100644 --- a/vfg/vfg.layout +++ b/vfg/vfg.layout @@ -1,4 +1,16 @@ + + + + + + + + + + + + -- cgit v1.2.3