首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何准确设置midi事件的时间戳?

如何准确设置midi事件的时间戳?
EN

Stack Overflow用户
提问于 2015-09-15 11:23:09
回答 1查看 888关注 0票数 0

我正在解析一个midi文件,然后使用MIKMIDI将midi事件发送到连接的合成器,但我会将事件的时间戳四舍五入为整数秒,而不是更具体的毫秒。我需要帮助准确地计算时间。谢谢。//之前定义的类备注{ var symbol:String var octave:Int var midiValue:Int var duration:Float }

代码语言:javascript
复制
let BPM:Double = 75
// Ode to joy simplified
var song:[Note] = [
  Note(symbol: "E", octave: 5),
  Note(symbol: "E", octave: 5),
  Note(symbol: "F", octave: 5),
  Note(symbol: "G", octave: 5),

  Note(symbol: "G", octave: 5),
  Note(symbol: "F", octave: 5),
  Note(symbol: "E", octave: 5),
  Note(symbol: "D", octave: 5),

  Note(symbol: "C", octave: 5),
  Note(symbol: "C", octave: 5),
  Note(symbol: "D", octave: 5),
  Note(symbol: "E", octave: 5),

  Note(symbol: "E", octave: 5, duration: 3/8),
  Note(symbol: "D", octave: 5, duration: 1/8),
  Note(symbol: "D", octave: 5, duration: 1/2)
]
let now = NSDate()
let totalDuration:Double = 0
for note:Note in song {
  let fullNoteValue:Double = (60000 / BPM) * 0.001 * 4
  let noteDuration:Double = fullNoteValue * Double(note.duration)
  let timestamp = now.dateByAddingTimeInterval(noteDuration + totalDuration)
  MidiDevice.sharedInstance().playNoteOn(note.midiValue, withTimestamp: timestamp)
  totalDuration += noteDuration
}

MidiDevice playNoteOn定义

代码语言:javascript
复制
- (void)playNoteOn:(NSInteger)note withTimestamp:(MIDITimeStamp)timestamp {
  MIKMutableMIDINoteOnCommand *noteOn = [MIKMutableMIDINoteOnCommand commandForCommandType:MIKMIDICommandTypeNoteOn];
  noteOn.note = (NSUInteger) note;
  noteOn.velocity = 100;
  noteOn.timestamp = timestamp
  // noteOn.midiTimestamp = timestamp;

  NSMutableArray *destinations = [NSMutableArray array];

  for (MIKMIDIDevice *device in [[MIKMIDIDeviceManager sharedDeviceManager] availableDevices]) {
    for (MIKMIDIEntity *entity in [device.entities valueForKeyPath:@"@unionOfArrays.destinations"]) {
      [destinations addObject:entity];
    }
  }

  //  NSArray *destinations = [self.device.entities valueForKeyPath:@"@unionOfArrays.destinations"];
  if (![destinations count]) return;
  for (MIKMIDIDestinationEndpoint *destination in destinations) {
    NSError *error = nil;
    if(![self.deviceManager sendCommands:@[noteOn] toEndpoint:destination error:&error]) {
      NSLog(@"Unable to send command %@ to endpoint %@: %@", noteOn, destination, error);
    }
  }
}

如何将此时间戳更改为可以使用MIDISend()或MIKMIDI发送的准确时间戳?

EN

回答 1

Stack Overflow用户

发布于 2015-09-15 12:18:28

您正在使用不兼容的时间度量。首先,你这样说:

代码语言:javascript
复制
let now = NSDate()
let timestamp = now.dateByAddingTimeInterval(noteDuration + totalDuration)

然后你把它交给midi设备:

代码语言:javascript
复制
 MidiDevice.sharedInstance().playNoteOn(note.midiValue, withTimestamp: timestamp)

但这里的时间戳应该是一个MIDITimeStamp:

代码语言:javascript
复制
(void)playNoteOn:(NSInteger)note withTimestamp:(MIDITimeStamp)timestamp {

MIDITimeStamp不是NSDate!MIDITimeStamp基于mach_absolute_time(),这是一种完全不同的度量。NSDate是以NSTimeInterval度量的,它是某个固定参考日期-时间的重复计数秒数。马赫绝对时间是一个巨大的整数,从计算机开机开始计算纳秒!

因此,要成功调用此方法,您需要去掉NSDate,并在MIDI时间内思考。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32577178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档