|
@@ -0,0 +1,83 @@
|
|
|
+#include <iostream>
|
|
|
+#include <thread>
|
|
|
+#include <mutex>
|
|
|
+#include <chrono>
|
|
|
+
|
|
|
+class Loop
|
|
|
+{
|
|
|
+ std::thread loopThread;
|
|
|
+ std::chrono::milliseconds lastBeatTime;
|
|
|
+ unsigned short bpm;
|
|
|
+ std::mutex bpmLock;
|
|
|
+ bool stopNext;
|
|
|
+
|
|
|
+public:
|
|
|
+ bool enabled;
|
|
|
+
|
|
|
+ Loop()
|
|
|
+ : bpm(60), stopNext(false), enabled(false), loopThread(&Loop::loop, this)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ ~Loop()
|
|
|
+ {
|
|
|
+ stopNext = true;
|
|
|
+ loopThread.join();
|
|
|
+ }
|
|
|
+
|
|
|
+ void setBpm(unsigned short b)
|
|
|
+ {
|
|
|
+ bpmLock.lock();
|
|
|
+ bpm = b;
|
|
|
+ bpmLock.unlock();
|
|
|
+ }
|
|
|
+
|
|
|
+ unsigned short getBpm()
|
|
|
+ {
|
|
|
+ bpmLock.lock();
|
|
|
+ unsigned short r = bpm;
|
|
|
+ bpmLock.unlock();
|
|
|
+ return r;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::chrono::milliseconds getBeatDuration()
|
|
|
+ {
|
|
|
+ return std::chrono::milliseconds(
|
|
|
+ (long long)((double)60 * 1000 / bpm)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ void start()
|
|
|
+ {
|
|
|
+ enabled = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ void stop()
|
|
|
+ {
|
|
|
+ enabled = false;
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ std::chrono::milliseconds getMillisecondsSinceEpoch()
|
|
|
+ {
|
|
|
+ std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
|
|
+ std::chrono::system_clock::duration duration = now.time_since_epoch();
|
|
|
+ return std::chrono::duration_cast<std::chrono::milliseconds>(duration);
|
|
|
+ }
|
|
|
+
|
|
|
+ void beat()
|
|
|
+ {
|
|
|
+ std::cout << "\a" << lastBeatTime.count() << std::endl;
|
|
|
+ }
|
|
|
+
|
|
|
+ void loop()
|
|
|
+ {
|
|
|
+ while(!stopNext) {
|
|
|
+ if((getMillisecondsSinceEpoch() - lastBeatTime) >= getBeatDuration()) {
|
|
|
+ lastBeatTime = getMillisecondsSinceEpoch();
|
|
|
+ beat();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|