Manage metronomes, uint32 timestamps
authorThomas Pietrzak <thomas.pietrzak@gmail.com>
Thu, 7 Apr 2011 22:07:34 +0000 (22:07 +0000)
committerThomas Pietrzak <thomas.pietrzak@gmail.com>
Thu, 7 Apr 2011 22:07:34 +0000 (22:07 +0000)
git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@9 47cf9a05-e0a8-4ed5-9e9b-101a649bc004

21 files changed:
Haptic Metronome/Haptic Metronome.suo
include/Config.hpp
include/Metronome.hpp [new file with mode: 0644]
include/MetronomeAudio.hpp [new file with mode: 0644]
include/MetronomeHaptic.hpp [new file with mode: 0644]
include/PaintGame.h
include/Serial.hpp [new file with mode: 0644]
include/SerialWindows.hpp [new file with mode: 0644]
include/Track.hpp
include/Wiimote.hpp
src/Config.cpp
src/MIDIReader.cpp
src/Metronome.cpp [new file with mode: 0644]
src/MetronomeAudio.cpp [new file with mode: 0644]
src/MetronomeHaptic.cpp [new file with mode: 0644]
src/PaintGame.cpp
src/Serial.cpp [new file with mode: 0644]
src/SerialWindows.cpp [new file with mode: 0644]
src/Track.cpp
src/Wiimote.cpp
src/main.cpp

index 6397c4f1d1d1e41d26151d2eeac91f536518acda..51f3482d84198a56f7e0b0ecba22a1002dbbbfb5 100644 (file)
Binary files a/Haptic Metronome/Haptic Metronome.suo and b/Haptic Metronome/Haptic Metronome.suo differ
index bd615a6f793f5b68551f130868b87d942bc6aa1f..d208ec12e81c845ccb09a96b4a0494cdf24a122d 100644 (file)
@@ -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 (file)
index 0000000..1ec54d5
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _METRONOME_\r
+#define _METRONOME_\r
+\r
+#include "Track.hpp"\r
+#include <stdint.h>\r
+\r
+class Metronome\r
+{\r
+       public:\r
+               Metronome(Track *track, uint32_t nbbeats=4, uint32_t tempo=0, bool activated=false);\r
+               virtual ~Metronome(){}\r
+\r
+               virtual void setActive(bool activated) { _activated = activated; }\r
+               virtual void setTempo(uint32_t tempo) { _tempo = tempo; }\r
+               virtual void setNbBeats(uint32_t nbbeats) {_nbbeats = nbbeats; }\r
+\r
+               virtual void run()=0;\r
+\r
+       protected:\r
+               uint32_t _nbbeats;\r
+               uint32_t _tempo;\r
+               bool _activated;\r
+               Track *_track;\r
+};\r
+\r
+#endif\r
diff --git a/include/MetronomeAudio.hpp b/include/MetronomeAudio.hpp
new file mode 100644 (file)
index 0000000..a652b3d
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _METRONOMEAUDIO_\r
+#define _METRONOMEAUDIO_\r
+\r
+#include "Metronome.hpp"\r
+
+#ifdef WIN32
+#include <time.h>
+#include <SDL.h>
+#include <SDL_Thread.h>
+#else
+#include <SDL/SDL.h>
+#include <SDL/SDL_Thread.h>
+#endif
+\r
+class MetronomeAudio : public Metronome\r
+{      \r
+       public:\r
+               MetronomeAudio(Track *track, uint32_t nbbeats=4, uint32_t tempo=0, bool activated=true);\r
+\r
+               ~MetronomeAudio();\r
+\r
+               void run();\r
+\r
+       private:\r
+               static int thread_func(void *unused);\r
+               SDL_Thread *thread;\r
+};\r
+\r
+#endif
\ No newline at end of file
diff --git a/include/MetronomeHaptic.hpp b/include/MetronomeHaptic.hpp
new file mode 100644 (file)
index 0000000..92db869
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _METRONOMEHAPTIC_\r
+#define _METRONOMEHAPTIC_\r
+\r
+#include "Metronome.hpp"\r
+
+#ifdef WIN32
+#include <time.h>
+#include <SDL.h>
+#include <SDL_Thread.h>
+#else
+#include <SDL/SDL.h>
+#include <SDL/SDL_Thread.h>
+#endif
+
+#include "Serial.hpp"
+\r
+class MetronomeHaptic : public Metronome\r
+{      \r
+       public:\r
+               MetronomeHaptic(Track *track, uint32_t nbbeats=4, uint32_t tempo=0, bool activated=true);\r
+\r
+               ~MetronomeHaptic();\r
+\r
+               void setTempo(uint32_t tempo);\r
+               void setNbBeats(uint32_t nbbeats);\r
+\r
+               void run();\r
+\r
+       private:\r
+               static int thread_func(void *unused);\r
+               SDL_Thread *thread;\r
+               Serial *_comport;\r
+};\r
+\r
+#endif
\ No newline at end of file
index a4557cd372553334e6c73b2d8832ff6e0da032dc..1a89b5c6aaf9cafd7d1a4cba1e79600642d95f63 100644 (file)
 
 void init();
 void initPaint();
