0

MIDI ファイルを解析してから、MIKMIDIを使用して MIDI イベントを接続されたシンセサイザーに送信していますが、イベントのタイムスタンプをより具体的なミリ秒ではなく整数秒に丸めています。時間を正確に計算するのに助けが必要です。ありがとう。// 以前に定義されたクラス Note { var symbol:String var octave:Int var midiValue:Int var duration:Float }

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 の定義

- (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 を使用して送信できる正確なタイムスタンプに変更するにはどうすればよいですか?

4

1 に答える 1

2

互換性のない時間測定を使用しています。最初にこう言います。

let now = NSDate()
let timestamp = now.dateByAddingTimeInterval(noteDuration + totalDuration)

しかし、それを midi デバイスに渡します。

 MidiDevice.sharedInstance().playNoteOn(note.midiValue, withTimestamp: timestamp)

しかし、ここでのタイムスタンプは MIDITimeStamp であることが判明しました。

(void)playNoteOn:(NSInteger)note withTimestamp:(MIDITimeStamp)timestamp {

MIDITimeStamp は NSDate ではありません! mach_absolute_time()MIDITimeStamp は、まったく異なる種類の尺度である に基づいています。NSDate は NSTimeInterval として測定されます。これは、固定参照日付/時間から秒数をカウントする Double です。マッハ絶対時間は、コンピューターの電源を入れてからナノ秒を数えた巨大な整数です!

したがって、このメソッドを正常に呼び出すには、NSDate を取り除き、MIDI 時間で考える必要があります。

于 2015-09-15T04:18:28.333 に答える