Hi!
Ich hab grad ein riesiges Problem und hoffe, ihr könnt mir da helfen.
Das Programm, an dem ich gerade schreibe, soll einen MIDI-Track auf einem externen MIDI-Gerät wiedergeben und gleichzeitig (zeitlich synchron) von diesem Gerät etwas aufnehmen. Man muß sich das ganze wie einen MIDI-Recorder vorstellen, der ein etwas komplexeres Metronom bzw eine Begleitautomatik enthält.
Der komplette Code ist ein bischen groß, aber das folgende ist prinzipiell das, was ich gemacht hab:
Wenn man's laufen lässt, schaut auf den ersten Blick alls super aus. Das Abspielen läuft und es passiert auch tatsächlich in dem Tempo, das ich vorher mit setTempoInBPM(...) angegeben hab. Nach dem erwartungsgemäßen Beenden (ohne Exceptions etc. und nach der erwarteten Zeit) des Abspielens sind auch tatsächlich MidiEvents im record_track drin. Wenn man dann aber genauer hinschaut, fällt einem das Problem auf:
Die Tick-Informationen der MIDI-Messages im record_track basieren allesamt auf einem Tempo von 120bpm, ganz egal, was man vorher mit setTempoInBPM(...) einstellt.
Als Sequencerimplementierung wird der "com.sun.media.sound.RealTimeSequencer" verwendet.
Ich hab auch schonmal versucht, die SlaveSyncModes zu wechseln, aber das einzige, was der RealTimeSequencer kann ist "No Timing".
Ich hab keine Ahnung, ob das Problem auf einem Programmierfehler meinerseits beruht oder auf einem Bug im RealTimeSequencer (oder einfach das von mir verwendeten MIDI-Keyboard spinnt).
Was kann ich da machen ums ans Laufen zu kriegen? Was mach ich evtl. falsch?
Schon jetzt vielen Dank!
Tom
Ich hab grad ein riesiges Problem und hoffe, ihr könnt mir da helfen.
Das Programm, an dem ich gerade schreibe, soll einen MIDI-Track auf einem externen MIDI-Gerät wiedergeben und gleichzeitig (zeitlich synchron) von diesem Gerät etwas aufnehmen. Man muß sich das ganze wie einen MIDI-Recorder vorstellen, der ein etwas komplexeres Metronom bzw eine Begleitautomatik enthält.
Der komplette Code ist ein bischen groß, aber das folgende ist prinzipiell das, was ich gemacht hab:
Java:
//set up the devices and the sequencer
midi_sequencer = (Sequencer)MidiSystem.getMidiDevice( midi_sequencer_info );
midi_out_device = MidiSystem.getMidiDevice( midi_out_device_info );
midi_in_device = MidiSystem.getMidiDevice( midi_in_device_info );
// build the sequence for recording and for playback
Sequence seq = new Sequence( Sequence.PPQ, ticks_per_quarter );
// add a track with playback data
fillTrack( seq.createTrack() );
// add a track into which the recorded data will be transferred
Track track_record = seq.createTrack();
// assign the sequence to the sequencer and record-enable the record_track
midi_sequencer.setSequence( seq );
midi_sequencer.recordEnable( track_record, -1 );
// open the devices and the sequencer
midi_out_device.open();
midi_sequencer.open();
midi_in_device.open();
// set transmitters and receivers from the sequencer
midi_sequencer.getTransmitter().setReceiver( midi_out_device.getReceiver() );
midi_in_device.getTransmitter().setReceiver( midi_sequencer.getReceiver() );
// set the tempo (shouldn't this method be responsible for the playback
// tempo as well as for the recording tempo?)
midi_sequencer.setTempoInBPM( 80 );
// do it - start recording AND playback
midi_sequencer.startRecording();
while( midi_sequencer.isRunning() ){ // wait for playback to finish and then also stop recording
Thread.sleep( 25 );
} // play back has finished
midi_sequencer.stopRecording();
// close sequencer and devices
midi_in_device.close();
midi_sequencer.close();
midi_out_device.close();
// print the recorded data
for( int i = 0; i < track_record.size(); i++ ){
MidiEvent ev = track_record.get( i );
if( ev.getMessage() instanceof ShortMessage ){
ShortMessage msg = (ShortMessage)ev.getMessage();
if( msg.getCommand() == ShortMessage.NOTE_ON && msg.getData2() > 0 ){
System.out.println( ev.getTick() + " " + msg.getData1() + " " + msg.getData2() );
}
}
}
Die Tick-Informationen der MIDI-Messages im record_track basieren allesamt auf einem Tempo von 120bpm, ganz egal, was man vorher mit setTempoInBPM(...) einstellt.
Als Sequencerimplementierung wird der "com.sun.media.sound.RealTimeSequencer" verwendet.
Ich hab auch schonmal versucht, die SlaveSyncModes zu wechseln, aber das einzige, was der RealTimeSequencer kann ist "No Timing".
Ich hab keine Ahnung, ob das Problem auf einem Programmierfehler meinerseits beruht oder auf einem Bug im RealTimeSequencer (oder einfach das von mir verwendeten MIDI-Keyboard spinnt).
Was kann ich da machen ums ans Laufen zu kriegen? Was mach ich evtl. falsch?
Schon jetzt vielen Dank!
Tom