简体   繁体   English

如何在自己的线程上运行时钟

[英]How to run a clock on its own thread

I'm trying to create a step sequencer in C++ that will eventually send out MIDI data. 我试图用C ++创建一个步进音序器,最终将发送MIDI数据。 I created it by having a clock on its own thread that calculates the amount of time since the last beat, and if it is time for the next beat, it writes a piece of data to the console. 我通过在自己的线程上放置一个时钟来计算它,该时钟计算自上一个拍子以来的时间,如果是下一个拍子的时间,它将向控制台写入一条数据。

However, I find that no matter what I set the BPM to, I get messages at a rate that is obviously too slow. 但是,我发现无论将BPM设置为什么,我收到消息的速度显然都太慢了。 I can't seem to figure out why the timing on this thread is wrong, and it doesn't help that I'm not terribly familiar with how the std::chrono library works. 我似乎无法弄清楚为什么此线程上的计时错误,并且对std::chrono库的工作方式不甚了解也无济于事。 Thoughts? 有什么想法吗?

Code below: 代码如下:

#include <thread>
#include <mutex>
#include <chrono>
#include <vector>
#include <iostream>

class StepSequencer {
 public:
  StepSequencer();
  ~StepSequencer();
  void run();
  void setBeatsPerMinute(float bpm);
  void addNote(int noteValue, int beatIndex);
  void playNote(int beatIndex);
 protected:
  int mNumberOfBeatBins;
  int mSequencerPlayhead;
  float mBeatsPerMinute;
  float mSecondsPerBeat;
  std::vector<int> mBeatBins;
  std::mutex mMutex;
  std::thread mSequencerThread;
  bool mRunSequencerThread;
  std::chrono::time_point<std::chrono::system_clock> mLastBeatTime;
  std::chrono::time_point<std::chrono::system_clock> mCurrentTime;
};

#include "stdafx.h"
#include "StepSequencer.h"

StepSequencer::StepSequencer() {
  mNumberOfBeatBins = 16;
  for(int i = 0; i < 16; i++) {
    mBeatBins.push_back(0);
  }

  mBeatsPerMinute = 0;
  mSecondsPerBeat = 1;

  mLastBeatTime = std::chrono::system_clock::now();
  mCurrentTime = std::chrono::system_clock::now();

  mSequencerPlayhead = 0;

    mRunSequencerThread = false;
    mSequencerThread = std::thread(&StepSequencer::run, this);
}

StepSequencer::~StepSequencer() {
  if(mSequencerThread.joinable()) {
    mSequencerThread.join();
  }
}

void StepSequencer::run() {
  mRunSequencerThread = true;
  while(mRunSequencerThread) {
        mCurrentTime = std::chrono::system_clock::now();
    mMutex.lock();
        if (std::chrono::duration_cast<std::chrono::seconds>(mCurrentTime - mLastBeatTime).count() > mSecondsPerBeat) {
      mSequencerPlayhead++;
      mSequencerPlayhead = mSequencerPlayhead % mNumberOfBeatBins;
      playNote(mSequencerPlayhead);
            mLastBeatTime = std::chrono::system_clock::now();
    }
    mMutex.unlock();
    this_thread::sleep_for(std::chrono::milliseconds(1));
  }
} 

void StepSequencer::setBeatsPerMinute(float bpm) {
  mMutex.lock();
  mBeatsPerMinute = bpm;
  if(mBeatsPerMinute > 0) {
      mSecondsPerBeat = 60.0 / mBeatsPerMinute;
  }
  else {
    mSecondsPerBeat = 1;
  }
 mMutex.unlock();
}

void StepSequencer::addNote(int noteValue, int beatIndex) {
  mBeatBins[beatIndex] = noteValue;
}

void StepSequencer::playNote(int beatIndex) {
  std::cout << mBeatBins[beatIndex] << std::endl;
}

std::chrono::seconds has a representation of 'A signed integral type of at least 35 bits'. std::chrono::seconds具有“至少35位的带符号整数类型”的表示形式。 So you are going to get a value of count() which increments only once per second, giving the option of 60,30,20,15,12, etc. beats per minute. 因此,您将获得count()的值,该值每秒仅增加一次,并提供每分钟60、30、20、15、12等节拍的选项。

Work in milliseconds or use a custom duration which is backed by a floating point value instead. 以毫秒为单位工作,或者使用自定义的持续时间,该持续时间由浮点值支持。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 让类完全在自己的线程上运行 - Having a class run entirely on its own thread 使用Windows API和C ++,如何从硬盘驱动器加载exe并在其自己的线程中运行它? - Using the windows api and C++, how could I load an exe from the hard drive and run it in its own thread? 如何链接非线程安全库,以便每个线程都有自己的全局变量? - How to link non thread-safe library so each thread will have its own global variables from it? 管理自己的boost :: thread的Singleton对象 - Singleton object that manages its own boost::thread 每个线程都有自己的堆栈吗? - Does each thread have its own stack? boost :: python-如何从C ++在自己的线程中调用python函数? - boost::python - how to invoke a python function in its own thread from C++? 如何让每个线程在C ++ 11中使用自己的RNG - how to make each thread use its own RNG in C++11 如何将现有功能放入其自己的连续(循环)线程并将更新的参数传递给它? - How to put an existing funtion into its own continuous (looping) thread and pass updated parameters to it? 使用lambda表达式创建线程时,如何为每个线程提供自己的lambda表达式副本? - When creating threads using lambda expressions, how to give each thread its own copy of the lambda expression? 如何在C中以较低的时钟速度运行程序 - How to run a program at a lower clock speed in C
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM