[jmsl] Playing Through An External Midi Device
jmsl at music.columbia.edu
jmsl at music.columbia.edu
Wed Apr 15 10:22:49 EDT 2009
Hmm, you're right. When I ran my test, it prints out the device time, but it
doesn't work when I ran your test. It seems like it just plays all 10 notes
at once.
Btw, how can I select different external midi out with new JMSL?
Thanks,
Chi
----- Original Message -----
From: <jmsl at music.columbia.edu>
To: <jmsl at music.columbia.edu>
Sent: Wednesday, April 15, 2009 10:05 AM
Subject: Re: [jmsl] Playing Through An External Midi Device
>I don't understand; the timestamps here are all -1 (!)
>
> The test for timestamped output would go something like this:
>
> // ...
> long timeNow = whateverNowIsAsATimeStamp();
> for (int i=0; i<10; i++) {
> rcvr.send(stopMsg, timeNow + i * whateverOneSecondIs);
> }
> System.out.println("done posting ten timestamped future events");
> // ...
>
> ... in other words this loop will run almost instantly and finish, then
> you should sit back and magically hear the ten events fire off in the
> future, each one perfect second later than the previous, no jitter. No
> MusicJobs, no thread sleep(), nothing like that. Just give rcvr a future
> timestamp and let the underlying Midi engine post them in the future.
>
> Thanks
> Nick
>
> jmsl at music.columbia.edu wrote:
>> Can you try this? Most of my devices supports time stamp.
>>
>> import java.io.BufferedReader;
>> import java.io.IOException;
>> import java.io.InputStreamReader;
>> import javax.sound.midi.InvalidMidiDataException;
>> import javax.sound.midi.MidiDevice;
>> import javax.sound.midi.MidiSystem;
>> import javax.sound.midi.MidiUnavailableException;
>> import javax.sound.midi.Receiver;
>> import javax.sound.midi.ShortMessage;
>> import com.softsynth.jmsl.JMSL;
>> import com.softsynth.jmsl.MusicJob;
>> import com.softsynth.jmsl.SequentialCollection;
>>
>> public class Test extends MusicJob {
>>
>> private MidiDevice device;
>> private Receiver rcvr;
>> private ShortMessage startMsg, stopMsg;
>>
>> public double start(double playTime) {
>> System.out.println("starting at " + device.getMicrosecondPosition());
>> return playTime;
>> }
>>
>> public double repeat(double playTime) {
>> System.out.println("Repeating at " + device.getMicrosecondPosition());
>> rcvr.send(stopMsg, -1);
>> rcvr.send(startMsg, -1);
>> return playTime;
>> }
>>
>> public double stop (double playTime) {
>> System.out.println("Stopping at " + device.getMicrosecondPosition());
>> rcvr.send(stopMsg, -1);
>> System.exit(0);
>> return playTime;
>> }
>>
>> public Test () {
>> initDevice();
>> startMsg = new ShortMessage();
>> try {
>> startMsg.setMessage(ShortMessage.NOTE_ON, 0, 60, 93);
>> } catch (InvalidMidiDataException e) {
>> // e.printStackTrace();
>> }
>> stopMsg = new ShortMessage();
>> try {
>> stopMsg.setMessage(ShortMessage.NOTE_OFF, 0, 60, 93);
>> } catch (InvalidMidiDataException e) {
>> // e.printStackTrace();
>> }
>>
>> }
>>
>> public void initDevice() {
>> MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
>> for (int i = 0; i < infos.length; i++) {
>> System.out.println(i+": "+infos[i]);
>> }
>>
>> BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
>> System.out.println("Which device?");
>> int n = 0;
>> try {
>> n = Integer.parseInt(bf.readLine());
>> } catch (NumberFormatException e) {} catch (IOException e) {
>> // e.printStackTrace();
>> }
>>
>> try {
>> device = MidiSystem.getMidiDevice(infos[n]);
>> } catch (MidiUnavailableException e) {}
>> if (!(device.isOpen())) {
>> try {
>> device.open();
>> } catch (MidiUnavailableException e) {
>> e.printStackTrace();
>> }
>> }
>>
>> try {
>> rcvr = device.getReceiver();
>> } catch (MidiUnavailableException e) {
>> e.printStackTrace();
>> }
>>
>> }
>>
>> public static void main(String[] args) {
>>
>> JMSL.clock.setAdvance(0.1);
>> Test mj = new Test();
>> mj.setRepeats(5);
>> mj.setRepeatPause(2);
>> mj.launch(JMSL.now());
>>
>> }
>>
>> }
>>
>> ----- Original Message ----- From: <jmsl at music.columbia.edu>
>> To: <jmsl at music.columbia.edu>
>> Sent: Wednesday, April 15, 2009 1:48 AM
>> Subject: Re: [jmsl] Playing Through An External Midi Device
>>
>>
>>> Hi Chi
>>>
>>> I have a prerelease posted at http://www.algomusic.com/prerelease/
>>> This prerelease include MidiIO_JavaSound support of external output
>>> devices (not input devices yet)
>>> Thanks very much for your work on this! It helped me get this rolled
>>> into JMSL in a straightforward manner....
>>>
>>> Oddly, JavaSound's device indexes do not distinguish between input and
>>> output devices, so people that use the Midi Device editor will see the
>>> input list is the same as the output list, with all devices listed in
>>> each... I'll fix that later.
>>>
>>> Don't celebrate the timestamps too soon! Even though there is an
>>> argument for timestamps, none of the midi devices I have support the
>>> time stamp. I think it's there as a place holder. I understand the only
>>> way to get accurate MIDI from JavaSound is to use their Real Time
>>> Sequencer. Something to look at. But right now, this works OK: you can
>>> select the midi output device and JMSL.midi will send! For this
>>> prerelease MidiIO_JavaSound is the default midi device for JMSL. But
>>> right now if people want rhythmically accurate MIDI output, use
>>> MidiShare
>>>
>>> A summary of changes since last prerelease follows (note there's a bunch
>>> of music font stuff there, so if any of you have Sonata music font
>>> installed you'll see that JMSL Score looks quite different now!)
>>>
>>> Thanks,
>>> Nick Didkovsky
>>>
>>> JMSL PRERELEASE 20090414
>>> 12/13/08 Fixed bug in
>>> com.softsynth.jmsl.score.midi.WriteScoreMidiFile. Chord Intervals with
>>> Midi Velocities greater than 1 were being multiplied by 128, erroneously
>>> assuming they were amplitudes. Fixed, thanks Georg Hajdu
>>> 12/13/08 MIDIFileToMusicShape now taking absolute values of meta time
>>> signature data. Greg Wilder provided 2 MIDI files which included
>>> negative time signatures that crashed the midi file transcriber.
>>> 12/27/08 TiedNoteAccumulator sets hold time to accumulated duration.
>>> This fixes the problem Joel Mellin discovered when the transcriber
>>> extends long hold times with tied notes and lets them sustain the
>>> full hold time.
>>> 02/02/09 LilyPond export handles colored noteheads now. Thanks Joel
>>> Mellin for feature request. See jmsltestsuite.TwoTracksPerStaff
>>> 02/02/09 Notehead color attribute saved and loaded to/from score xml
>>> 02/02/09 Punos Music plug-in with text-only color chooser for
>>> Notehead Color. "NoteHeadColorTransform". Not a serious color chooser
>>> gui.
>>> 03/06/09 Music Font Rendering using Sonata font, major progress.
>>> noteheads, clefs, stems, expression marks, dynamics, time signatures
>>> 03/06/09 Bug fix: clicking on score canvas triggered two renders.
>>> Removed extra call to score.render()
>>> 04/06/09 ScoreFrame has support to use JavaSound MIDI, searches for
>>> soundbank.gm in classpath/javasound
>>> 04/06/09 run_jmsl_score scripts now include ../classes in classpath
>>> (so that javasound/soundbank.gm can be found)
>>> 04/8/09 MusicGlyphRenderers are per Score now, not static any more
>>> 04/14/09 Support for external MIDI devices in JavaSound MIDI (Thanks
>>> Chi!)
>>> 04/14/09 Default JMSL.midi is now MidiIO_JavaSound (no longer
>>> MidiShare)
>>>
>>>
>>>
>>> jmsl at music.columbia.edu wrote:
>>>> I'm glad it worked. It even supports time stamp, so it's time to ditch
>>>> MidiShare and move to applet! :) JavaSound seem to have bunch of other
>>>> stuff for midi (like writing midi file to OutputStream), so it might be
>>>> worth checking out the program guide when you get a chance.
>>>> How long do you think will take to implement external Midi device
>>>> support with JavaSound? Let me know when you release new jmsl update.
>>>> Thanks,
>>>>
>>>> Chi
>>>> ----- Original Message ----- From: <jmsl at music.columbia.edu>
>>>> To: <jmsl at music.columbia.edu>
>>>> Sent: Tuesday, April 14, 2009 10:43 PM
>>>> Subject: Re: [jmsl] Playing Through An External Midi Device
>>>>
>>>>
>>>>> OK! I can successfully send midi notes to an external piano module
>>>>> using this code. I tested it with two different MIDI interfaces:
>>>>> XSession and Presonus Firepod
>>>>> Works great!
>>>>> thanks
>>>>> Nick
>>>>>
>>>>>
>>>>> jmsl at music.columbia.edu wrote:
>>>>>> Run this and then select the device from the console. It'll play a
>>>>>> short note.
>>>>>> device.getMicrosecondPosition();
>>>>>> This method returns -1 if the device ignores time stamps. Otherwise,
>>>>>> it returns the device's current notion of time, which you as the
>>>>>> sender can use as an offset when determining the time stamps for
>>>>>> messages you subsequently send. For example, if you want to send a
>>>>>> message with a time stamp for five milliseconds in the future, you
>>>>>> can get the device's current position in microseconds, add 5000
>>>>>> microseconds, and use that as the time stamp. Keep in mind that the
>>>>>> MidiDevice's notion of time always places time zero at the time the
>>>>>> device was opened.
>>>>>>
>>>>>>
>>>>>> import java.io.BufferedReader;
>>>>>>
>>>>>> import java.io.IOException;
>>>>>>
>>>>>> import java.io.InputStreamReader;
>>>>>>
>>>>>> import javax.sound.midi.InvalidMidiDataException;
>>>>>>
>>>>>> import javax.sound.midi.MidiDevice;
>>>>>>
>>>>>> import javax.sound.midi.MidiSystem;
>>>>>>
>>>>>> import javax.sound.midi.MidiUnavailableException;
>>>>>>
>>>>>> import javax.sound.midi.ShortMessage;
>>>>>>
>>>>>>
>>>>>> public class Test {
>>>>>>
>>>>>> public static void main(String args[]) throws
>>>>>> InvalidMidiDataException, MidiUnavailableException, IOException {
>>>>>>
>>>>>>
>>>>>> MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
>>>>>>
>>>>>> for (int i = 0; i < infos.length; i++) {
>>>>>>
>>>>>> System.out.println(i+": "+infos[i]);
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>> BufferedReader bf = new BufferedReader(new
>>>>>> InputStreamReader(System.in));
>>>>>>
>>>>>> System.out.println("Which device?");
>>>>>>
>>>>>> int n = 0;
>>>>>>
>>>>>> try {
>>>>>>
>>>>>> n = Integer.parseInt(bf.readLine());
>>>>>>
>>>>>> } catch (NumberFormatException e) {}
>>>>>>
>>>>>>
>>>>>> MidiDevice device = null;
>>>>>>
>>>>>> try {
>>>>>>
>>>>>> device = MidiSystem.getMidiDevice(infos[n]);
>>>>>>
>>>>>> } catch (MidiUnavailableException e) {}
>>>>>>
>>>>>> if (!(device.isOpen())) {
>>>>>>
>>>>>> try {
>>>>>>
>>>>>> device.open();
>>>>>>
>>>>>> } catch (MidiUnavailableException e) {
>>>>>>
>>>>>> // Handle or throw exception...
>>>>>>
>>>>>> }
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>> ShortMessage msg = new ShortMessage();
>>>>>>
>>>>>> msg.setMessage(ShortMessage.NOTE_ON, 0, 60, 93);
>>>>>>
>>>>>> long timeStamp = -1;
>>>>>>
>>>>>> javax.sound.midi.Receiver rcvr = device.getReceiver();
>>>>>>
>>>>>> rcvr.send(msg, timeStamp);
>>>>>>
>>>>>> System.exit(0);
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>>
>>>>>> ----- Original Message ----- From: <jmsl at music.columbia.edu>
>>>>>> To: <jmsl at music.columbia.edu>
>>>>>> Sent: Tuesday, April 14, 2009 11:50 AM
>>>>>> Subject: Re: [jmsl] Playing Through An External Midi Device
>>>>>>
>>>>>>
>>>>>>> Hi Chi
>>>>>>>
>>>>>>> Please help me out here, I don't have a lot of resources currently
>>>>>>> to work on this. If you can do the following in a few lines of pure
>>>>>>> Java (no JMSL at all), then I will implement it in JMSL's JavaSound
>>>>>>> support
>>>>>>>
>>>>>>> If someone already knows how to do this, please share it here.
>>>>>>>
>>>>>>> You already know how to enumerate through midi device info.
>>>>>>>
>>>>>>> You can create a MidiDevice using minfo like this:
>>>>>>> MidiDevice mdev = MidiSystem.getMidiDevice(infos[i]);
>>>>>>>
>>>>>>> Your challenge is to open the mdev you want, get the transmitter or
>>>>>>> receiver or whatever it is one needs to do to send a midi message
>>>>>>> out to it, and send it a simple MidiMessage like a noteon.
>>>>>>> I've tried it but cannot get a receiver or a transmitter for these
>>>>>>> midi devices, I just get nulls or exceptions. Something's missing
>>>>>>> and I don't know what it is.
>>>>>>>
>>>>>>> My code follows...
>>>>>>> MidiDevice.Info[] minfo= MidiSystem.getMidiDeviceInfo();
>>>>>>> for (int i = 0; i < minfo.length; i++) {
>>>>>>> MidiDevice mdev = MidiSystem.getMidiDevice(minfo[i]);
>>>>>>> String info = minfo[i].getDescription() + ", " +
>>>>>>> minfo[i].getName() + ", " +
>>>>>>> minfo[i].getVendor() + ", " +
>>>>>>> minfo[i].getVersion();
>>>>>>> System.out.println("\nDevice " + i + " = " + minfo[i]
>>>>>>> + " ... " + mdev.toString());
>>>>>>> System.out.println("CLASS: " + mdev.getClass());
>>>>>>> mdev.open();
>>>>>>> try {
>>>>>>> System.out.println("transmitter for this: " +
>>>>>>> mdev.getTransmitter());
>>>>>>> System.out.println("receiver for this : " +
>>>>>>> mdev.getReceiver());
>>>>>>> } catch (MidiUnavailableException e) {
>>>>>>> System.out.println("can't get transmitter or
>>>>>>> receiver for this");
>>>>>>> } mdev.close();
>>>>>>> }
>>>>>>>
>>>>>>> Thanks
>>>>>>> Nick
>>>>>>>
>>>>>>> jmsl at music.columbia.edu wrote:
>>>>>>>> How can I hookup JavaSound ports to JMSL? If I do this I can see
>>>>>>>> all the external midi devices I have on my computer.
>>>>>>>>
>>>>>>>> MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
>>>>>>>> for (int i = 0; i < infos.length; i++) {
>>>>>>>> System.out.println(infos[i]);
>>>>>>>> }
>>>>>>>>
>>>>>>>> /*
>>>>>>>> Result:
>>>>>>>> USB Audio Device
>>>>>>>> Microsoft MIDI Mapper
>>>>>>>> USB Audio Device
>>>>>>>> SB X-Fi Synth A [BC00]
>>>>>>>> SB X-Fi Synth B [BC00]
>>>>>>>> Microsoft GS Wavetable SW Synth
>>>>>>>> Real Time Sequencer
>>>>>>>> Java Sound Synthesizer
>>>>>>>> */
>>>>>>>>
>>>>>>>> If I do this, I get an error.
>>>>>>>> JMSL.midi = MidiIO_JavaSound.instance();
>>>>>>>> String[] deviceNames = JMSL.midi.getOutputDeviceNames();
>>>>>>>> System.out.println("There are " + deviceNames.length + "midi
>>>>>>>> devices.");
>>>>>>>> for (int i=0; i<deviceNames.length; i++) {
>>>>>>>> System.out.println(deviceNames[i]);
>>>>>>>> }
>>>>>>>>
>>>>>>>> /*
>>>>>>>> Result:
>>>>>>>> There are 1midi devices.
>>>>>>>> Unimplemented
>>>>>>>> */
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> jmsl mailing list
>>>>>>>> jmsl at music.columbia.edu
>>>>>>>> http://music.columbia.edu/mailman/listinfo/jmsl
>>>>>>> _______________________________________________
>>>>>>> jmsl mailing list
>>>>>>> jmsl at music.columbia.edu
>>>>>>> http://music.columbia.edu/mailman/listinfo/jmsl
>>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> jmsl mailing list
>>>>>> jmsl at music.columbia.edu
>>>>>> http://music.columbia.edu/mailman/listinfo/jmsl
>>>>> _______________________________________________
>>>>> jmsl mailing list
>>>>> jmsl at music.columbia.edu
>>>>> http://music.columbia.edu/mailman/listinfo/jmsl
>>>>>
>>>>
>>>> _______________________________________________
>>>> jmsl mailing list
>>>> jmsl at music.columbia.edu
>>>> http://music.columbia.edu/mailman/listinfo/jmsl
>>> _______________________________________________
>>> jmsl mailing list
>>> jmsl at music.columbia.edu
>>> http://music.columbia.edu/mailman/listinfo/jmsl
>>>
>>
>> _______________________________________________
>> jmsl mailing list
>> jmsl at music.columbia.edu
>> http://music.columbia.edu/mailman/listinfo/jmsl
> _______________________________________________
> jmsl mailing list
> jmsl at music.columbia.edu
> http://music.columbia.edu/mailman/listinfo/jmsl
>
More information about the jmsl
mailing list