-void draw(Track &t, float currenttime, char diff);\r
+void draw(Track &t, uint32_t currenttime, char diff);\r
 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);
 \r
-void handleKeyOn(keys k, float currenttime);\r
-void handleKeyOff(keys k, float currenttime);\r
-void handleKeys(bool a, bool b, bool c, bool d, bool e, float currenttime);
-void handleStrokeOn(float currenttime);\r
-void handleStrokeOff(float currenttime);\r
-bool processEvents(float currenttime);
+void handleKeyOn(keys k, uint32_t currenttime);\r
+void handleKeyOff(keys k, uint32_t currenttime);\r
+void handleKeys(bool a, bool b, bool c, bool d, bool e, uint32_t currenttime);
+void handleStrokeOn(uint32_t currenttime);\r
+void handleStrokeOff(uint32_t currenttime);\r
+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); }
 };
 \r
 #endif\r
diff --git a/include/Serial.hpp b/include/Serial.hpp
new file mode 100644 (file)
index 0000000..096fe6f
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _SERIAL_\r
+#define _SERIAL_\r
+\r
+#define ARDUINO_WAIT_TIME 500\r
+\r
+class Serial\r
+{\r
+    public:\r
+        //Initialize Serial communication with the given COM port\r
+        Serial(char *portName);\r
+\r
+        //Close the connection\r
+        //NOTA: for some reason you can't connect again before exiting\r
+        //the program and running it again\r
+        virtual ~Serial();\r
+\r
+        //Read data in a buffer, if nbChar is greater than the\r
+        //maximum number of bytes available, it will return only the\r
+        //bytes available. The function return -1 when nothing could\r
+        //be read, the number of bytes actually read.\r
+        virtual int ReadData(char *buffer, unsigned int nbChar)=0;\r
+\r
+        //Writes data from a buffer through the Serial connection\r
+        //return true on success.\r
+        virtual bool WriteData(char *buffer, unsigned int nbChar)=0;\r
+\r
+        //Check if we are actually connected\r
+               bool IsConnected() { return _connected; }\r
+\r
+    protected:\r
+        //Connection status\r
+        bool _connected;\r
+};\r
+\r
+#endif\r
diff --git a/include/SerialWindows.hpp b/include/SerialWindows.hpp
new file mode 100644 (file)
index 0000000..3b99741
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _SERIALWINDOWS_\r
+#define _SERIALWINDOWS_\r
+\r
+#include "Serial.hpp"\r
+\r
+#include <windows.h>\r
+\r
+class SerialWindows : public Serial\r
+{\r
+    public:\r
+        //Initialize Serial communication with the given COM port\r
+        SerialWindows(char *portName);\r
+        //Close the connection\r
+        //NOTA: for some reason you can't connect again before exiting\r
+        //the program and running it again\r
+        ~SerialWindows();\r
+        //Read data in a buffer, if nbChar is greater than the\r
+        //maximum number of bytes available, it will return only the\r
+        //bytes available. The function return -1 when nothing could\r
+        //be read, the number of bytes actually read.\r
+        int ReadData(char *buffer, unsigned int nbChar);\r
+        //Writes data from a buffer through the Serial connection\r
+        //return true on success.\r
+        bool WriteData(char *buffer, unsigned int nbChar);\r
+\r
+\r
+    private:\r
+        //Serial comm handler\r
+        HANDLE _hSerial;\r
+        //Get various information about the connection\r
+        COMSTAT _status;\r
+        //Keep track of last error\r
+        DWORD _errors;\r
+};\r
+#endif\r
index 501e3611c46c217d2d2f5f05804810443680bc17..4ecfd8d23ce1a9724719b98ecc7ce2f9b3c64487 100644 (file)
@@ -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<float, uint32_t>(timestamp, t); }
-    void addTimesignature(uint32_t tick, float timestamp, uint32_t t) { _timesignatures[tick] = Pair<float, uint32_t>(timestamp, t); }
-       map<uint32_t, Pair<float, uint32_t> > *getTempos() { return &_tempo; }  
-       map<uint32_t, Pair<float, uint32_t> > *getTimeSignatures() { return &_timesignatures; }
+    void addTempo(uint32_t tick, uint32_t timestamp, uint32_t t) { _tempo[tick] =  Pair<uint32_t, uint32_t>(timestamp, t); }
+    void addTimesignature(uint32_t tick, uint32_t timestamp, uint32_t t) { _timesignatures[tick] = Pair<uint32_t, uint32_t>(timestamp, t); }
+       map<uint32_t, Pair<uint32_t, uint32_t> > *getTempos() { return &_tempo; }  
+       map<uint32_t, Pair<uint32_t, uint32_t> > *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<Pair<uint32_t, float> > * getBips() { return &_bips; }
-       void addBip(uint32_t tick, float timestamp) { _bips.push_back(Pair<uint32_t, float>(tick, timestamp)); }
+       list<Pair<uint32_t, uint32_t> > * getBips() { return &_bips; }
+       void addBip(uint32_t tick, uint32_t timestamp) { _bips.push_back(Pair<uint32_t, uint32_t>(tick, timestamp)); }
 
     //void computeBips();
 
