diff options
| author | Tim Redfern <tim@gray.(none)> | 2012-11-01 21:10:31 +0000 |
|---|---|---|
| committer | Tim Redfern <tim@gray.(none)> | 2012-11-01 21:10:31 +0000 |
| commit | c31a609399c2e05a50a5df8be10049903521c9e7 (patch) | |
| tree | 246c2c9a67ad0fc8b7473006d0763ab8bbf22675 /vfg/src | |
initial commit
Diffstat (limited to 'vfg/src')
| -rwxr-xr-x | vfg/src/main.cpp | 16 | ||||
| -rwxr-xr-x | vfg/src/music.cpp | 91 | ||||
| -rwxr-xr-x | vfg/src/music.h | 55 | ||||
| -rwxr-xr-x | vfg/src/testApp.cpp | 64 | ||||
| -rwxr-xr-x | vfg/src/testApp.h | 56 |
5 files changed, 282 insertions, 0 deletions
diff --git a/vfg/src/main.cpp b/vfg/src/main.cpp new file mode 100755 index 0000000..6a32c6a --- /dev/null +++ b/vfg/src/main.cpp @@ -0,0 +1,16 @@ +#include "ofMain.h" +#include "testApp.h" +#include "ofAppGlutWindow.h" + +//======================================================================== +int main( ){ + + ofAppGlutWindow window; + ofSetupOpenGL(&window, 1024,768, OF_WINDOW); // <-------- setup the GL context + + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + ofRunApp( new testApp()); + +} diff --git a/vfg/src/music.cpp b/vfg/src/music.cpp new file mode 100755 index 0000000..82e953e --- /dev/null +++ b/vfg/src/music.cpp @@ -0,0 +1,91 @@ +#include "music.h"
+
+//event times & durations are absolute integer milliseconds
+
+note::note(int n,int v,int d){
+ num=n;
+ velocity=v;
+ duration=d;
+}
+void musicscore::parseMidi(string filename){
+ // millis = 60000 / (BPM * PPQ)
+ // BPM = 60000000 / MQPN (last 3 bytes of midi tempoSet)
+ // http://www.lastrayofhope.com/2009/12/23/midi-delta-time-ticks-to-seconds/
+ // presume no change in time signature?
+
+ //2 passes:: extract notes & set abs times, then scan for + + float wt=ofGetElapsedTimef();
+
+ float BPM=120.0f;
+ //input:: MPQN :: default 500000
+ float MPQN=60000000.0f/BPM;
+ //unknown:: ticks per quarter note
+ int TPQN=96;
+ //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 + + map<int,note*> events;
+
+ if( !XML.loadFile(filename) ){
+ printf("unable to load %s check data/ folder\n",filename.c_str());
+ }else{
+ if(XML.pushTag("MidiFile")) {
+ for (int i=0;i<XML.getNumTags("TrackChunk");i++) {
+ XML.pushTag("TrackChunk",i);
+ for (int i=0;i<XML.getNumTags("Event");i++) {
+ time+=(SPT*XML.getAttribute("Event", "DeltaTimeTicks",0,i));
+ if (XML.getAttribute("Event", "Label","",i)=="TempoSet") {
+ string data=XML.getAttribute("Event", "Data","",i);
+ char* endptr;
+ int d1=strtoul(data.substr(6,2).c_str(),&endptr,16);
+ int d2=strtoul(data.substr(9,2).c_str(),&endptr,16);
+ int d3=strtoul(data.substr(12,2).c_str(),&endptr,16);
+ int MPQN=(d1<<16)+(d2<<8)+d3;
+ SPT =(MPQN/1000000.0f)/TPQN;
+ //printf("Tempo change: seconds per tick now: %f\n",SPT);
+ }
+ if (XML.getAttribute("Event", "Label","",i)=="NoteOn"||XML.getAttribute("Event", "Label","",i)=="NoteOff") {
+ string data=XML.getAttribute("Event", "Data","",i);
+ char* endptr;
+ int d1=strtoul(data.substr(0,2).c_str(),&endptr,16);
+ int d2=strtoul(data.substr(3,2).c_str(),&endptr,16);
+ int id=strtoul(XML.getAttribute("Event", "Id","",i).c_str(),&endptr,16);
+ if (id==128||id==144) events[(int)(time*1000.0f)]=new note(d1,d2,id); //noteon/off
+ }
+ }
+ XML.popTag();
+ }
+
+ }
+ XML.popTag();
+ } + //iterate events and compute durations now the absolute times are established: extract to notes + map<int,note*>::iterator iter1; + map<int,note*>::iterator iter2; + + for (iter1 = events.begin(); iter1 != events.end(); ++iter1) { + if (iter1->second->duration==144) { + 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; + } + } + } + }
+ printf("processed %s: %i notes in %f seconds\n",filename.c_str(),notes.size(),ofGetElapsedTimef()-wt);
+}
+
+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
+} diff --git a/vfg/src/music.h b/vfg/src/music.h new file mode 100755 index 0000000..145538e --- /dev/null +++ b/vfg/src/music.h @@ -0,0 +1,55 @@ +#pragma once
+
+#include "ofMain.h"
+#include "ofxXmlSettings.h"
+
+//event times are absolute integer milliseconds
+
+class note {
+ public:
+ note(int n,int v,int d=0);
+ int num;
+ int velocity;
+ int duration; //may be needed another time?
+};
+
+class score {
+ //implements basics of timelime, loading from xml, time, checking
+ public:
+
+ protected:
+ ofxXmlSettings XML;
+};
+
+class lyricscore: public score {
+ //draws lyrics to screen for a certain time
+ public:
+};
+
+class musicscore: public score {
+ //draws notes to screen for a certain time and certain parameters, checks when they become ready
+ //how will it be played dictates how the data is stored
+ //play : start from beginning, schedule event at next delta
+ //end : clean up and start again
+ //you can set position of sound file, it will seek. will we want ffwd at any stage
+ //when it comes to drawing, we will want to repeatedly retrieve notes in a range of times
+ //lower_bound and upper_bound
+ public:
+ void parseMidi(string filename);
+ private:
+ map<int,note*> notes;
+};
+
+class song {
+ public:
+ song(string backfile,string melfile,string musfile);
+ private:
+ ofSoundPlayer backing;
+ ofSoundPlayer melody;
+ lyricscore lyrics;
+ musicscore notes;
+ int bpm;
+};
+
+
+
diff --git a/vfg/src/testApp.cpp b/vfg/src/testApp.cpp new file mode 100755 index 0000000..7710326 --- /dev/null +++ b/vfg/src/testApp.cpp @@ -0,0 +1,64 @@ +#include "testApp.h" + +//-------------------------------------------------------------- +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"); +} + +void testApp::exit(){ + delete testsong; +} + +//-------------------------------------------------------------- +void testApp::update(){ +} + +//-------------------------------------------------------------- +void testApp::draw(){ + +} + +//-------------------------------------------------------------- +void testApp::keyPressed(int key){ + +} + +//-------------------------------------------------------------- +void testApp::keyReleased(int key){ + +} + +//-------------------------------------------------------------- +void testApp::mouseMoved(int x, int y ){ + +} + +//-------------------------------------------------------------- +void testApp::mouseDragged(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::mousePressed(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::mouseReleased(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::windowResized(int w, int h){ + +} + +//-------------------------------------------------------------- +void testApp::gotMessage(ofMessage msg){ + +} + +//-------------------------------------------------------------- +void testApp::dragEvent(ofDragInfo dragInfo){ + +} diff --git a/vfg/src/testApp.h b/vfg/src/testApp.h new file mode 100755 index 0000000..94691a5 --- /dev/null +++ b/vfg/src/testApp.h @@ -0,0 +1,56 @@ +#pragma once + +#include "ofMain.h" +#include "music.h" + +/* +this library? + +https://github.com/micknoise/Maximilian + +Maximilian is an audio synthesis and signal processing library written in C++. It's cross-platform compatible with MacOS, Windows, Linux and IOS systems. The main features are: + +- sample playback, recording and looping +- read from WAV and OGG files. +- a selection of oscillators and filters +- enveloping +- multichannel mixing for 1, 2, 4 and 8 channel setups +- controller mapping functions +- effects including delay, distortion, chorus, flanging +- granular synthesis, including time and pitch stretching +- atom synthesis +- realtime music information retrieval functions: spectrum analysis, spectral features, octave analysis, and MFCCs +- example projects for Windows and MacOS, using command line and OpenFrameworks environments + +*/ + +class game { + vector<song*> songs; +}; + +class testApp : public ofBaseApp{ + + public: + void setup(); + void update(); + void draw(); + void exit(); + + void keyPressed (int key); + void keyReleased(int key); + void mouseMoved(int x, int y ); + void mouseDragged(int x, int y, int button); + void mousePressed(int x, int y, int button); + void mouseReleased(int x, int y, int button); + void windowResized(int w, int h); + void dragEvent(ofDragInfo dragInfo); + void gotMessage(ofMessage msg); + + song* testsong; + +}; + + + + + |
