andrewm@11: /* andrewm@11: TouchKeys: multi-touch musical keyboard control software andrewm@11: Copyright (c) 2013 Andrew McPherson andrewm@11: andrewm@11: This program is free software: you can redistribute it and/or modify andrewm@11: it under the terms of the GNU General Public License as published by andrewm@11: the Free Software Foundation, either version 3 of the License, or andrewm@11: (at your option) any later version. andrewm@11: andrewm@11: This program is distributed in the hope that it will be useful, andrewm@11: but WITHOUT ANY WARRANTY; without even the implied warranty of andrewm@11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the andrewm@11: GNU General Public License for more details. andrewm@11: andrewm@11: You should have received a copy of the GNU General Public License andrewm@11: along with this program. If not, see . andrewm@11: andrewm@11: ===================================================================== andrewm@11: andrewm@11: TouchkeyEntropyGenerator.cpp: generate random TouchKeys data for testing andrewm@11: */ andrewm@11: andrewm@11: #include "TouchkeyEntropyGenerator.h" andrewm@13: #include andrewm@11: andrewm@11: TouchkeyEntropyGenerator::TouchkeyEntropyGenerator(PianoKeyboard& keyboard) andrewm@11: : Thread("TouchkeyEntropyGenerator"), keyboard_(keyboard), andrewm@11: waitableEvent_(true), isRunning_(false), andrewm@11: keyboardRangeLow_(36), keyboardRangeHigh_(60), andrewm@11: dataInterval_(milliseconds_to_timestamp(5.0)) andrewm@11: { andrewm@13: srand(time(NULL)); andrewm@11: } andrewm@11: andrewm@11: // Start the thread handling the scheduling. andrewm@11: void TouchkeyEntropyGenerator::start() { andrewm@11: if(isRunning_) andrewm@11: return; andrewm@11: // Initialize the touch data before starting andrewm@11: for(int i = 0; i <= 127; i++) { andrewm@11: clearTouchData(i); andrewm@11: nextOnOffFrameCount_[i] = abs(rand()) % 8192; andrewm@11: } andrewm@11: isRunning_ = true; andrewm@11: startThread(); andrewm@11: } andrewm@11: andrewm@11: // Stop the scheduler thread if it is currently running. andrewm@11: void TouchkeyEntropyGenerator::stop() { andrewm@11: if(!isRunning_) andrewm@11: return; andrewm@11: andrewm@11: // Tell the thread to quit and signal the event it waits on andrewm@11: signalThreadShouldExit(); andrewm@11: stopThread(-1); andrewm@11: andrewm@11: isRunning_ = false; andrewm@11: } andrewm@11: andrewm@11: // Run the entropy generator in its own thread andrewm@11: void TouchkeyEntropyGenerator::run() { andrewm@11: timestamp_type lastDataTime = keyboard_.schedulerCurrentTimestamp(); andrewm@11: timestamp_type currentTime; andrewm@11: andrewm@11: while(!threadShouldExit()) { andrewm@11: // Generate random data at regular intervals andrewm@11: currentTime = keyboard_.schedulerCurrentTimestamp(); andrewm@11: while(currentTime - lastDataTime < dataInterval_ && !threadShouldExit()) { andrewm@11: waitableEvent_.wait(1); andrewm@11: currentTime = keyboard_.schedulerCurrentTimestamp(); andrewm@11: } andrewm@11: andrewm@11: for(int i = keyboardRangeLow_; i <= keyboardRangeHigh_; i++) { andrewm@11: if(touchFrames_[i].count != 0) { andrewm@11: // This key is on. Check if it should go off; otherwise generate new data andrewm@11: if(--nextOnOffFrameCount_[i] <= 0) { andrewm@11: clearTouchData(i); andrewm@11: if(keyboard_.key(i) != 0) andrewm@11: keyboard_.key(i)->touchOff(currentTime); andrewm@11: nextOnOffFrameCount_[i] = abs(rand()) % 8192; andrewm@11: } andrewm@11: else { andrewm@11: generateRandomFrame(i); andrewm@11: if(keyboard_.key(i) != 0) { andrewm@11: KeyTouchFrame copyFrame(touchFrames_[i]); andrewm@11: keyboard_.key(i)->touchInsertFrame(copyFrame, currentTime); andrewm@11: } andrewm@11: } andrewm@11: } andrewm@11: else { andrewm@11: // This key is off. Check if it should go on andrewm@11: if(--nextOnOffFrameCount_[i] <= 0) { andrewm@11: generateRandomFrame(i); andrewm@11: if(keyboard_.key(i) != 0) { andrewm@11: KeyTouchFrame copyFrame(touchFrames_[i]); andrewm@11: keyboard_.key(i)->touchInsertFrame(copyFrame, currentTime); andrewm@11: } andrewm@11: nextOnOffFrameCount_[i] = abs(rand()) % 8192; andrewm@11: } andrewm@11: } andrewm@11: } andrewm@11: } andrewm@11: andrewm@11: // Tell all currently enabled notes to turn off andrewm@11: for(int i = 0; i < 128; i++) { andrewm@11: if(touchFrames_[i].count > 0 && keyboard_.key(i) != 0) andrewm@11: keyboard_.key(i)->touchOff(currentTime); andrewm@11: } andrewm@11: } andrewm@11: andrewm@11: // Clear touch data for a particular key andrewm@11: void TouchkeyEntropyGenerator::clearTouchData(int i) { andrewm@11: touchFrames_[i].count = 0; andrewm@11: touchFrames_[i].locH = -1.0; andrewm@11: touchFrames_[i].nextId = 0; andrewm@11: for(int j = 0; j < 3; j++) { andrewm@11: touchFrames_[i].ids[j] = -1; andrewm@11: touchFrames_[i].locs[j] = -1.0; andrewm@11: touchFrames_[i].sizes[j] = 0; andrewm@11: } andrewm@11: int key = i % 12; andrewm@11: if(key == 1 || key == 3 || key == 6 || key == 8 || key == 10) andrewm@11: touchFrames_[i].white = false; andrewm@11: else andrewm@11: touchFrames_[i].white = true; andrewm@11: } andrewm@11: andrewm@11: // Generate a random frame of touch data on this key andrewm@11: void TouchkeyEntropyGenerator::generateRandomFrame(int key) { andrewm@11: touchFrames_[key].count = 1; andrewm@11: touchFrames_[key].locH = (float)abs(rand()) / (float)RAND_MAX; andrewm@11: touchFrames_[key].locs[0] = (float)abs(rand()) / (float)RAND_MAX; andrewm@11: touchFrames_[key].sizes[0] = (float)abs(rand()) / (float)RAND_MAX; andrewm@11: }