@@ -73,11 +84,11 @@ class Track
   private:
     //notes : position ; configs
     map<uint32_t, Config> _notes[NBDIFFICULTIES];
-    map<uint32_t, Pair<float, uint32_t> > _tempo;
-    map<uint32_t, Pair<float, uint32_t> > _timesignatures;
+    map<uint32_t, Pair<uint32_t, uint32_t> > _tempo;
+    map<uint32_t, Pair<uint32_t, uint32_t> > _timesignatures;
 
-//  private:
-    list<Pair<uint32_t, float> > _bips;
+       // (beat, timestamp)
+    list<Pair<uint32_t, uint32_t> > _bips;
     
     Config _currentconfig[NBDIFFICULTIES];
     
index 4d5ad9c02a6445619e67ea34fb1f0d47d39f1e84..9802af538c6b42695ab245ed4791145b7fa99e9b 100644 (file)
@@ -3,6 +3,8 @@
 
 #ifndef WIN32
        #include <unistd.h>
+#else
+       #include <stdint.h>
 #endif
 
 #include <wiiuse.h>
@@ -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];
index b8df6d7053c3d801facee32340a52903419fc499..ebe8ea8be3aaa8920d6f6f87a76522c4e0b0f66f 100644 (file)
@@ -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<float>(_end - _position);
+               float notelength = static_cast<float>(_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;
 }
