[jmsl] Playing Through An External Midi Device

jmsl at music.columbia.edu jmsl at music.columbia.edu
Wed Apr 15 10:05:09 EDT 2009


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


More information about the jmsl mailing list