From 4020dd4442cdda200eeda71dbf2f9cd6a7e7cdf4 Mon Sep 17 00:00:00 2001 From: Thomas Pietrzak Date: Fri, 27 May 2011 21:10:20 +0000 Subject: [PATCH] Haptic metronome, speed accuracy track generation git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@17 47cf9a05-e0a8-4ed5-9e9b-101a649bc004 --- Haptic Metronome/Haptic Metronome.suo | Bin 28160 -> 29184 bytes include/Config.hpp | 4 +- include/Mixer.hpp | 7 +- include/Serial.hpp | 4 +- include/SerialWindows.hpp | 4 +- include/Track.hpp | 2 + src/Config.cpp | 6 ++ src/MetronomeHaptic.cpp | 115 ++++++++++++++++++++------ src/Mixer.cpp | 23 ++++-- src/PaintGame.cpp | 11 ++- src/SerialWindows.cpp | 6 +- src/Track.cpp | 37 ++++++++- src/main.cpp | 29 ++++++- 13 files changed, 198 insertions(+), 50 deletions(-) diff --git a/Haptic Metronome/Haptic Metronome.suo b/Haptic Metronome/Haptic Metronome.suo index d2e0b3597d8d7369693f48d36ba97919d122e037..8e8eb835a6076069edf1f2140bcf3a3c5d669745 100644 GIT binary patch delta 1580 zcmZXU4Nz277>3VT?y|csAq%*%LF2Np4Du@kvWUX+6C=X}C?pJ`g0P`RX?3Rzn^@2$ zM$=(EGd0unL+Uh6HBE369s6NdFcD0a%2J{-l@u+d+J-4d=soM*9h%P0Gw1!j@4ffj zd(YX=K0)nQ=|^uULT2awJJ<(`2*WZ$NG9-=vY@%q#CjeKlcp7Ql;*K$VR7*EoNn-N z)L9w;gMB4y6^7MTNFK7W;CSXV3DORwdy$YKXCyJwEvVxWCHp+0v5GlDlbFX?q2>!N z@mr(a3UxZ72mIF9ayB5OF;8r{h8mEy_$y{_Me>*{1a%^^(Q-u+6Go|qE<&jHo0Ht? zSOigWB5(*orD3hfC9KfAvNz=h71Bu#k#40vs?g9#RAXc-6VofyMg-x$geM&|)W^S<*!)^4#eyY+8f)%nt%+=uTD43$6LP#CA}NX7wQ z#+>=PG?X93G~Cd8j>Q7`;1yH}335^r3->Ej*a)H|E*4$(GV3bNkxrDPC|GJ~CsVCS zW8-CRK}m}IRc5Tz>p#ZzzTt#e2#St*Z=hOJNBg{LTXnHM&*vi3{e{pmK4Yh3-I7A} zFZt_nP6u?TH)htdY^h~kIAwdX%W&8ZGe>o-v~~4nrT!8B1x9BTGzCSz^)3n~g#2wK zv8IBm&4?o8jP^~4BLG91v_w+2+p;NQ{t<4Jk8lVa2ds9s-?El%Yz(J_wbgCc)wCaJ zI$5@_xW1&XelF2wQQDvO!^~ByPA%b(b%_enIbkwYavgzf_eG>=Kn7@I$Y~CW~T4#dT;Vs zSNHmN0Z18yUV94hyWT8eJ?jj-iJ-AW-G8rj>^yz#&Pc=YGuPKX<(bjH zHKoL(nVG%0+3as3^BRrA=7~2H4!18jT1gK+5q5{WGnh5JL$_g7!ajr8{eJzFn2=`M JI-)@(`Conp;?V#A delta 1035 zcmZ`&ZAep57{2Frmv@$9vpHrTHci8vGq*l8P2JoYGs~@}7`8q{*Gxi3+`#-XZdqgz zmA=0MgZdFfNaZe;n#E$!k3JXFpR!*CMi4}-pd#0M?(Tl{qYDrBdEWE9=RM~==ZGJP zI7jY`vD#9GVb&qa5E~FM&Kh+KsZ?qcij4@$7bbR@$tbsjSfP+xtr3|I35)I-S%kyP zdKl!M@b$>3gjbqUh!t_tfGUy4tyChCup+_n22_@eM=-T=ri@6Me0&~?5+xuBg$b6& z!m0d>MJV>F35_hzM3Ti`h?h6O$r49;q&SnEEb(zXU3+0BB9y%(5a+BQlqckQ&C1B) zA|$8uFlcE~lNHFRrkjwGmLCKhErw{NlTD}Ed_3(G?U=mHq|FOXbDbn^uyKpRi~y5W z%_Ij%^$;sC;K)BJ<#zC7w8lwYAlAgy#D=-XOa-CVOVng7%1R})cmT;amGo=tTarf` ze-HH(g7O*s--lNX>qicLV#5ra2=oCL(1K|Hsk`dhw{klB>#~Bu(~&W#xNU}sRhuE^ z7)r0a5qqb{^lC(U>5Z*0l3Okb&I@c-1c#O~kHFzM1DD*jWJ+dZZ8kECY)E^!uj|OM z?qI;#-*@P6sGBW%uu9 zD?D|dg8AKBny z6l+87rsliyTC|=@F!>EI*$&(q49ll1?C}x#LTpwdORgZffxr(6JKEtumtKk-Vu@t; z>IsN}e%<@IKjYT>z5W@?^9j$ko8Pmr*>=gkk0U&NMJ&yvH%Qq3hv>fSy!9~a!SS}s zL)jmQBU-9Mb3KU0> 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"); } -- 2.30.2