index 407367673231962f05e0ff628184180d60c3a9b6..5783ded0295a34fe524aee0897c9c4a27019d780 100644 (file)
@@ -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<uint32_t>(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<uint32_t>((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 (file)
index 0000000..d4f304d
--- /dev/null
@@ -0,0 +1,6 @@
+#include "Metronome.hpp"\r
+\r
+Metronome::Metronome(Track *track, uint32_t nbbeats, uint32_t tempo, bool activated)\r
+:_track(track), _nbbeats(nbbeats), _tempo(tempo), _activated(activated)\r
+{\r
+}\r
diff --git a/src/MetronomeAudio.cpp b/src/MetronomeAudio.cpp
new file mode 100644 (file)
index 0000000..c3fcae2
--- /dev/null
@@ -0,0 +1,92 @@
+#include "MetronomeAudio.hpp"
+
+#include "Mixer.hpp"
+
+#ifdef WIN32
+#include <time.h>
+#include <windows.h>
+#else
+#include <sys/time.h>
+#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<MetronomeAudio *>(obj);
+
+       SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
+
+       const list<Pair<uint32_t, uint32_t> > *bips = thismetronome->_track->getBips();
+       //const map<uint32_t, Pair<float, uint32_t> > *tempo = thismetronome->_track->getTempos();
+    const map<uint32_t, Pair<uint32_t, uint32_t> > *timesignatures = thismetronome->_track->getTimeSignatures();
+       static list<Pair<uint32_t, uint32_t> >::const_iterator cBips = bips->begin();
+       //static map<uint32_t, Pair<float, uint32_t> >::const_iterator cTempo = tempo->begin();
+       static map<uint32_t, Pair<uint32_t, uint32_t> >::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 (file)
index 0000000..c1086b8
--- /dev/null
@@ -0,0 +1,220 @@
+#include "MetronomeHaptic.hpp"
+
+#include "Mixer.hpp"
+
+#ifdef WIN32
+#include <time.h>
+#include <windows.h>
+#include "SerialWindows.hpp"
+#else
+#include <sys/time.h>
+#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)\r
+{\r
+       Metronome::setTempo(tempo);\r
+       //send info to Serial Port\r
+       //char outBuffer[5];\r
+       char outBuffer[5];// = {'T', 'A', 'B', 'C', 'D'};\r
+       memset(outBuffer, 0, 5);
+       /*sprintf(OUTBUFFER, "T%3d\n", 60000000/tempo);*/\r
+       outBuffer[0] = 'T';\r
+       outBuffer[1] = (tempo & 0xff000000) >> 24;\r
+       outBuffer[2] = (tempo & 0x00ff0000) >> 16;\r
+       outBuffer[3] = (tempo & 0x0000ff00) >> 8;\r
+       outBuffer[4] = tempo & 0x000000ff;\r
+       
+       bool written = _comport->WriteData(outBuffer, 5);\r
+       /*
+       char INBUFFER[128];\r
+       memset(INBUFFER, 0, 128);
+       int nbread = _comport->ReadData(INBUFFER, 128);
+                       stringstream s;
+                       s << nbread << " read:\n" << INBUFFER << endl;
+                       OutputDebugString(s.str().c_str());*/
+}\r
+
+void MetronomeHaptic::setNbBeats(uint32_t nbbeats)
+{
+       Metronome::setNbBeats(nbbeats);\r
+       //send info to Serial Port\r
+       char outBuffer[5];// = {'B', '5', '6', '7', '8'};\r
+       memset(outBuffer, 0, 5);
+/*     sprintf(OUTBUFFER, "B%3d\n", nbbeats);*/\r
+       outBuffer[0] = 'B';\r
+       outBuffer[1] = (nbbeats & 0xff000000) >> 24;\r
+       outBuffer[2] = (nbbeats & 0x00ff0000) >> 16;\r
+       outBuffer[3] = (nbbeats & 0x0000ff00) >> 8;\r
+       outBuffer[4] = nbbeats & 0x000000ff;\r
+       \r
+       bool written = _comport->WriteData(outBuffer, 5);\r
+
+/*     char INBUFFER[128];\r
+       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<MetronomeHaptic *>(obj);
+
+       SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
+
+       const list<Pair<uint32_t, uint32_t> > *bips = thismetronome->_track->getBips();
+       //const map<uint32_t, Pair<float, uint32_t> > *tempo = thismetronome->_track->getTempos();
+    const map<uint32_t, Pair<uint32_t, uint32_t> > *timesignatures = thismetronome->_track->getTimeSignatures();
+       static list<Pair<uint32_t, uint32_t> >::const_iterator cBips = bips->begin();
+       //static map<uint32_t, Pair<float, uint32_t> >::const_iterator cTempo = tempo->begin();
+       static map<uint32_t, Pair<uint32_t, uint32_t> >::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];\r
+       outBuffer[0] = 'S';\r
+       outBuffer[1] = 0;\r
+       outBuffer[2] = 0;\r
+       outBuffer[3] = 0;\r
+       outBuffer[4] = 0;\r
+       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];\r
+                       outBuffer[0] = 'N';\r
+                       outBuffer[1] = ((*cBips).getY() & 0xff000000) >> 24;\r
+                       outBuffer[2] = ((*cBips).getY() & 0x00ff0000) >> 16;\r
+                       outBuffer[3] = ((*cBips).getY() & 0x0000ff00) >> 8;\r
+                       outBuffer[4] = (*cBips).getY() & 0x000000ff;\r
+       \r
+                       bool written = thismetronome->_comport->WriteData(outBuffer, 5);\r
+
+                       cBips++;
+               }
+
+               // on avance tant que les tempos sont dépassées
+               while (cTimesignature != timesignatures->end() && TIMESTAMP(*cTimesignature) < currenttime - BEFOREDELAY)
+               {
+                       char outBuffer[5];\r
+                       outBuffer[0] = 'T';\r
+                       outBuffer[1] = ((*cTimesignature).second.getY() & 0xff000000) >> 24;\r
+                       outBuffer[2] = ((*cTimesignature).second.getY() & 0x00ff0000) >> 16;\r
+                       outBuffer[3] = ((*cTimesignature).second.getY() & 0x0000ff00) >> 8;\r
+                       outBuffer[4] = (*cTimesignature).second.getY() & 0x000000ff;\r
+       \r
+                       bool written = thismetronome->_comport->WriteData(outBuffer, 5);\r
+                               
+                       cTimesignature++;
+               }
+
+               SDL_Delay(5);
+       }
+       return 0;
+}
+
+/*
+int MetronomeHaptic::thread_func(void *obj)
+{
+       MetronomeHaptic *thismetronome = static_cast<MetronomeHaptic *>(obj);
+
+       SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
+
+       const map<uint32_t, Pair<float, uint32_t> > *tempo = thismetronome->_track->getTempos();
+    const map<uint32_t, Pair<float, uint32_t> > *timesignatures = thismetronome->_track->getTimeSignatures();
+       static map<uint32_t, Pair<float, uint32_t> >::const_iterator cTempo = tempo->begin();
+       static map<uint32_t, Pair<float, uint32_t> >::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
index b11e10d1ad60fea451a92e8926df5c4d41c71b58..206b7e9bf08530ffaf157fcba92063106f92ddbc 100644 (file)
@@ -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 (file)
index 0000000..7898324
--- /dev/null
@@ -0,0 +1,10 @@
+#include "Serial.hpp"\r
+\r
+Serial::Serial(char *portName)\r
+:_connected(false)\r
+{\r
+}\r
+\r
+Serial::~Serial()\r
+{\r
+}\r
diff --git a/src/SerialWindows.cpp b/src/SerialWindows.cpp
new file mode 100644 (file)
index 0000000..927cfae
--- /dev/null
@@ -0,0 +1,141 @@
+#include "SerialWindows.hpp"\r
+\r
+#include <iostream>\r
+using namespace std;\r
+
+#ifdef WIN32
+#include <SDL.h>
+#include <windows.h>
+#else
+#include <SDL/SDL.h>
+#endif
+\r
+SerialWindows::SerialWindows(char *portName)\r
+:Serial(portName)\r
+{\r
+    //Try to connect to the given port throuh CreateFile\r
+    _hSerial = CreateFile(portName,\r
+            GENERIC_READ | GENERIC_WRITE,\r
+            0,\r
+            NULL,\r
+            OPEN_EXISTING,\r
+            FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, //FILE_ATTRIBUTE_NORMAL,\r
+            NULL);\r
+\r
+    //Check if the connection was successfull\r
+    if(_hSerial == INVALID_HANDLE_VALUE)\r
+    {\r
+        //If not success full display an Error\r
+        if(GetLastError() == ERROR_FILE_NOT_FOUND)\r
+            cerr << "ERROR: Handle was not attached. Reason: " << portName << " not available." << endl;\r
+        else\r
+            cerr << "ERROR unknown" << endl;\r
+    }\r
+    else\r
+    {\r
+       /*      
+       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";*/
+\r
+\r
+        //If connected we try to set the comm parameters\r
+        DCB dcbSerialParams = {0};\r
+\r
+        //Try to get the current\r
+        if (!GetCommState(_hSerial, &dcbSerialParams))\r
+            //If impossible, show an error\r
+            cerr << "ERROR: failed to get current serial parameters!" << endl;\r
+        else\r
+        {\r
+            //Define serial connection parameters for the arduino board\r
+            dcbSerialParams.BaudRate=CBR_57600;\r
+            dcbSerialParams.ByteSize=8;\r
+            dcbSerialParams.StopBits=ONESTOPBIT;\r
+            dcbSerialParams.Parity=NOPARITY;\r
+\r
+             //Set the parameters and check for their proper application\r
+             if(!SetCommState(_hSerial, &dcbSerialParams))\r
+                cerr << "ERROR: Could not set Serial Port parameters" << endl;\r
+             else\r
+             {\r
+                 //If everything went fine we're connected\r
+                 _connected = true;\r
+                 //We wait 2s as the arduino board will be reseting\r
+                 SDL_Delay(ARDUINO_WAIT_TIME);\r
+             }\r
+        }\r
+    }\r
+}\r
+\r
+SerialWindows::~SerialWindows()\r
+{\r
+    //Check if we are connected before trying to disconnect\r
+    if(_connected)\r
+    {\r
+        //We're no longer connected\r
+        _connected = false;\r
+        //Close the serial handler\r
+        CloseHandle(_hSerial);\r
+    }\r
+}\r
+\r
+int SerialWindows::ReadData(char *buffer, unsigned int nbChar)\r
+{\r
+    //Number of bytes we'll have read\r
+    DWORD bytesRead = 0;\r
+    //Number of bytes we'll really ask to read\r
+    unsigned int toRead = 0;\r
+\r
+    //Use the ClearCommError function to get status info on the Serial port\r
+    ClearCommError(_hSerial, &_errors, &_status);\r
+\r
+    //Check if there is something to read\r
+    if(_status.cbInQue > 0)\r
+    {\r
+        //If there is we check if there is enough data to read the required number\r
+        //of characters, if not we'll read only the available characters to prevent\r
+        //locking of the application.\r
+        if(_status.cbInQue > nbChar)\r
+                       toRead = nbChar;\r
+        else\r
+                       toRead = _status.cbInQue;\r
+\r
+        //Try to read the require number of chars, and return the number of read bytes on success\r
+        if(ReadFile(_hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0)\r
+            return bytesRead;\r
+    }\r
+\r
+    //If nothing has been read, or that an error was detected return -1\r
+    return -1;\r
+}\r
+\r
+\r
+bool SerialWindows::WriteData(char *buffer, unsigned int nbChar)\r
+{\r
+    DWORD bytesSend;\r
+\r
+    //Try to write the buffer on the Serial port\r
+    if(!WriteFile(_hSerial, (void *)buffer, nbChar, &bytesSend, 0))\r
+    {\r
+        //In case it don't work get comm error and return false\r
+        ClearCommError(_hSerial, &_errors, &_status);\r
+\r
+        return false;\r
+    }\r
+    else\r
+       {\r
+        ClearCommError(_hSerial, &_errors, &_status);\r
+/*             if(!FlushFileBuffers(_hSerial))\r
+                       cout << "ERROR while flushing" << endl;*/\r
+/*             stringstream s;
+               s << bytesSend << " SENT" << endl;
+               OutputDebugString(s.str().c_str());*/
+        return true;\r
+       }\r
+}\r
index d3e8117dc08978c0954d11de29b56a4e43b22c11..925885d6496fbd12b6f39066a7962b1d2f1a7cfe 100644 (file)
@@ -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<uint32_t, Pair<float, uint32_t> >::iterator ti = _tempo.begin();
+               map<uint32_t, Pair<uint32_t, uint32_t> >::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<uint32_t>((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<uint32_t>((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<uint32_t>((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<uint32_t, Pair<float, uint32_t> >::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<uint32_t, Pair<float, uint32_t> >::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<uint32_t, Pair<float, uint32_t> >::iterator ii=_tempo.begin(); ii!=_tempo.end(); ++ii)
-       cout << (*ii).first << ": " << (*ii).second.getX() << " (" << (*ii).second.getY() << ")" << endl;
+   for( map<uint32_t, Pair<uint32_t, uint32_t> >::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<Pair<uint32_t, float> >::const_iterator startingbips = _bips.begin();
+       static list<Pair<uint32_t, uint32_t> >::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<Pair<uint32_t, float> >::const_iterator b = startingbips;
+       list<Pair<uint32_t, uint32_t> >::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<float>(- SECONDSIZE * (*b).getY()));
+               glTranslatef(0, 0, static_cast<float>(- 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<uint32_t,Config>::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<float>(- SECONDSIZE * (*n).second.getPosition()));
+               glTranslatef(0, 0, static_cast<float>(- SECONDSIZE * NOTETIMESTAMP(*n)));
                (*n).second.display();
                glPopMatrix();
                n++;
index 4e8132f80e00c80b5dede004df96db09b550c0c0..962c40b6ef1ed15f4c46b22b573055065cdf0e5b 100644 (file)
@@ -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;
index 8218b048374379e61603a2dbe541905ee9166b53..167f656e5d13b242263c50177b0d3cc56140b5dd 100644 (file)
@@ -6,6 +6,7 @@
 #include "PaintGame.h"
 #include "Metronome.hpp"
 #include "MetronomeAudio.hpp"
+#include "MetronomeHaptic.hpp"
 
 #ifdef WIN32
 #include <time.h>
@@ -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);