From: Thomas Pietrzak Date: Thu, 7 Apr 2011 22:07:34 +0000 (+0000) Subject: Manage metronomes, uint32 timestamps X-Git-Url: https://git.thomaspietrzak.com/?a=commitdiff_plain;h=ca395a50867250c364dc6401715c6dce023fba83;p=hapticmetronome.git Manage metronomes, uint32 timestamps git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@9 47cf9a05-e0a8-4ed5-9e9b-101a649bc004 --- diff --git a/Haptic Metronome/Haptic Metronome.suo b/Haptic Metronome/Haptic Metronome.suo index 6397c4f..51f3482 100644 Binary files a/Haptic Metronome/Haptic Metronome.suo and b/Haptic Metronome/Haptic Metronome.suo differ diff --git a/include/Config.hpp b/include/Config.hpp index bd615a6..d208ec1 100644 --- a/include/Config.hpp +++ b/include/Config.hpp @@ -26,21 +26,22 @@ using namespace std; class Config { public: - Config(double position=0, double end=0, uint32_t time=0, uint32_t ticks=0,bool a=false, bool b=false, bool c=false, bool d=false, bool e=false) - :_position(position), _end(end), _time(time), _ticks(ticks), _a(a), _b(b), _c(c), _d(d), _e(e){} + Config(uint32_t timestamp=0, uint32_t end=0, uint32_t time=0, uint32_t ticks=0, + bool a=false, bool b=false, bool c=false, bool d=false, bool e=false); - Config(const Config &cf):_position(cf._position), _end(cf._end), _time(cf._time), _ticks(cf._ticks), _a(cf._a), _b(cf._b), _c(cf._c), _d(cf._d), _e(cf._e){} - ~Config(){} + Config(const Config &cf); + + ~Config(); void addKey(keys k); void remKey(keys k); void setKeys(bool a, bool b, bool c, bool d, bool e); - void setPosition(double p) { _position = p; } - double getPosition() const { return _position; } + void setTimestamp(uint32_t t) { _timestamp = t; } + uint32_t getTimestamp() const { return _timestamp; } - void setEnd(double d) { _end = d; } - double getEnd() const { return _end; } + void setEndTimestamp(uint32_t t) { _endtimestamp = t; } + uint32_t getEndTimestamp() const { return _endtimestamp; } void setTime(uint32_t t) { _time = t; } uint32_t getTime() const { return _time; } @@ -53,12 +54,12 @@ class Config Config &operator =(const Config&cfg); - friend ostream& operator <<(ostream &os,const Config &c); + friend ostream& operator << (ostream &os, const Config &c); bool isNone() const { return !(_a || _b || _c || _d || _e ); } private: - double _position, _end; + uint32_t _timestamp, _endtimestamp; uint32_t _time, _ticks; bool _a, _b, _c, _d, _e; }; diff --git a/include/Metronome.hpp b/include/Metronome.hpp new file mode 100644 index 0000000..1ec54d5 --- /dev/null +++ b/include/Metronome.hpp @@ -0,0 +1,26 @@ +#ifndef _METRONOME_ +#define _METRONOME_ + +#include "Track.hpp" +#include + +class Metronome +{ + public: + Metronome(Track *track, uint32_t nbbeats=4, uint32_t tempo=0, bool activated=false); + virtual ~Metronome(){} + + virtual void setActive(bool activated) { _activated = activated; } + virtual void setTempo(uint32_t tempo) { _tempo = tempo; } + virtual void setNbBeats(uint32_t nbbeats) {_nbbeats = nbbeats; } + + virtual void run()=0; + + protected: + uint32_t _nbbeats; + uint32_t _tempo; + bool _activated; + Track *_track; +}; + +#endif diff --git a/include/MetronomeAudio.hpp b/include/MetronomeAudio.hpp new file mode 100644 index 0000000..a652b3d --- /dev/null +++ b/include/MetronomeAudio.hpp @@ -0,0 +1,29 @@ +#ifndef _METRONOMEAUDIO_ +#define _METRONOMEAUDIO_ + +#include "Metronome.hpp" + +#ifdef WIN32 +#include +#include +#include +#else +#include +#include +#endif + +class MetronomeAudio : public Metronome +{ + public: + MetronomeAudio(Track *track, uint32_t nbbeats=4, uint32_t tempo=0, bool activated=true); + + ~MetronomeAudio(); + + void run(); + + private: + static int thread_func(void *unused); + SDL_Thread *thread; +}; + +#endif \ No newline at end of file diff --git a/include/MetronomeHaptic.hpp b/include/MetronomeHaptic.hpp new file mode 100644 index 0000000..92db869 --- /dev/null +++ b/include/MetronomeHaptic.hpp @@ -0,0 +1,35 @@ +#ifndef _METRONOMEHAPTIC_ +#define _METRONOMEHAPTIC_ + +#include "Metronome.hpp" + +#ifdef WIN32 +#include +#include +#include +#else +#include +#include +#endif + +#include "Serial.hpp" + +class MetronomeHaptic : public Metronome +{ + public: + MetronomeHaptic(Track *track, uint32_t nbbeats=4, uint32_t tempo=0, bool activated=true); + + ~MetronomeHaptic(); + + void setTempo(uint32_t tempo); + void setNbBeats(uint32_t nbbeats); + + void run(); + + private: + static int thread_func(void *unused); + SDL_Thread *thread; + Serial *_comport; +}; + +#endif \ No newline at end of file diff --git a/include/PaintGame.h b/include/PaintGame.h index a4557cd..1a89b5c 100644 --- a/include/PaintGame.h +++ b/include/PaintGame.h @@ -12,27 +12,27 @@ void init(); void initPaint(); -void draw(Track &t, float currenttime, char diff); +void draw(Track &t, uint32_t currenttime, char diff); void drawCube(float pos, float size, float colorx, float colory, float colorz); void drawLong(float pos, float size, float length, float colorx, float colory, float colorz); -void handleKeyOn(keys k, float currenttime); -void handleKeyOff(keys k, float currenttime); -void handleKeys(bool a, bool b, bool c, bool d, bool e, float currenttime); -void handleStrokeOn(float currenttime); -void handleStrokeOff(float currenttime); -bool processEvents(float currenttime); +void handleKeyOn(keys k, uint32_t currenttime); +void handleKeyOff(keys k, uint32_t currenttime); +void handleKeys(bool a, bool b, bool c, bool d, bool e, uint32_t currenttime); +void handleStrokeOn(uint32_t currenttime); +void handleStrokeOff(uint32_t currenttime); +bool processEvents(uint32_t currenttime); class MyWiimote: public Wiimote { public: MyWiimote():Wiimote(1){} - void handleStrumOn(float currenttime) { handleStrokeOn(currenttime); } - void handleStrumOff(float currenttime) { handleStrokeOff(currenttime); } - void handleButtonOn(int k, float currenttime) { handleKeyOn(keys(k), currenttime); } - void handleButtonOff(int k, float currenttime) { handleKeyOff(keys(k), currenttime); } - void handleButtons(bool a, bool b, bool c, bool d, bool e, float currenttime) { handleKeys(a, b, c, d, e, currenttime); } + void handleStrumOn(uint32_t currenttime) { handleStrokeOn(currenttime); } + void handleStrumOff(uint32_t currenttime) { handleStrokeOff(currenttime); } + void handleButtonOn(int k, uint32_t currenttime) { handleKeyOn(keys(k), currenttime); } + void handleButtonOff(int k, uint32_t currenttime) { handleKeyOff(keys(k), currenttime); } + void handleButtons(bool a, bool b, bool c, bool d, bool e, uint32_t currenttime) { handleKeys(a, b, c, d, e, currenttime); } }; #endif diff --git a/include/Serial.hpp b/include/Serial.hpp new file mode 100644 index 0000000..096fe6f --- /dev/null +++ b/include/Serial.hpp @@ -0,0 +1,35 @@ +#ifndef _SERIAL_ +#define _SERIAL_ + +#define ARDUINO_WAIT_TIME 500 + +class Serial +{ + public: + //Initialize Serial communication with the given COM port + Serial(char *portName); + + //Close the connection + //NOTA: for some reason you can't connect again before exiting + //the program and running it again + virtual ~Serial(); + + //Read data in a buffer, if nbChar is greater than the + //maximum number of bytes available, it will return only the + //bytes available. The function return -1 when nothing could + //be read, the number of bytes actually read. + virtual int ReadData(char *buffer, unsigned int nbChar)=0; + + //Writes data from a buffer through the Serial connection + //return true on success. + virtual bool WriteData(char *buffer, unsigned int nbChar)=0; + + //Check if we are actually connected + bool IsConnected() { return _connected; } + + protected: + //Connection status + bool _connected; +}; + +#endif diff --git a/include/SerialWindows.hpp b/include/SerialWindows.hpp new file mode 100644 index 0000000..3b99741 --- /dev/null +++ b/include/SerialWindows.hpp @@ -0,0 +1,35 @@ +#ifndef _SERIALWINDOWS_ +#define _SERIALWINDOWS_ + +#include "Serial.hpp" + +#include + +class SerialWindows : public Serial +{ + public: + //Initialize Serial communication with the given COM port + SerialWindows(char *portName); + //Close the connection + //NOTA: for some reason you can't connect again before exiting + //the program and running it again + ~SerialWindows(); + //Read data in a buffer, if nbChar is greater than the + //maximum number of bytes available, it will return only the + //bytes available. The function return -1 when nothing could + //be read, the number of bytes actually read. + int ReadData(char *buffer, unsigned int nbChar); + //Writes data from a buffer through the Serial connection + //return true on success. + bool WriteData(char *buffer, unsigned int nbChar); + + + private: + //Serial comm handler + HANDLE _hSerial; + //Get various information about the connection + COMSTAT _status; + //Keep track of last error + DWORD _errors; +}; +#endif diff --git a/include/Track.hpp b/include/Track.hpp index 501e361..4ecfd8d 100644 --- a/include/Track.hpp +++ b/include/Track.hpp @@ -22,6 +22,19 @@ using namespace std; #include "Pair.hpp" //#include "Metronome.hpp" +#define BIPTICK(X) ((X).getX()) +#define BIPTIMESTAMP(X) ((X).getY()) + +#define NOTETICK(X) ((X).first) +#define ISLONGNOTE(X) ((X).second.getTicks() > 240) +#define NOTETIMESTAMP(X) ((X).second.getTimestamp()) +#define NOTEENDTIMESTAMP(X) ((X).second.getEndTimestamp()) +#define NOTEDURATION(X) (((X).second.getEndTimestamp())-((X).second.getTimestamp())) + +#define TICK(X) ((X).first) +#define TIMESTAMP(X) ((X).second.getX()) +#define VALUE(X) ((X).second.getY()) + class Track { public: @@ -32,22 +45,22 @@ class Track void addKey(uint32_t time, uint8_t note); void remKey(uint32_t time, uint8_t note); - void addTempo(uint32_t tick, float timestamp, uint32_t t) { _tempo[tick] = Pair(timestamp, t); } - void addTimesignature(uint32_t tick, float timestamp, uint32_t t) { _timesignatures[tick] = Pair(timestamp, t); } - map > *getTempos() { return &_tempo; } - map > *getTimeSignatures() { return &_timesignatures; } + void addTempo(uint32_t tick, uint32_t timestamp, uint32_t t) { _tempo[tick] = Pair(timestamp, t); } + void addTimesignature(uint32_t tick, uint32_t timestamp, uint32_t t) { _timesignatures[tick] = Pair(timestamp, t); } + map > *getTempos() { return &_tempo; } + map > *getTimeSignatures() { return &_timesignatures; } // int getTempo() const { return _currenttempo; } // void setTempo(uint32 t) { _currenttempo = t; } // uint32 beatsToTicks(uint32 time) { return (time * _currenttempo * 480) / 60000.0; } - uint32_t beatsToTicks(uint32_t time, uint32_t tempo) { return uint32_t((time * tempo * 480) / 60000.0); } + uint32_t beatsToTicks(uint32_t time, uint32_t tempo) { return (time * tempo * 480) / 60000; } uint32_t ticksToBeats(uint32_t time) { return 60000000 / time; } void displayTracks(); - void drawFrets(float postime) const; - void drawNotes(float postime, uint8_t difficulty) const; + void drawFrets(uint32_t postime) const; + void drawNotes(uint32_t postime, uint8_t difficulty) const; // void checkMetronome(float postime, Metronome *m) const; uint32_t getNbNotes(uint32_t k) const { return _nbnotes[k]; } @@ -58,13 +71,11 @@ class Track uint32_t getEndOfTrack() const { return _trackSize; } Config getNote(uint32_t pos, uint8_t difficulty); - uint32_t getTempo(uint32_t pos); - uint32_t getTimeSignature(uint32_t pos); - uint32_t getTempo(float pos); - uint32_t getTimeSignature(float pos); + uint32_t getTempo(uint32_t tick); + uint32_t getTimeSignature(uint32_t tick); - list > * getBips() { return &_bips; } - void addBip(uint32_t tick, float timestamp) { _bips.push_back(Pair(tick, timestamp)); } + list > * getBips() { return &_bips; } + void addBip(uint32_t tick, uint32_t timestamp) { _bips.push_back(Pair(tick, timestamp)); } //void computeBips(); @@ -73,11 +84,11 @@ class Track private: //notes : position ; configs map _notes[NBDIFFICULTIES]; - map > _tempo; - map > _timesignatures; + map > _tempo; + map > _timesignatures; -// private: - list > _bips; + // (beat, timestamp) + list > _bips; Config _currentconfig[NBDIFFICULTIES]; diff --git a/include/Wiimote.hpp b/include/Wiimote.hpp index 4d5ad9c..9802af5 100644 --- a/include/Wiimote.hpp +++ b/include/Wiimote.hpp @@ -3,6 +3,8 @@ #ifndef WIN32 #include +#else + #include #endif #include @@ -14,18 +16,18 @@ class Wiimote{ public: Wiimote(int nb=1); - void handleEvents(float currenttime); + void handleEvents(uint32_t currenttime); void vibration(int wiimote, int time); - virtual void handleStrumOn(float currenttime) = 0; - virtual void handleStrumOff(float currenttime) = 0; - virtual void handleButtonOn(int k, float currenttime) = 0; - virtual void handleButtonOff(int k, float currenttime) = 0; - virtual void handleButtons(bool a, bool b, bool c, bool d, bool e, float currenttime) = 0; + virtual void handleStrumOn(uint32_t currenttime) = 0; + virtual void handleStrumOff(uint32_t currenttime) = 0; + virtual void handleButtonOn(int k, uint32_t currenttime) = 0; + virtual void handleButtonOff(int k, uint32_t currenttime) = 0; + virtual void handleButtons(bool a, bool b, bool c, bool d, bool e, uint32_t currenttime) = 0; private: - void handleKey(guitar_hero_3_t* gh3, int key, int button, float currenttime); + void handleKey(guitar_hero_3_t* gh3, int key, int button, uint32_t currenttime); wiimote **_wiimotes; int _nb; bool _strumstate, _keystate[5]; diff --git a/src/Config.cpp b/src/Config.cpp index b8df6d7..ebe8ea8 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -3,6 +3,22 @@ #include "PaintGame.h" +Config::Config(uint32_t timestamp, uint32_t endtimestamp, uint32_t time, uint32_t ticks, bool a, bool b, bool c, bool d, bool e) +:_timestamp(timestamp), _endtimestamp(endtimestamp), _time(time), _ticks(ticks), + _a(a), _b(b), _c(c), _d(d), _e(e) +{ +} + +Config::Config(const Config &cf) +:_timestamp(cf._timestamp), _endtimestamp(cf._endtimestamp), _time(cf._time), _ticks(cf._ticks), + _a(cf._a), _b(cf._b), _c(cf._c), _d(cf._d), _e(cf._e) +{ +} + +Config::~Config() +{ +} + void Config::addKey(keys k) { switch(k) @@ -60,7 +76,7 @@ void Config::display() const { if (_ticks > 240) { - float notelength = static_cast(_end - _position); + float notelength = static_cast(_endtimestamp - _timestamp); if (_a) drawLong(-2*NOTEDIST, LONGSIZE, notelength, COLOR_GREEN); if (_b) @@ -89,10 +105,10 @@ void Config::log(const String &type, FILE *file) const { if (!file) return; - fprintf(file, "%s;%d;%d;%d;%d;%d;%f;%f;%d;%d\n", type.c_str(), _a, _b, _c, _d, _e, _position, _end, _time, _ticks); + fprintf(file, "%s;%d;%d;%d;%d;%d;%d;%d;%d;%d\n", type.c_str(), _a, _b, _c, _d, _e, _timestamp, _endtimestamp, _time, _ticks); } -Config &Config::operator =(const Config&cfg) +Config &Config::operator =(const Config &cfg) { if (&cfg != this) { @@ -101,8 +117,8 @@ Config &Config::operator =(const Config&cfg) _c = cfg._c; _d = cfg._d; _e = cfg._e; - _position = cfg._position; - _end = cfg._end; + _timestamp = cfg._timestamp; + _endtimestamp = cfg._endtimestamp; _time = cfg._time; _ticks = cfg._ticks; } @@ -132,6 +148,6 @@ ostream& operator <<(ostream &os,const Config &c) os << "\033[0;33mO\033[0m"; else os << "\033[0;33m.\033[0m"; - os << " " << c._position << " " << c._end; + os << " " << c._timestamp << " " << c._endtimestamp; return os; } diff --git a/src/MIDIReader.cpp b/src/MIDIReader.cpp index 4073676..5783ded 100644 --- a/src/MIDIReader.cpp +++ b/src/MIDIReader.cpp @@ -131,11 +131,11 @@ void MIDIReader::readTrack(Track &tr, bool addbips) bool end = false; uint8_t oldeventandchannel = 0; uint32_t ticks = 0; - float timestamp = 0; + uint32_t timestamp = 0; uint32_t currenttempo = 60000000/120; if (addbips) - tr.addBip(0, 0.0); + tr.addBip(0, 0); // Track example; @@ -153,23 +153,23 @@ void MIDIReader::readTrack(Track &tr, bool addbips) { uint32_t lastbiptick = 0; lastbiptick = tr.getBips()->back().getX(); - float temptimestamp = timestamp; + uint32_t temptimestamp = timestamp; //manage 1st bip, taking into account the time elapsed since the last event if (lastbiptick > 0 && ticks >= lastbiptick + 480) { lastbiptick += 480; - temptimestamp = timestamp + (lastbiptick - ticks + delta) * (currenttempo / 480000.0f); + temptimestamp = timestamp + (lastbiptick - ticks + delta) * (currenttempo / 480000); tr.addBip(lastbiptick, temptimestamp); } //add bips with the current tempo for (uint32_t i = lastbiptick + 480 ; i < ticks ; i += 480 ) { - temptimestamp += currenttempo / 1000.0f; + temptimestamp += currenttempo / 1000; tr.addBip(i, temptimestamp); } } - timestamp += delta * (currenttempo / 480000.0f); + timestamp += static_cast(delta * (currenttempo / 480000.0)); uint8_t eventandchannel, tempevt; // 4 bits for event type, and 4 others for the channel @@ -245,17 +245,17 @@ void MIDIReader::readTrack(Track &tr, bool addbips) end = true; break; case 0x51: - tempo = ((int(data[2]) << 16) + (int(data[1]) << 8) + int(data[0])); + tempo = ((uint32_t(data[2] & 0x000000ff) << 16) + (uint32_t(data[1] & 0x000000ff) << 8) + uint32_t(data[0] & 0x000000ff)); cout << "Tempo at " << ticks << " : x=" << tempo << "=" << 60000000 / tempo << "bpm" << endl; currenttempo = tempo; tr.addTempo(ticks, timestamp, tempo); break; case 0x58: - cout << "Time signature at " << ticks<< " : " << int(data[3]) << "|" << int(pow(float(2), int(data[2]))) << " " << int(data[1]) << " ticks " << int(data[0]) << "x" << endl; - tr.addTimesignature(ticks, timestamp, int(data[3])); + cout << "Time signature at " << ticks<< " : " << uint8_t(data[3]) << "|" << int(pow(float(2), uint8_t(data[2]))) << " " << int(data[1]) << " ticks " << int(data[0]) << "x" << endl; + tr.addTimesignature(ticks, timestamp, uint8_t(data[3])); break; case 0x59: - cout << "Key signature: " << int(data[1]) << " " << int(data[0]) << endl; + cout << "Key signature: " << uint8_t(data[1]) << " " << uint8_t(data[0]) << endl; break; case 0x7F: cout << "Sequencer stuff!" << endl; @@ -346,19 +346,19 @@ void MIDIReader::readTrack(Track &tr, bool addbips) uint32_t lastbiptick = 0; if (!tr.getBips()->empty()) lastbiptick = tr.getBips()->back().getX(); - float temptimestamp = timestamp; + uint32_t temptimestamp = timestamp; //manage 1st bip, taking into account the time elapsed since the last event if (lastbiptick > 0) { lastbiptick += 480; - temptimestamp = timestamp + (lastbiptick - ticks) * (currenttempo / 480000.0f); + temptimestamp = timestamp + static_cast((lastbiptick - ticks) * (currenttempo / 480000.0)); tr.addBip(lastbiptick, temptimestamp); } //add 1000 bips with the current tempo for (uint32_t i = lastbiptick ; i < lastbiptick + 480000 ; i += 480 ) { tr.addBip(i, temptimestamp); - temptimestamp += currenttempo / 1000.0f; + temptimestamp += currenttempo / 1000; } } // tr.displayTracks(); diff --git a/src/Metronome.cpp b/src/Metronome.cpp new file mode 100644 index 0000000..d4f304d --- /dev/null +++ b/src/Metronome.cpp @@ -0,0 +1,6 @@ +#include "Metronome.hpp" + +Metronome::Metronome(Track *track, uint32_t nbbeats, uint32_t tempo, bool activated) +:_track(track), _nbbeats(nbbeats), _tempo(tempo), _activated(activated) +{ +} diff --git a/src/MetronomeAudio.cpp b/src/MetronomeAudio.cpp new file mode 100644 index 0000000..c3fcae2 --- /dev/null +++ b/src/MetronomeAudio.cpp @@ -0,0 +1,92 @@ +#include "MetronomeAudio.hpp" + +#include "Mixer.hpp" + +#ifdef WIN32 +#include +#include +#else +#include +#endif + +MetronomeAudio::MetronomeAudio(Track *track, uint32_t nbbeats, uint32_t tempo, bool activated) +:Metronome(track, nbbeats, tempo, activated), thread(NULL) +{ + Mixer::getInstance()->addSound("bip","bip.ogg"); + Mixer::getInstance()->addSound("bip2","bip2.ogg"); +} + +MetronomeAudio::~MetronomeAudio() +{ + _activated = false; + SDL_WaitThread(thread, NULL); +} + +void MetronomeAudio::run() +{ + thread = SDL_CreateThread(&MetronomeAudio::thread_func, this); +} + +int MetronomeAudio::thread_func(void *obj) +{ + MetronomeAudio *thismetronome = static_cast(obj); + + SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); + + const list > *bips = thismetronome->_track->getBips(); + //const map > *tempo = thismetronome->_track->getTempos(); + const map > *timesignatures = thismetronome->_track->getTimeSignatures(); + static list >::const_iterator cBips = bips->begin(); + //static map >::const_iterator cTempo = tempo->begin(); + static map >::const_iterator cTimesignature = timesignatures->begin(); + + int currentbeat = 0; + +#ifdef WIN32 + struct { int tv_sec, tv_usec; } now, start; + DWORD t = timeGetTime (); + start.tv_sec = t / 1000; + start.tv_usec = (t % 1000) * 1000; +#else + struct timeval now, start; + gettimeofday(&start, NULL); +#endif + uint32_t currenttime = 0; + float lag = 0.0; + + while(thismetronome->_activated) + { +#ifdef WIN32 + t = timeGetTime (); + now.tv_sec = t / 1000; + now.tv_usec = (t % 1000) * 1000; +#else + gettimeofday(&now, NULL); +#endif + uint32_t currenttime = (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec - start.tv_usec) / 1000; + + while (cBips != bips->end() && currenttime >= (*cBips).getY()) + { + if (currentbeat == 0) + Mixer::getInstance()->playSound("bip"); + else + Mixer::getInstance()->playSound("bip2"); + currentbeat = (currentbeat + 1) % thismetronome->_nbbeats; + cBips++; + } + + // on avance tant que les tempos sont dépassées + while (cTimesignature != timesignatures->end() && (*cTimesignature).second.getX() < currenttime) + { + //tempo change + stringstream s; + s << "Time signature change at " << currenttime << " : tick=" << (*cTimesignature).first << " at " << (*cTimesignature).second.getX() << " for " << (*cTimesignature).second.getY() << " beats " << endl; + OutputDebugString(s.str().c_str()); + thismetronome->_nbbeats = (*cTimesignature).second.getY(); + cTimesignature++; + } + + SDL_Delay(5); + } + return 0; +} diff --git a/src/MetronomeHaptic.cpp b/src/MetronomeHaptic.cpp new file mode 100644 index 0000000..c1086b8 --- /dev/null +++ b/src/MetronomeHaptic.cpp @@ -0,0 +1,220 @@ +#include "MetronomeHaptic.hpp" + +#include "Mixer.hpp" + +#ifdef WIN32 +#include +#include +#include "SerialWindows.hpp" +#else +#include +#include "SerialLinux.hpp" +#endif + +#define BEFOREDELAY 20 + +MetronomeHaptic::MetronomeHaptic(Track *track, uint32_t nbbeats, uint32_t tempo, bool activated) +:Metronome(track, nbbeats, tempo, activated), thread(NULL), _comport(new SerialWindows("COM5")) +{ +} + +MetronomeHaptic::~MetronomeHaptic() +{ + _activated = false; + delete _comport; + SDL_WaitThread(thread, NULL); +} + +void MetronomeHaptic::setTempo(uint32_t tempo) +{ + Metronome::setTempo(tempo); + //send info to Serial Port + //char outBuffer[5]; + char outBuffer[5];// = {'T', 'A', 'B', 'C', 'D'}; + memset(outBuffer, 0, 5); + /*sprintf(OUTBUFFER, "T%3d\n", 60000000/tempo);*/ + outBuffer[0] = 'T'; + outBuffer[1] = (tempo & 0xff000000) >> 24; + outBuffer[2] = (tempo & 0x00ff0000) >> 16; + outBuffer[3] = (tempo & 0x0000ff00) >> 8; + outBuffer[4] = tempo & 0x000000ff; + + bool written = _comport->WriteData(outBuffer, 5); + /* + char INBUFFER[128]; + memset(INBUFFER, 0, 128); + int nbread = _comport->ReadData(INBUFFER, 128); + stringstream s; + s << nbread << " read:\n" << INBUFFER << endl; + OutputDebugString(s.str().c_str());*/ +} + +void MetronomeHaptic::setNbBeats(uint32_t nbbeats) +{ + Metronome::setNbBeats(nbbeats); + //send info to Serial Port + char outBuffer[5];// = {'B', '5', '6', '7', '8'}; + memset(outBuffer, 0, 5); +/* sprintf(OUTBUFFER, "B%3d\n", nbbeats);*/ + outBuffer[0] = 'B'; + outBuffer[1] = (nbbeats & 0xff000000) >> 24; + outBuffer[2] = (nbbeats & 0x00ff0000) >> 16; + outBuffer[3] = (nbbeats & 0x0000ff00) >> 8; + outBuffer[4] = nbbeats & 0x000000ff; + + bool written = _comport->WriteData(outBuffer, 5); + +/* char INBUFFER[128]; + memset(INBUFFER, 0, 128); + int nbread = _comport->ReadData(INBUFFER, 128); + stringstream s; + s << nbread << " read:\n" << INBUFFER << endl; + OutputDebugString(s.str().c_str());*/ +} + +void MetronomeHaptic::run() +{ + thread = SDL_CreateThread(&MetronomeHaptic::thread_func, this); +} + +int MetronomeHaptic::thread_func(void *obj) +{ + MetronomeHaptic *thismetronome = static_cast(obj); + + SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); + + const list > *bips = thismetronome->_track->getBips(); + //const map > *tempo = thismetronome->_track->getTempos(); + const map > *timesignatures = thismetronome->_track->getTimeSignatures(); + static list >::const_iterator cBips = bips->begin(); + //static map >::const_iterator cTempo = tempo->begin(); + static map >::const_iterator cTimesignature = timesignatures->begin(); + +#ifdef WIN32 + struct { int tv_sec, tv_usec; } now, start; + DWORD t = timeGetTime () - BEFOREDELAY; + start.tv_sec = t / 1000; + start.tv_usec = (t % 1000) * 1000; +#else + struct timeval now, start; + gettimeofday(&start, NULL); +#endif + //float currenttime = 0; + + char outBuffer[5]; + outBuffer[0] = 'S'; + outBuffer[1] = 0; + outBuffer[2] = 0; + outBuffer[3] = 0; + outBuffer[4] = 0; + bool written = thismetronome->_comport->WriteData(outBuffer, 5); + + while(thismetronome->_activated) + { +#ifdef WIN32 + t = timeGetTime (); + now.tv_sec = t / 1000; + now.tv_usec = (t % 1000) * 1000; +#else + gettimeofday(&now, NULL); +#endif + uint32_t currenttime = (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec - start.tv_usec) / 1000; + + while (cBips != bips->end() && currenttime >= BIPTIMESTAMP(*cBips)) + { + char outBuffer[5]; + outBuffer[0] = 'N'; + outBuffer[1] = ((*cBips).getY() & 0xff000000) >> 24; + outBuffer[2] = ((*cBips).getY() & 0x00ff0000) >> 16; + outBuffer[3] = ((*cBips).getY() & 0x0000ff00) >> 8; + outBuffer[4] = (*cBips).getY() & 0x000000ff; + + bool written = thismetronome->_comport->WriteData(outBuffer, 5); + + cBips++; + } + + // on avance tant que les tempos sont dépassées + while (cTimesignature != timesignatures->end() && TIMESTAMP(*cTimesignature) < currenttime - BEFOREDELAY) + { + char outBuffer[5]; + outBuffer[0] = 'T'; + outBuffer[1] = ((*cTimesignature).second.getY() & 0xff000000) >> 24; + outBuffer[2] = ((*cTimesignature).second.getY() & 0x00ff0000) >> 16; + outBuffer[3] = ((*cTimesignature).second.getY() & 0x0000ff00) >> 8; + outBuffer[4] = (*cTimesignature).second.getY() & 0x000000ff; + + bool written = thismetronome->_comport->WriteData(outBuffer, 5); + + cTimesignature++; + } + + SDL_Delay(5); + } + return 0; +} + +/* +int MetronomeHaptic::thread_func(void *obj) +{ + MetronomeHaptic *thismetronome = static_cast(obj); + + SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); + + const map > *tempo = thismetronome->_track->getTempos(); + const map > *timesignatures = thismetronome->_track->getTimeSignatures(); + static map >::const_iterator cTempo = tempo->begin(); + static map >::const_iterator cTimesignature = timesignatures->begin(); + +#ifdef WIN32 + struct { int tv_sec, tv_usec; } now, start; + DWORD t = timeGetTime (); + start.tv_sec = t / 1000; + start.tv_usec = (t % 1000) * 1000; +#else + struct timeval now, start; + gettimeofday(&start, NULL); +#endif + float currenttime = 0; + + while(thismetronome->_activated) + { +#ifdef WIN32 + t = timeGetTime (); + now.tv_sec = t / 1000; + now.tv_usec = (t % 1000) * 1000; +#else + gettimeofday(&now, NULL); +#endif + float currenttime = (now.tv_sec - start.tv_sec) * 1000.0f + (now.tv_usec - start.tv_usec) / 1000.0f; + + // on avance tant que les tempos sont dépassées + while (cTempo != tempo->end() && currenttime > (*cTempo).second.getX()) + { + //tempo change + stringstream s; + s << "Tempo change at " << currenttime << " : tick=" << (*cTempo).first << " at " << (*cTempo).second.getX() << " for " << (60000000/(*cTempo).second.getY()) << " bpm" << endl; + OutputDebugString(s.str().c_str()); + + thismetronome->setTempo((*cTempo).second.getY()); + + cTempo++; + } + + // on avance tant que les tempos sont dépassées + while (cTimesignature != timesignatures->end() && (*cTimesignature).second.getX() < currenttime) + { + //time signature change + stringstream s; + s << "Time signature change at " << currenttime << " : tick=" << (*cTimesignature).first << " at " << (*cTimesignature).second.getX() << " for " << (*cTimesignature).second.getY() << " beats " << endl; + OutputDebugString(s.str().c_str()); + + thismetronome->setNbBeats((*cTimesignature).second.getY()); + + cTimesignature++; + } + SDL_Delay(5); + } + return 0; +} +*/ \ No newline at end of file diff --git a/src/PaintGame.cpp b/src/PaintGame.cpp index b11e10d..206b7e9 100644 --- a/src/PaintGame.cpp +++ b/src/PaintGame.cpp @@ -158,6 +158,7 @@ void init() glEnable(GL_BLEND); glShadeModel(GL_SMOOTH); glEnable(GL_NORMALIZE); +// glEnable(GL_POLYGON_SMOOTH); GLfloat light_ambient[] = { 0.8f, 0.7f, 0.9f, 1.0f }; GLfloat light_diffuse[] = { 1.0f, 0.9f, 0.8f, 1.0f }; @@ -172,8 +173,8 @@ void init() glEnable(GL_LIGHT0); // SDL_EnableKeyRepeat(10, 100); - fromKeyboard.setPosition(-1); - fromKeyboard.setEnd(-1); + fromKeyboard.setTimestamp(-1); + fromKeyboard.setEndTimestamp(-1); } void initPaint() @@ -184,7 +185,7 @@ void initPaint() } -void draw(Track &t, float currenttime, char diff) +void draw(Track &t, uint32_t currenttime, char diff) { posz = -SECONDSIZE * currenttime; @@ -204,10 +205,10 @@ void draw(Track &t, float currenttime, char diff) texturefond->useTexture(); glBegin(GL_QUADS); glColor3f(1.0f, 1.0f, 1.0f); - glTexCoord2d(0, 0); glVertex2f(0.0f, 0.0f); - glTexCoord2d(0, 1); glVertex2f(0.0f, float(resolution_y)); - glTexCoord2d(1, 1); glVertex2f(float(resolution_x), float(resolution_y)); - glTexCoord2d(1, 0); glVertex2f(float(resolution_x), 0.0f); + glTexCoord2f(0.0, 0.0); glVertex2f(0.0f, 0.0f); + glTexCoord2f(0.0, 1.0); glVertex2f(0.0f, float(resolution_y)); + glTexCoord2f(1.0, 1.0); glVertex2f(float(resolution_x), float(resolution_y)); + glTexCoord2f(1.0, 0.0); glVertex2f(float(resolution_x), 0.0f); glEnd(); glDisable(GL_TEXTURE_2D); @@ -225,19 +226,22 @@ void draw(Track &t, float currenttime, char diff) // cout << "End: " << t.getEndOfTrack() << endl; //glEnable(GL_LIGHTING); + glPolygonOffset(1.0f, 4.0f); // Draw the guitar neck - glEnable(GL_TEXTURE_2D); + glEnable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_TEXTURE_2D); texturebois->useTexture(); glBegin(GL_QUADS); glColor3f(1.0f, 1.0f, 1.0f); // Set The Color To Green - glTexCoord2d(0, 0); glVertex3f( NECKWIDTH,0, 0); - glTexCoord2d(0, 20000); glVertex3f( NECKWIDTH,0,-1500000); - glTexCoord2d(1, 20000); glVertex3f(-NECKWIDTH,0,-1500000); - glTexCoord2d(1, 0); glVertex3f(-NECKWIDTH,0, 0); + glTexCoord2f(0.0, 0.0); glVertex3f( NECKWIDTH, 0.0, 0.0); + glTexCoord2f(0.0, 150000.0/NECKWIDTH); glVertex3f( NECKWIDTH, 0.0,-1500000.0); + glTexCoord2f(1.0, 150000.0/NECKWIDTH); glVertex3f(-NECKWIDTH, 0.0,-1500000.0); + glTexCoord2f(1.0, 0.0); glVertex3f(-NECKWIDTH, 0.0, 0.0); glEnd(); - glDisable(GL_TEXTURE_2D); - + glDisable(GL_TEXTURE_2D); + glDisable(GL_POLYGON_OFFSET_FILL); + glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(0, 0, posz); @@ -326,28 +330,28 @@ void drawCube(float pos, float size, float colorx, float colory, float colorz) glVertex3f( size+pos,0,-size); // Bottom Right Of The Quad (Bottom) */ glNormal3f(0, 0.5, 0.5); - glTexCoord2d(1.0, 0.0); glVertex3f( size/2+pos, size/3, size/2); // Top Right Of The Quad (Front) - glTexCoord2d(0.0, 0.0); glVertex3f(-size/2+pos, size/3, size/2); // Top Left Of The Quad (Front) - glTexCoord2d(0.0, 1.0); glVertex3f(-size+pos,0, size); // Bottom Left Of The Quad (Front) - glTexCoord2d(1.0, 1.0); glVertex3f( size+pos,0, size); // Bottom Right Of The Quad (Front) + glTexCoord2f(1.0, 1.0); glVertex3f( size/2+pos, size/3, size/2); // Top Right Of The Quad (Front) + glTexCoord2f(0.0, 1.0); glVertex3f(-size/2+pos, size/3, size/2); // Top Left Of The Quad (Front) + glTexCoord2f(0.0, 0.0); glVertex3f(-size+pos,0, size); // Bottom Left Of The Quad (Front) + glTexCoord2f(1.0, 0.0); glVertex3f( size+pos,0, size); // Bottom Right Of The Quad (Front) glNormal3f(0, 0.5, -0.5); - glTexCoord2d(1.0, 0.0); glVertex3f( size+pos,0,-size); // Bottom Left Of The Quad (Back) - glTexCoord2d(0.0, 0.0); glVertex3f(-size+pos,0,-size); // Bottom Right Of The Quad (Back) - glTexCoord2d(0.0, 1.0); glVertex3f(-size/2+pos, size/3,-size/2); // Top Right Of The Quad (Back) - glTexCoord2d(1.0, 1.0); glVertex3f( size/2+pos, size/3,-size/2); // Top Left Of The Quad (Back) + glTexCoord2f(0.0, 0.0); glVertex3f( size+pos,0,-size); // Bottom Left Of The Quad (Back) + glTexCoord2f(1.0, 0.0); glVertex3f(-size+pos,0,-size); // Bottom Right Of The Quad (Back) + glTexCoord2f(1.0, 1.0); glVertex3f(-size/2+pos, size/3,-size/2); // Top Right Of The Quad (Back) + glTexCoord2f(0.0, 1.0); glVertex3f( size/2+pos, size/3,-size/2); // Top Left Of The Quad (Back) glNormal3f(-0.5, 0.5, 0); - glTexCoord2d(1.0, 0.0); glVertex3f(-size/2+pos, size/3, size/2); // Top Right Of The Quad (Left) - glTexCoord2d(0.0, 0.0); glVertex3f(-size/2+pos, size/3,-size/2); // Top Left Of The Quad (Left) - glTexCoord2d(0.0, 1.0); glVertex3f(-size+pos,0,-size); // Bottom Left Of The Quad (Left) - glTexCoord2d(1.0, 1.0); glVertex3f(-size+pos,0, size); // Bottom Right Of The Quad (Left) + glTexCoord2f(1.0, 1.0); glVertex3f(-size/2+pos, size/3, size/2); // Top Right Of The Quad (Left) + glTexCoord2f(0.0, 1.0); glVertex3f(-size/2+pos, size/3,-size/2); // Top Left Of The Quad (Left) + glTexCoord2f(0.0, 0.0); glVertex3f(-size+pos,0,-size); // Bottom Left Of The Quad (Left) + glTexCoord2f(1.0,0.0); glVertex3f(-size+pos,0, size); // Bottom Right Of The Quad (Left) glNormal3f(0.5, 0.5, 0); - glTexCoord2d(1.0, 0.0); glVertex3f( size/2+pos, size/3,-size/2l); // Top Right Of The Quad (Right) - glTexCoord2d(0.0, 0.0); glVertex3f( size/2+pos, size/3, size/2); // Top Left Of The Quad (Right) - glTexCoord2d(0.0, 1.0); glVertex3f( size+pos,0, size); // Bottom Left Of The Quad (Right) - glTexCoord2d(1.0, 1.0); glVertex3f( size+pos,0,-size); // Bottom Right Of The Quad (Right) + glTexCoord2f(1.0, 1.0); glVertex3f( size/2+pos, size/3,-size/2); // Top Right Of The Quad (Right) + glTexCoord2f(0.0, 1.0); glVertex3f( size/2+pos, size/3, size/2); // Top Left Of The Quad (Right) + glTexCoord2f(0.0, 0.0); glVertex3f( size+pos,0, size); // Bottom Left Of The Quad (Right) + glTexCoord2f(1.0, 0.0); glVertex3f( size+pos,0,-size); // Bottom Right Of The Quad (Right) glEnd(); glDisable(GL_TEXTURE_2D); @@ -409,7 +413,7 @@ void drawLong(float pos, float size, float length, float colorx, float colory, f glEnd(); // Done Drawing The Quad } -void handleKeyOn(keys k, float currenttime) +void handleKeyOn(keys k, uint32_t currenttime) { fromKeyboard.addKey(k); /* switch(k) @@ -432,43 +436,43 @@ void handleKeyOn(keys k, float currenttime) }*/ } -void handleKeyOff(keys k, float currenttime) +void handleKeyOff(keys k, uint32_t currenttime) { // fromKeyboard.remKey(k); - if (fromKeyboard.getPosition() == -1) + if (fromKeyboard.getTimestamp() == -1) return; - fromKeyboard.setEnd(currenttime); + fromKeyboard.setEndTimestamp(currenttime); cout << fromKeyboard << endl; fromKeyboard.log("Play", logfile); - fromKeyboard.setPosition(currenttime); - fromKeyboard.setEnd(-1); + fromKeyboard.setTimestamp(currenttime); + fromKeyboard.setEndTimestamp(-1); } -void handleKeys(bool a, bool b, bool c, bool d, bool e, float currenttime) +void handleKeys(bool a, bool b, bool c, bool d, bool e, uint32_t currenttime) { if (fromKeyboard.isNone()) - fromKeyboard.setPosition(-1); + fromKeyboard.setTimestamp(-1); fromKeyboard.setKeys(a, b, c, d, e); } -void handleStrokeOn(float currenttime) +void handleStrokeOn(uint32_t currenttime) { - if (fromKeyboard.getPosition() != -1) + if (fromKeyboard.getTimestamp() != -1) { - fromKeyboard.setEnd(currenttime); + fromKeyboard.setEndTimestamp(currenttime); cout << fromKeyboard << endl; fromKeyboard.log("Play", logfile); } - fromKeyboard.setPosition(currenttime); - fromKeyboard.setEnd(-1); + fromKeyboard.setTimestamp(currenttime); + fromKeyboard.setEndTimestamp(-1); } -void handleStrokeOff(float currenttime) +void handleStrokeOff(uint32_t currenttime) { } -bool processEvents(float currenttime) +bool processEvents(uint32_t currenttime) { SDL_Event event; // bool quitProgram = false; diff --git a/src/Serial.cpp b/src/Serial.cpp new file mode 100644 index 0000000..7898324 --- /dev/null +++ b/src/Serial.cpp @@ -0,0 +1,10 @@ +#include "Serial.hpp" + +Serial::Serial(char *portName) +:_connected(false) +{ +} + +Serial::~Serial() +{ +} diff --git a/src/SerialWindows.cpp b/src/SerialWindows.cpp new file mode 100644 index 0000000..927cfae --- /dev/null +++ b/src/SerialWindows.cpp @@ -0,0 +1,141 @@ +#include "SerialWindows.hpp" + +#include +using namespace std; + +#ifdef WIN32 +#include +#include +#else +#include +#endif + +SerialWindows::SerialWindows(char *portName) +:Serial(portName) +{ + //Try to connect to the given port throuh CreateFile + _hSerial = CreateFile(portName, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, //FILE_ATTRIBUTE_NORMAL, + NULL); + + //Check if the connection was successfull + if(_hSerial == INVALID_HANDLE_VALUE) + { + //If not success full display an Error + if(GetLastError() == ERROR_FILE_NOT_FOUND) + cerr << "ERROR: Handle was not attached. Reason: " << portName << " not available." << endl; + else + cerr << "ERROR unknown" << endl; + } + else + { + /* + COMMTIMEOUTS commTimeouts; + commTimeouts.ReadIntervalTimeout = 1; + commTimeouts.ReadTotalTimeoutMultiplier = 10; + commTimeouts.ReadTotalTimeoutConstant = 100; + commTimeouts.WriteTotalTimeoutMultiplier = 10; + commTimeouts.WriteTotalTimeoutConstant = 100; + if (SetCommTimeouts(_comport, &commTimeouts) == 0) + throw "Cannot set COM port timeouts";*/ + + + //If connected we try to set the comm parameters + DCB dcbSerialParams = {0}; + + //Try to get the current + if (!GetCommState(_hSerial, &dcbSerialParams)) + //If impossible, show an error + cerr << "ERROR: failed to get current serial parameters!" << endl; + else + { + //Define serial connection parameters for the arduino board + dcbSerialParams.BaudRate=CBR_57600; + dcbSerialParams.ByteSize=8; + dcbSerialParams.StopBits=ONESTOPBIT; + dcbSerialParams.Parity=NOPARITY; + + //Set the parameters and check for their proper application + if(!SetCommState(_hSerial, &dcbSerialParams)) + cerr << "ERROR: Could not set Serial Port parameters" << endl; + else + { + //If everything went fine we're connected + _connected = true; + //We wait 2s as the arduino board will be reseting + SDL_Delay(ARDUINO_WAIT_TIME); + } + } + } +} + +SerialWindows::~SerialWindows() +{ + //Check if we are connected before trying to disconnect + if(_connected) + { + //We're no longer connected + _connected = false; + //Close the serial handler + CloseHandle(_hSerial); + } +} + +int SerialWindows::ReadData(char *buffer, unsigned int nbChar) +{ + //Number of bytes we'll have read + DWORD bytesRead = 0; + //Number of bytes we'll really ask to read + unsigned int toRead = 0; + + //Use the ClearCommError function to get status info on the Serial port + ClearCommError(_hSerial, &_errors, &_status); + + //Check if there is something to read + if(_status.cbInQue > 0) + { + //If there is we check if there is enough data to read the required number + //of characters, if not we'll read only the available characters to prevent + //locking of the application. + if(_status.cbInQue > nbChar) + toRead = nbChar; + else + toRead = _status.cbInQue; + + //Try to read the require number of chars, and return the number of read bytes on success + if(ReadFile(_hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0) + return bytesRead; + } + + //If nothing has been read, or that an error was detected return -1 + return -1; +} + + +bool SerialWindows::WriteData(char *buffer, unsigned int nbChar) +{ + DWORD bytesSend; + + //Try to write the buffer on the Serial port + if(!WriteFile(_hSerial, (void *)buffer, nbChar, &bytesSend, 0)) + { + //In case it don't work get comm error and return false + ClearCommError(_hSerial, &_errors, &_status); + + return false; + } + else + { + ClearCommError(_hSerial, &_errors, &_status); +/* if(!FlushFileBuffers(_hSerial)) + cout << "ERROR while flushing" << endl;*/ +/* stringstream s; + s << bytesSend << " SENT" << endl; + OutputDebugString(s.str().c_str());*/ + return true; + } +} diff --git a/src/Track.cpp b/src/Track.cpp index d3e8117..925885d 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -150,7 +150,7 @@ void Track::remKey(uint32_t time, uint8_t note) uint8_t difficulty = note / 12 - 5; uint8_t key = note % 12; // cout << "- diff=" << difficulty+0 << " key=" << key+0 << " note=" << note+0 << endl; - if (difficulty >= NBDIFFICULTIES || difficulty+0 < 0) + if (difficulty >= NBDIFFICULTIES || difficulty + 0 < 0) { // cout << "Wrong difficulty!" << difficulty << endl; return; @@ -166,42 +166,49 @@ void Track::remKey(uint32_t time, uint8_t note) _currentconfig[difficulty].setTicks(time - _currentconfig[difficulty].getTime()); //compute the note duration and position uint32_t currenttempo = 0, lasttick = 0; - map >::iterator ti = _tempo.begin(); + map >::iterator ti = _tempo.begin(); uint32_t tickpos = _currentconfig[difficulty].getTime(); - while (ti != _tempo.end() && (*ti).first <= tickpos) + while (ti != _tempo.end() && TICK(*ti) <= tickpos) { - _currentconfig[difficulty].setPosition(_currentconfig[difficulty].getPosition() + ((*ti).first - lasttick) * (currenttempo / 480000.0)); - lasttick = (*ti).first; - currenttempo = (*ti).second.getY(); +// _currentconfig[difficulty].setPosition(_currentconfig[difficulty].getPosition() + (TICK(*ti) - lasttick) * (currenttempo / 480000.0)); + _currentconfig[difficulty].setTimestamp(TIMESTAMP(*ti)); + lasttick = TICK(*ti); + currenttempo = VALUE(*ti); ti++; } if (tickpos > lasttick) - _currentconfig[difficulty].setPosition(_currentconfig[difficulty].getPosition() + (tickpos - lasttick) * (currenttempo / 480000.0)); - + { + uint32_t delta = static_cast((tickpos - lasttick) * (currenttempo / 480000.0)); + _currentconfig[difficulty].setTimestamp(_currentconfig[difficulty].getTimestamp() + delta); + } + + //long notes while (tickpos < time) { - if (ti != _tempo.end() && (*ti).first < time) + if (ti != _tempo.end() && TICK(*ti) < time) { - _currentconfig[difficulty].setEnd(_currentconfig[difficulty].getPosition() + ((*ti).first - tickpos) * (currenttempo / 480000.0)); - tickpos = (*ti).first; - currenttempo = (*ti).second.getY(); + uint32_t delta = static_cast((TICK(*ti) - tickpos) * (currenttempo / 480000.0)); + _currentconfig[difficulty].setEndTimestamp(_currentconfig[difficulty].getTimestamp() + delta); + _currentconfig[difficulty].setEndTimestamp(TIMESTAMP(*ti)); + tickpos = TICK(*ti); + currenttempo = VALUE(*ti); ti++; } else { - _currentconfig[difficulty].setEnd(_currentconfig[difficulty].getPosition() + (time - tickpos) * (currenttempo / 480000.0)); + uint32_t delta = static_cast((time - tickpos) * (currenttempo / 480000.0)); + _currentconfig[difficulty].setEndTimestamp(_currentconfig[difficulty].getTimestamp() + delta); tickpos = time; } } - _notes[difficulty][_currentconfig[difficulty].getTime()] = _currentconfig[difficulty]; // cout << "add note pos=" << _notes[difficulty][_currentconfig[difficulty].getTime()].getPosition() << " duration=" << _notes[difficulty][_currentconfig[difficulty].getTime()].getDuration() << endl; - _currentconfig[difficulty].setPosition(0); - _currentconfig[difficulty].setEnd(0); + _currentconfig[difficulty].setTimestamp(0); + _currentconfig[difficulty].setEndTimestamp(0); _currentconfig[difficulty].setTicks(0); _nbnotes[difficulty]++; } @@ -261,23 +268,6 @@ uint32_t Track::getTimeSignature(uint32_t pos) return _timesignatures[pos].getY(); } - -uint32_t Track::getTempo(float pos) -{ - for( map >::iterator ii=_tempo.begin(); ii!=_tempo.end(); ++ii) - if ((*ii).second.getX() - pos < EPSILON) - return (*ii).second.getY(); - return 0; -} - -uint32_t Track::getTimeSignature(float pos) -{ - for( map >::iterator ii=_timesignatures.begin(); ii!=_timesignatures.end(); ++ii) - if ((*ii).second.getX() - pos < EPSILON) - return (*ii).second.getY(); - return 0; -} - /* void Track::computeBips() { @@ -314,36 +304,42 @@ void Track::displayTracks() void Track::debugTempo() { cout << "Tempo changes: " << endl; - for( map >::iterator ii=_tempo.begin(); ii!=_tempo.end(); ++ii) - cout << (*ii).first << ": " << (*ii).second.getX() << " (" << (*ii).second.getY() << ")" << endl; + for( map >::iterator ii=_tempo.begin(); ii!=_tempo.end(); ++ii) + cout << TICK(*ii) << ": " << TIMESTAMP(*ii) << " (" << VALUE(*ii) << ")" << endl; //ticksToBeats((*ii).second) << ")" << endl; } -void Track::drawFrets(float postime) const +void Track::drawFrets(uint32_t postime) const { - static list >::const_iterator startingbips = _bips.begin(); + static list >::const_iterator startingbips = _bips.begin(); // on avance tant que les bips sont dépassées - while (startingbips != _bips.end() && (*startingbips).getY() < postime) + while (startingbips != _bips.end() && BIPTIMESTAMP(*startingbips) < postime) { // Mixer::getInstance()->playSound("bip"); - if (logfile) - fprintf(logfile, "Bip;%f;%f;%f\n", (*startingbips).getY(), postime, postime - (*startingbips).getY()); +// if (logfile) +// fprintf(logfile, "Bip;%f;%f;%f\n", (*startingbips).getY(), postime, postime - (*startingbips).getY()); startingbips++; } - list >::const_iterator b = startingbips; + list >::const_iterator b = startingbips; glMatrixMode(GL_MODELVIEW); //on dessine les frettes jusqu'à 10s - while (b != _bips.end() && (*b).getY() < postime + 10000) + while (b != _bips.end() && BIPTIMESTAMP(*b) < postime + 10000) { glPushMatrix(); - glTranslatef(0, 0, static_cast(- SECONDSIZE * (*b).getY())); + glTranslatef(0, 0, static_cast(- SECONDSIZE * BIPTIMESTAMP(*b))); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-2.0f, -20.0f); glBegin(GL_QUADS); glColor3f(0.8f, 0.8f, 0.0f); // Set The Color To Green - glNormal3f(0, 0.5f, 0.5f); - glVertex3f( NECKWIDTH,0, 0.1f); + glNormal3f(0, 1.0f, 0); + glVertex3f( NECKWIDTH, 0.0f, 0.2f); + glVertex3f( NECKWIDTH, 0.0f, -0.2f); + glVertex3f(-NECKWIDTH, 0.0f, -0.2f); + glVertex3f(-NECKWIDTH, 0.0f, 0.2f); +/* glVertex3f( NECKWIDTH,0, 0.1f); glVertex3f( NECKWIDTH,0.1f, 0); glVertex3f(-NECKWIDTH,0.1f, 0); glVertex3f(-NECKWIDTH,0, 0.1f); @@ -351,14 +347,15 @@ void Track::drawFrets(float postime) const glVertex3f( NECKWIDTH,0.1f, 0); glVertex3f( NECKWIDTH,0, -0.1f); glVertex3f(-NECKWIDTH,0, -0.1f); - glVertex3f(-NECKWIDTH,0.1f, 0); + glVertex3f(-NECKWIDTH,0.1f, 0);*/ glEnd(); + glDisable(GL_POLYGON_OFFSET_FILL); glPopMatrix(); b++; } } -void Track::drawNotes(float postime, uint8_t diff) const +void Track::drawNotes(uint32_t postime, uint8_t diff) const { static map::const_iterator startingn = _notes[diff].begin(); static double startingpos = 0.0; @@ -368,12 +365,12 @@ void Track::drawNotes(float postime, uint8_t diff) const // on avance tant que les notes sont dépassées while (startingn != _notes[diff].end()) { - double endpos = (*startingn).second.getPosition(); - if ((*startingn).second.getTicks() > 240) - endpos = (*startingn).second.getEnd(); + double endpos = NOTETIMESTAMP(*startingn); + if (ISLONGNOTE(*startingn)) + endpos = NOTEENDTIMESTAMP(*startingn); if (endpos >= postime) break; - startingpos = (*startingn).second.getPosition(); + startingpos = NOTETIMESTAMP(*startingn); (*startingn).second.log("Note", logfile); startingn++; } @@ -382,10 +379,10 @@ void Track::drawNotes(float postime, uint8_t diff) const glMatrixMode(GL_MODELVIEW); //on dessine les notes jusqu'à 10s - while (n != _notes[diff].end() && (*n).second.getEnd() < postime + 10000) + while (n != _notes[diff].end() && NOTEENDTIMESTAMP(*n) < postime + 10000) { glPushMatrix(); - glTranslatef(0, 0, static_cast(- SECONDSIZE * (*n).second.getPosition())); + glTranslatef(0, 0, static_cast(- SECONDSIZE * NOTETIMESTAMP(*n))); (*n).second.display(); glPopMatrix(); n++; diff --git a/src/Wiimote.cpp b/src/Wiimote.cpp index 4e8132f..962c40b 100644 --- a/src/Wiimote.cpp +++ b/src/Wiimote.cpp @@ -38,7 +38,7 @@ Wiimote::Wiimote(int nb) } } -void Wiimote::handleKey(guitar_hero_3_t* gh3, int key, int button, float currenttime) +void Wiimote::handleKey(guitar_hero_3_t* gh3, int key, int button, uint32_t currenttime) { if (_keystate[key]) { @@ -54,7 +54,7 @@ void Wiimote::handleKey(guitar_hero_3_t* gh3, int key, int button, float current } } -void Wiimote::handleEvents(float currenttime) +void Wiimote::handleEvents(uint32_t currenttime) { if (!wiiuse_poll(_wiimotes, _nb)) return; diff --git a/src/main.cpp b/src/main.cpp index 8218b04..167f656 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "PaintGame.h" #include "Metronome.hpp" #include "MetronomeAudio.hpp" +#include "MetronomeHaptic.hpp" #ifdef WIN32 #include @@ -77,19 +78,17 @@ int main(int argc, char *argv[]) exit(0); } - cout << "Loading notes" << endl; - - test->readHeader(); Track tr; - cout << "Reading tracks" << endl; - test->readTracks(tr); - - cout << "Computing metronome bips" << endl; - //compute the ticks positions -// tr.computeBips(); + cout << "Loading notes" << endl; + test->readHeader(); + cout << "Reading tracks" << endl; + test->readTracks(tr); init(); + cout << "Create Metronome" << endl; +// Metronome *m = new MetronomeAudio(&tr); + Metronome *m = new MetronomeHaptic(&tr); bool quitProgram = false; @@ -104,8 +103,6 @@ int main(int argc, char *argv[]) cout << "Init paint" << endl; initPaint(); - - Metronome *m = new MetronomeAudio(&tr); #ifdef WIN32 @@ -158,7 +155,7 @@ int main(int argc, char *argv[]) struct timeval now; gettimeofday(&now, NULL); #endif - float currenttime = (now.tv_sec - start.tv_sec) * 1000.0f + (now.tv_usec - start.tv_usec) / 1000.0f; + uint32_t currenttime = (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec - start.tv_usec) / 1000; // cout << "draw" << endl; draw(tr, currenttime, NORMAL);