From: Thomas Pietrzak Date: Fri, 27 May 2011 21:10:20 +0000 (+0000) Subject: Haptic metronome, speed accuracy track generation X-Git-Url: https://git.thomaspietrzak.com/?a=commitdiff_plain;h=4020dd4442cdda200eeda71dbf2f9cd6a7e7cdf4;p=hapticmetronome.git Haptic metronome, speed accuracy track generation git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@17 47cf9a05-e0a8-4ed5-9e9b-101a649bc004 --- diff --git a/Haptic Metronome/Haptic Metronome.suo b/Haptic Metronome/Haptic Metronome.suo index d2e0b35..8e8eb83 100644 Binary files a/Haptic Metronome/Haptic Metronome.suo and b/Haptic Metronome/Haptic Metronome.suo differ diff --git a/include/Config.hpp b/include/Config.hpp index d208ec1..54d0e54 100644 --- a/include/Config.hpp +++ b/include/Config.hpp @@ -26,7 +26,9 @@ using namespace std; class Config { public: - Config(uint32_t timestamp=0, uint32_t end=0, uint32_t time=0, uint32_t ticks=0, + Config(uint8_t buttons, uint32_t timestamp=0, uint32_t endtimestamp=0, uint32_t time=0, uint32_t ticks=0); + + Config(uint32_t timestamp=0, uint32_t endtimestamp=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); diff --git a/include/Mixer.hpp b/include/Mixer.hpp index ba49c2e..512b3b2 100644 --- a/include/Mixer.hpp +++ b/include/Mixer.hpp @@ -40,15 +40,16 @@ class Mixer public: Mixer(); ~Mixer(); - static void playMusic(const String &); + static void loadMusic(const String &); + static void playMusic(); static void stopMusic(); void playSound(const String &); void stopSound(const int &); bool addSound(const String &s, const String &filename); static void channelStopped(int); - int getMusicVolume() const { return _musicVolume; } + int getMusicVolume() const { return _musicVolume; } void setMusicVolume(const int &); - int getSoundVolume() const { return _soundVolume; } + int getSoundVolume() const { return _soundVolume; } void setSoundVolume(const int &); static void initMixer(); diff --git a/include/Serial.hpp b/include/Serial.hpp index 096fe6f..f306af7 100644 --- a/include/Serial.hpp +++ b/include/Serial.hpp @@ -18,11 +18,11 @@ class Serial //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; + virtual int ReadData(void *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; + virtual bool WriteData(void *buffer, unsigned int nbChar)=0; //Check if we are actually connected bool IsConnected() { return _connected; } diff --git a/include/SerialWindows.hpp b/include/SerialWindows.hpp index 3b99741..28eb1af 100644 --- a/include/SerialWindows.hpp +++ b/include/SerialWindows.hpp @@ -18,10 +18,10 @@ class SerialWindows : public Serial //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); + int ReadData(void *buffer, unsigned int nbChar); //Writes data from a buffer through the Serial connection //return true on success. - bool WriteData(char *buffer, unsigned int nbChar); + bool WriteData(void *buffer, unsigned int nbChar); private: diff --git a/include/Track.hpp b/include/Track.hpp index c5679f6..efcc702 100644 --- a/include/Track.hpp +++ b/include/Track.hpp @@ -42,6 +42,8 @@ class Track Track(const Track &); //create an empty track with the specified tempo and specified duration Track(uint32_t tempo, uint32_t duration); + //create a track for speed/accuracy experiments + Track(uint8_t nbbuttons, uint8_t repetitions, uint8_t nbspeeds, uint32_t *speeds); ~Track(); void addKey(uint32_t time, uint8_t note); diff --git a/src/Config.cpp b/src/Config.cpp index ebe8ea8..fd0bb7e 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -9,6 +9,12 @@ Config::Config(uint32_t timestamp, uint32_t endtimestamp, uint32_t time, uint32_ { } +Config::Config(uint8_t buttons, uint32_t timestamp, uint32_t endtimestamp, uint32_t time, uint32_t ticks) +:_timestamp(timestamp), _endtimestamp(endtimestamp), _time(time), _ticks(ticks), +_a(buttons & 0x01), _b((buttons >> 1) & 0x01), _c((buttons >> 2) & 0x01), _d((buttons >> 3) & 0x01), _e((buttons >> 4) & 0x01) +{ +} + 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) diff --git a/src/MetronomeHaptic.cpp b/src/MetronomeHaptic.cpp index 91af41d..30c1c93 100644 --- a/src/MetronomeHaptic.cpp +++ b/src/MetronomeHaptic.cpp @@ -13,17 +13,69 @@ extern struct timeval start; #endif -#define BEFOREDELAY 150 +#define BEFOREDELAY 2000 extern FILE *logfile; MetronomeHaptic::MetronomeHaptic(const Track *track, uint32_t nbbeats, uint32_t tempo, bool activated) -:Metronome(track, nbbeats, tempo, activated), thread(NULL), _comport(new SerialWindows("COM5")) +:Metronome(track, nbbeats, tempo, activated), thread(NULL), _comport(new SerialWindows("COM3")) { + unsigned char buffer1[3]; + buffer1[0] = 'N'; buffer1[1] = 0x00; buffer1[2] = 0x01; + unsigned char buffer2[6]; + buffer2[0] = 0x01; //pattern + buffer2[1] = 0; buffer2[2] = 100; //duration + buffer2[3] = 0; buffer2[4] = 250; //frequency + buffer2[5] = 255; //amplitude + + //Tacton 1 + _comport->WriteData(buffer1, 3); + _comport->WriteData(buffer2, 6); + +/* 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());*/ + + //Tacton 2 + buffer2[0] = 0x02; //pattern + _comport->WriteData(buffer1, 3); + _comport->WriteData(buffer2, 6); + +/* memset(INBUFFER, 0, 128); + nbread = _comport->ReadData(INBUFFER, 128); + stringstream s2; + s2 << nbread << " read:\n" << INBUFFER << endl; + OutputDebugString(s2.str().c_str());*/ + + //Tacton 3 + buffer2[0] = 0x04; //pattern + _comport->WriteData(buffer1, 3); + _comport->WriteData(buffer2, 6); + +/* memset(INBUFFER, 0, 128); + nbread = _comport->ReadData(INBUFFER, 128); + stringstream s3; + s3 << nbread << " read:\n" << INBUFFER << endl; + OutputDebugString(s3.str().c_str());*/ + + //Tacton 4 + buffer2[0] = 0x08; //pattern + _comport->WriteData(buffer1, 3); + _comport->WriteData(buffer2, 6); + +/* memset(INBUFFER, 0, 128); + nbread = _comport->ReadData(INBUFFER, 128); + stringstream s4; + s4 << nbread << " read:\n" << INBUFFER << endl; + OutputDebugString(s4.str().c_str());*/ } MetronomeHaptic::~MetronomeHaptic() { + _comport->WriteData("Q", 1); _activated = false; delete _comport; SDL_WaitThread(thread, NULL); @@ -34,9 +86,9 @@ 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'}; + /*char outBuffer[5];// = {'T', 'A', 'B', 'C', 'D'}; memset(outBuffer, 0, 5); - /*sprintf(OUTBUFFER, "T%3d\n", 60000000/tempo);*/ + sprintf(OUTBUFFER, "T%3d\n", 60000000/tempo); outBuffer[0] = 'T'; outBuffer[1] = (tempo & 0xff000000) >> 24; outBuffer[2] = (tempo & 0x00ff0000) >> 16; @@ -44,7 +96,7 @@ void MetronomeHaptic::setTempo(uint32_t tempo) outBuffer[4] = tempo & 0x000000ff; bool written = _comport->WriteData(outBuffer, 5); - /* + char INBUFFER[128]; memset(INBUFFER, 0, 128); int nbread = _comport->ReadData(INBUFFER, 128); @@ -57,9 +109,9 @@ void MetronomeHaptic::setNbBeats(uint32_t nbbeats) { Metronome::setNbBeats(nbbeats); //send info to Serial Port - char outBuffer[5];// = {'B', '5', '6', '7', '8'}; +/* char outBuffer[5];// = {'B', '5', '6', '7', '8'}; memset(outBuffer, 0, 5); -/* sprintf(OUTBUFFER, "B%3d\n", nbbeats);*/ + sprintf(OUTBUFFER, "B%3d\n", nbbeats); outBuffer[0] = 'B'; outBuffer[1] = (nbbeats & 0xff000000) >> 24; outBuffer[2] = (nbbeats & 0x00ff0000) >> 16; @@ -68,7 +120,7 @@ void MetronomeHaptic::setNbBeats(uint32_t nbbeats) bool written = _comport->WriteData(outBuffer, 5); -/* char INBUFFER[128]; + char INBUFFER[128]; memset(INBUFFER, 0, 128); int nbread = _comport->ReadData(INBUFFER, 128); stringstream s; @@ -96,7 +148,7 @@ int MetronomeHaptic::thread_func(void *obj) #ifdef WIN32 struct { int tv_sec, tv_usec; } now;//, start - DWORD t = timeGetTime () - BEFOREDELAY; + DWORD t = timeGetTime () + BEFOREDELAY; /* start.tv_sec = t / 1000; start.tv_usec = (t % 1000) * 1000;*/ #else @@ -105,13 +157,10 @@ int MetronomeHaptic::thread_func(void *obj) #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); + bool written = thismetronome->_comport->WriteData("S", 1); + unsigned char outBuffer[6]; + outBuffer[0] = 'P'; + unsigned char currentbeat = 0; while(thismetronome->_activated) { @@ -126,24 +175,33 @@ int MetronomeHaptic::thread_func(void *obj) while (cBips != bips->end() && currenttime >= BIPTIMESTAMP(*cBips)) { - char outBuffer[5]; - outBuffer[0] = 'N'; - outBuffer[1] = (BIPTIMESTAMP(*cBips) & 0xff000000) >> 24; - outBuffer[2] = (BIPTIMESTAMP(*cBips) & 0x00ff0000) >> 16; - outBuffer[3] = (BIPTIMESTAMP(*cBips) & 0x0000ff00) >> 8; - outBuffer[4] = BIPTIMESTAMP(*cBips) & 0x000000ff; - - bool written = thismetronome->_comport->WriteData(outBuffer, 5); +/* char outBuffer[5]; + outBuffer[0] = 'N';*/ + outBuffer[1] = currentbeat % 4; + outBuffer[2] = (BIPTIMESTAMP(*cBips) & 0xff000000) >> 24; + outBuffer[3] = (BIPTIMESTAMP(*cBips) & 0x00ff0000) >> 16; + outBuffer[4] = (BIPTIMESTAMP(*cBips) & 0x0000ff00) >> 8; + outBuffer[5] = BIPTIMESTAMP(*cBips) & 0x000000ff; + + bool written = thismetronome->_comport->WriteData(outBuffer, 6); +/* char INBUFFER[128]; + memset(INBUFFER, 0, 128); + int nbread = thismetronome->_comport->ReadData(INBUFFER, 128); + stringstream s; + s << nbread << " read:\n" << INBUFFER << endl; + OutputDebugString(s.str().c_str());*/ + if (logfile) fprintf(logfile, "BIP;%d;%d;%d\n", BIPTICK(*cBips), BIPTIMESTAMP(*cBips), currenttime); + currentbeat = (currentbeat + 1) % thismetronome->_nbbeats; cBips++; } // on avance tant que les tempos sont dépassées while (cTimesignature != timesignatures->end() && currenttime >= TIMESTAMP(*cTimesignature)) { - char outBuffer[5]; +/* char outBuffer[5]; outBuffer[0] = 'B'; outBuffer[1] = (TIMESTAMP(*cTimesignature) & 0xff000000) >> 24; outBuffer[2] = (TIMESTAMP(*cTimesignature) & 0x00ff0000) >> 16; @@ -151,7 +209,12 @@ int MetronomeHaptic::thread_func(void *obj) outBuffer[4] = TIMESTAMP(*cTimesignature) & 0x000000ff; bool written = thismetronome->_comport->WriteData(outBuffer, 5); - + */ + //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++; } diff --git a/src/Mixer.cpp b/src/Mixer.cpp index 2c22ee7..f895c7a 100644 --- a/src/Mixer.cpp +++ b/src/Mixer.cpp @@ -73,7 +73,7 @@ void Mixer::initMixer() }*/ } -void Mixer::playMusic(const String &filename) +void Mixer::loadMusic(const String &filename) { //_debug_(stderr, "playMusic(%s)\n",filename.c_str()); if (_music) @@ -95,16 +95,16 @@ void Mixer::playMusic(const String &filename) if (buffer != "") { - SDL_mutexP(_mutex); +// SDL_mutexP(_mutex); _music = Mix_LoadMUS(buffer.c_str()); if(_music==NULL) fprintf(stderr, "cannot load music %s\n",buffer.c_str()); - else +/* else { Mix_PlayMusic(_music, -1); Mix_HookMusicFinished(stopMusic); - } - SDL_mutexV(_mutex); + }*/ +// SDL_mutexV(_mutex); } else fprintf(stderr, "music file %s not found\n",filename.c_str()); @@ -113,6 +113,15 @@ void Mixer::playMusic(const String &filename) // cout << "music file " << filename << " not found" << endl; } +void Mixer::playMusic() +{ + if(_music != NULL) + { + Mix_PlayMusic(_music, -1); + Mix_HookMusicFinished(stopMusic); + } +} + void Mixer::stopMusic() { Mix_HaltMusic(); @@ -133,9 +142,9 @@ bool Mixer::addSound(const String &s, const String &filename) snd = _sounds[s]; } - SDL_mutexP(_mutex); +// SDL_mutexP(_mutex); bool res = snd->addSound(filename); - SDL_mutexV(_mutex); +// SDL_mutexV(_mutex); return res; } diff --git a/src/PaintGame.cpp b/src/PaintGame.cpp index b0763da..e585170 100644 --- a/src/PaintGame.cpp +++ b/src/PaintGame.cpp @@ -140,8 +140,10 @@ void init() throw "Impossible to initialize SDL_GL_MULTISAMPLESAMPLES"; // int flags = SDL_OPENGL | SDL_OPENGLBLIT | SDL_SWSURFACE | SDL_FULLSCREEN; - int flags = SDL_OPENGL | SDL_FULLSCREEN; + int flags = SDL_OPENGL;// | SDL_FULLSCREEN; SDL_Surface * screen; + resolution_x = 1024; + resolution_y = 768; // if (!(screen = SDL_SetVideoMode(resolution_x, resolution_y, 0, flags))) if (!(screen = SDL_SetVideoMode(resolution_x, resolution_y, 0, flags))) throw "Impossible to change the video mode"; @@ -634,8 +636,8 @@ void loop(const Track &tr, const String &songname) init(); cout << "Create Metronome" << endl; - Metronome *m = new MetronomeAudio(&tr); -// Metronome *m = new MetronomeHaptic(&tr); +// Metronome *m = new MetronomeAudio(&tr); + Metronome *m = new MetronomeHaptic(&tr); bool quitProgram = false; @@ -649,6 +651,7 @@ void loop(const Track &tr, const String &songname) cout << "Init paint" << endl; initPaint(); + Mixer::getInstance()->loadMusic(songname + "/tout.ogg"); //must be done before paint and metronomes #ifdef WIN32 @@ -662,7 +665,7 @@ void loop(const Track &tr, const String &songname) cout << "LET'S ROCK!" << endl; //m->setActive(true); - Mixer::getInstance()->playMusic(songname + "/tout.ogg"); + Mixer::getInstance()->playMusic(); m->run(); /* Mixer::getInstance()->playSound("guitar"); if (rhythm) diff --git a/src/SerialWindows.cpp b/src/SerialWindows.cpp index 2b6d4d8..73f434e 100644 --- a/src/SerialWindows.cpp +++ b/src/SerialWindows.cpp @@ -84,7 +84,7 @@ SerialWindows::~SerialWindows() } } -int SerialWindows::ReadData(char *buffer, unsigned int nbChar) +int SerialWindows::ReadData(void *buffer, unsigned int nbChar) { //Number of bytes we'll have read DWORD bytesRead = 0; @@ -115,12 +115,12 @@ int SerialWindows::ReadData(char *buffer, unsigned int nbChar) } -bool SerialWindows::WriteData(char *buffer, unsigned int nbChar) +bool SerialWindows::WriteData(void *buffer, unsigned int nbChar) { DWORD bytesSend; //Try to write the buffer on the Serial port - if(!WriteFile(_hSerial, (void *)buffer, nbChar, &bytesSend, 0)) + if(!WriteFile(_hSerial, buffer, nbChar, &bytesSend, 0)) { //In case it don't work get comm error and return false ClearCommError(_hSerial, &_errors, &_status); diff --git a/src/Track.cpp b/src/Track.cpp index 8b709b8..c9e2c20 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include using namespace std; extern Texture* texturesteel, *texturefrett; @@ -19,7 +21,7 @@ Track::Track() { for (uint8_t i = 0 ; i < NBDIFFICULTIES ; i++) { - _currentconfig[i] = 0; + _currentconfig[i] = (uint8_t) 0; _nbnotes[i] = 0; _totallength[i] = 0; } @@ -54,6 +56,39 @@ Track::Track(uint32_t tempo, uint32_t duration) _bips.push_back(Pair(i, i * t / 1000 + 2000)); } +/** + Experimentation track + nbbuttons: maximum buttons + repetitions: repetitions of all buttons configurations for a given speed + nbspeeds: number of speeds + speeds: +*/ +Track::Track(uint8_t nbbuttons, uint8_t repetitions, uint8_t nbspeeds, uint32_t *speeds) +{ + uint32_t tick = 0, timestamp = 2000; + addTimesignature(0, 0, 1); + + for (int n = 0 ; n < nbspeeds ; n++) + { + uint32_t tempo = 60000000 / speeds[n]; + addTempo(tick, timestamp, tempo); + vector configs; + + for (int i = 1 ; i < (int)pow(2.0, (double)nbbuttons) ; i++) + for (int j = 0 ; j < repetitions ; j++) + configs.push_back(i); + random_shuffle(configs.begin(), configs.end()); + + for (vector::iterator it = configs.begin() ; it != configs.end() ; it++) + { + for (int d=0 ; d < NBDIFFICULTIES ; d++) + _notes[d][tick] = Config(*it, timestamp, timestamp+100, tick, 1); + tick++; + timestamp += tempo / 1000; + } + } +} + Track::~Track() { } diff --git a/src/main.cpp b/src/main.cpp index f21bc77..f9df849 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,6 +48,13 @@ int main(int argc, char *argv[]) struct tm *t = gmtime(&tim); cout << "Loading song" << endl; + //6 params => toms law experiment + // v0 = prog + // v1 = condition + // v2 = user + // v3 = speed + // v4 = duration + // v5 = distance if (argc >= 6) { Track tr(atoi(argv[3]), atoi(argv[4])); @@ -61,11 +68,31 @@ int main(int argc, char *argv[]) //run the game with a click track loop(tr, songname); } + //6 params => speed accuracy experiment + // v0 = prog + // v1 = condition + // v2 = user + // v3 = nbbuttons + // v4 = nbrepetitions + else if (argc >= 5) + { + uint32_t speeds[] = {40, 80, 120, 160, 200}; + Track tr(atoi(argv[3]), atoi(argv[4]), 5, speeds); + SECONDSIZE = 0.08; + + String logfilename = String(argv[1]) + "-" + String(argv[2]) + "-" + \ + String(1900 + t->tm_year) + "-" + String(t->tm_mon) + "-" + String(t->tm_mday) + "-" + \ + String(t->tm_hour) + "-" + String(t->tm_min) + "-" + String(t->tm_sec) + "-" + \ + String(argv[3]) + "-" + String(argv[4]); + logfile = fopen(logfilename.c_str(), "w"); + //run the game with the experiment track + loop(tr, songname); + } else { if (argc >= 3) { - String logfilename = String(argv[1]) + "-" + String(argv[2]) + "-" + String(1900 + t->tm_year) + "-" + String(t->tm_mon) + "-" + String(t->tm_mday) + "-" + String(t->tm_hour) + "-" + String(t->tm_min) + "-" + String(t->tm_sec) + "-" + String(argv[1]); + String logfilename = String(argv[1]) + "-" + String(argv[2]) + "-" + String(1900 + t->tm_year) + "-" + String(t->tm_mon) + "-" + String(t->tm_mday) + "-" + String(t->tm_hour) + "-" + String(t->tm_min) + "-" + String(t->tm_sec); logfile = fopen(logfilename.c_str(), "w"); }