Arduino 16 步音序器 - 音符不同步

Posted

技术标签:

【中文标题】Arduino 16 步音序器 - 音符不同步【英文标题】:Arduino 16-step sequencer - Notes not in sync 【发布时间】:2017-03-06 10:06:24 【问题描述】:

我正在为我的 arduino mega 使用以下代码将 midi 时钟发送到我的鼓机和合成器。 当我也尝试在“节拍”上准确发送 MIDI 音符时,就会出现问题。 只有第一个音符完美同步,其余音符不同步,您可以听到。 代码有什么明显的缺陷吗?

// METRONOME
#include <MIDI.h>

#define LED1PIN 13
#define LED4PIN 7
#define SWITCHAPIN 5
#define SWITCHBPIN 2
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

void setup() 
  pinMode(LED1PIN, OUTPUT);
  pinMode(LED4PIN, OUTPUT);

  pinMode(SWITCHAPIN, INPUT);
  pinMode(SWITCHBPIN, INPUT);

  digitalWrite(SWITCHAPIN, HIGH);
  digitalWrite(SWITCHBPIN, HIGH);

  MIDI.begin(MIDI_CHANNEL_OMNI);
  Serial.begin(9600);
  Serial.println("Setting up");


unsigned long nextClockTime = 0;
int clockDelay = 20;
int tickCount = 0;
byte running = 0;
int pula = 0;
int currentStep = 1;
int lastPulse = 0;
int currPulse = 0;
int nextTickCount = 0;

typedef struct 
  int noteNumber;
  int velocity;
  int noteLength;
  bool enabled;

Step;

Step stepData[100];

void loop() 

  stepData[0].enabled = true;
  stepData[0].velocity = 127;
  stepData[0].noteNumber = 40;
  stepData[23].enabled = true;
  stepData[23].velocity = 127;
  stepData[23].noteNumber = 40;
  stepData[47].enabled = true;
  stepData[47].velocity = 127;
  stepData[47].noteNumber = 40;
  stepData[71].enabled = true;
  stepData[71].velocity = 127;
  stepData[71].noteNumber = 40;
  stepData[95].enabled = true;
  stepData[95].velocity = 127;
  stepData[95].noteNumber = 40;

  MIDI.read();
  unsigned long milliseconds = millis();
  if (milliseconds > nextClockTime) 
    if (running)
      MIDI.sendRealTime(MIDI_NAMESPACE::Clock);

    nextClockTime = milliseconds + clockDelay;
    nextTickCount = tickCount + 1;
    if (tickCount == 0) 
      if (stepData[tickCount].enabled) 
        MIDI.sendNoteOn(stepData[tickCount].noteNumber, stepData[tickCount].velocity, 1);
        Serial.print("STEP ENABLED: ");
        Serial.println(tickCount);
      
    
    if (tickCount == 23) 
      if (stepData[tickCount].enabled) 
        MIDI.sendNoteOn(stepData[tickCount].noteNumber, stepData[tickCount].velocity, 1);
        Serial.print("STEP ENABLED: ");
        Serial.println(tickCount);
        currPulse = millis(); //1500
        Serial.println(currPulse - lastPulse); //1500-500
        lastPulse = currPulse;
      
    
    if (tickCount == 47) 
      if (stepData[tickCount].enabled) 
        MIDI.sendNoteOn(stepData[tickCount].noteNumber, stepData[tickCount].velocity, 1);
        Serial.print("STEP ENABLED: ");
        Serial.println(tickCount);
        currPulse = millis();
        Serial.println(currPulse - lastPulse);
        lastPulse = currPulse;
      
    
    if (tickCount == 71) 
      if (stepData[tickCount].enabled) 
        MIDI.sendNoteOn(stepData[tickCount].noteNumber, stepData[tickCount].velocity, 1);
        Serial.print("STEP ENABLED: ");
        Serial.println(tickCount);
        currPulse = millis();
        Serial.println(currPulse - lastPulse);
        lastPulse = currPulse;
      
    
    if (tickCount == 95) 
      if (stepData[tickCount].enabled) 
        //MIDI.sendNoteOn(stepData[tickCount].noteNumber, stepData[tickCount].velocity, 1);
        Serial.print("STEP ENABLED: ");
        Serial.println(tickCount);
        currPulse = millis();
        Serial.println(currPulse - lastPulse);
        lastPulse = currPulse;
      
      nextTickCount = 0;
    
    tickCount = nextTickCount;
   else if (digitalRead(SWITCHBPIN) == LOW) 
    if (running) 
      MIDI.sendRealTime(MIDI_NAMESPACE::Stop);
      running = 0;
      digitalWrite(LED4PIN, LOW);
    
   else 
    clockDelay = analogRead(A0) / 10;
  
  if (pula == 0) 
    if (!running) 
      MIDI.sendRealTime(MIDI_NAMESPACE::Start);
      tickCount = 0;
      running = 1;
      digitalWrite(LED4PIN, HIGH);
      pula = 1;
    
  

【问题讨论】:

尝试在尝试运行实时代码的同时不要发送全部串行调试负载... 【参考方案1】:

节拍间隔不均匀。 24 - 1 是 23,48 - 24 是 24 等等。

一个简单的解决方法是将您的第一个节拍设置为 0 而不是 1。不要增加 tickCount,而是将变量 nextTickCount 设置为 tickCount +1,并将其分配给 if (milliseconds &gt; nextClockTime) 条件括号末尾的 tickCount。

另外,当 tickCount 达到 95 时,将 nextTickCount 设置为 0,但不要弹奏任何音符(它将在 0 拍上播放)

【讨论】:

16 步音序器 = 4 拍 => 24ppqn *4 = 96。我错过了什么吗? 不,你是对的,出于某种原因,我很困惑并在思考 2 的幂。不过,您确实需要更改最后一个节拍的处理方式(请参阅编辑) 我实施了您的更改,结果相同..这让我发疯。请查看顶部已编辑的代码。 让 24 和 48 和 72 保持原样。音符应在 0、24、48 和 72 上播放。回零应在 95 我试过了,还是有audibe不同步。我开始认为这个敏感操作的 arduino 计时器可能存在问题。

以上是关于Arduino 16 步音序器 - 音符不同步的主要内容,如果未能解决你的问题,请参考以下文章

从 Arduino Yun 上的 USB 接口获取 MIDI 音符

在播放时捕捉 MIDI 音符?

使用 AudioKit 从 MIDI 文件中读取音符

用 Arduino 播放音乐

AudioKit 5:音序效果

AudioKit iOS - 收到MIDINoteOn 功能