From ca395a50867250c364dc6401715c6dce023fba83 Mon Sep 17 00:00:00 2001 From: Thomas Pietrzak Date: Thu, 7 Apr 2011 22:07:34 +0000 Subject: [PATCH] Manage metronomes, uint32 timestamps git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@9 47cf9a05-e0a8-4ed5-9e9b-101a649bc004 --- Haptic Metronome/Haptic Metronome.suo | Bin 66048 -> 71168 bytes include/Config.hpp | 21 +-- include/Metronome.hpp | 26 +++ include/MetronomeAudio.hpp | 29 ++++ include/MetronomeHaptic.hpp | 35 ++++ include/PaintGame.h | 24 +-- include/Serial.hpp | 35 ++++ include/SerialWindows.hpp | 35 ++++ include/Track.hpp | 45 ++++-- include/Wiimote.hpp | 16 +- src/Config.cpp | 28 +++- src/MIDIReader.cpp | 26 +-- src/Metronome.cpp | 6 + src/MetronomeAudio.cpp | 92 +++++++++++ src/MetronomeHaptic.cpp | 220 ++++++++++++++++++++++++++ src/PaintGame.cpp | 94 +++++------ src/Serial.cpp | 10 ++ src/SerialWindows.cpp | 141 +++++++++++++++++ src/Track.cpp | 103 ++++++------ src/Wiimote.cpp | 4 +- src/main.cpp | 21 ++- 21 files changed, 834 insertions(+), 177 deletions(-) create mode 100644 include/Metronome.hpp create mode 100644 include/MetronomeAudio.hpp create mode 100644 include/MetronomeHaptic.hpp create mode 100644 include/Serial.hpp create mode 100644 include/SerialWindows.hpp create mode 100644 src/Metronome.cpp create mode 100644 src/MetronomeAudio.cpp create mode 100644 src/MetronomeHaptic.cpp create mode 100644 src/Serial.cpp create mode 100644 src/SerialWindows.cpp diff --git a/Haptic Metronome/Haptic Metronome.suo b/Haptic Metronome/Haptic Metronome.suo index 6397c4f1d1d1e41d26151d2eeac91f536518acda..51f3482d84198a56f7e0b0ecba22a1002dbbbfb5 100644 GIT binary patch delta 4893 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 A-T(jq delta 3970 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 wU`jE)9%86-od;W8qhE + +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); -- 2.30.2