JEM Updates

Version 4.6 (Build 2, 17-Mar-2018)

gui.py, version 3.6 (20-Feb-2018) |  (bm)

Added a useful library of additional musical GUI controls for receiving user input.  This provides horizontal and vertical sliders (HFader, VFader), an XYPad (for capturing both x and y cursor coordinates), Toggle button (on/off), Push button (on-while-pressing-only), and Rotary (a rotary dial). For each of these you can control various color options, the functionality that the control is connected to, and the range of values (when it makes sense).

osc.py, version 4.11 (07-Mar-2018) |  (bm)

Now, we allow multiple callback functions to be associated with the same incoming OSC address. This is was introduced to be consistent with the MidiIn API.


Version 4.5 (Build 5, 21-Mar-2017)

music.py, version 4.11 (21-Mar-2017) |  (bm)

Fixed pitch bend bug.  Now, Play.setPitchBend() works as expected.


Version 4.5 (Build 6, 17-Feb-2017)

osc.py, version 1.5 (17-Feb-2017) |  (dj)

Update in how we get host IP address in OscIn object to fix Mac OSX problem.


Version 4.5 (Build 5, 16-Jan-2017)

music.py, version 4.10 (16-Jan-2017) |  (bm)

Fixed Note.getPitch() to return REST for rest notes, as it should.


Version 4.5 (Build 4, 28-Dec-2016)

music.py, version 4.9 (27-Dec-2016) |  (bm)

Fixed jMusic Note bug, where, if int pitch is given, both frequency and pitch attributes are populated, but if float pitch is given (i.e., frequency in Hertz), only the frequency attribute is populated – no pitch).  Consequently, in the second case, calling getPitch() crashes the system. Also added getPitch() and getPitchBend() to fully convert a frequency to MIDI pitch information.


Version 4.5 (Build 3, 26-Dec-2016)

music.py, version 4.8 (26-Dec-2016) |  (mm)

Added Envelope class for using with Play.audio(). An envelope contains a list of attack times (in milliseconds, relative from the previous time) and values (to reach at those times), how long to wait (delay time, in milliseconds, relative from the previous time) to get to a sustain value, and then how long to wait to reach a value of zero (in milliseconds, relative from the end time). Also modified Play.audio() to accept an Envelope as an optional parameter.


Version 4.5 (Build 2, 22-Nov-2016)

midi.py, version 2.1 (22-Nov-2016) |  (bm)

Fixed minor bug in MidiOut play() global instrument settings.


Version 4.5 (Build 1, 11-Nov-2016)

midi.py, version 2.1 (12-Nov-2016) |  (bm)

Updated MidiOut play() to respect global instrument settings, also updated set/getInstrument(), set/getVolume(), set/getPanning(). MidiOut() now also accepts a preferred output device as a string. If available, it is selected directly (without a selection display – faster!). Same thing for MidiIn()

music.py, version 4.7 (11-Nov-2016) |  (bm)

Small bug fix in Play.midi – now we pay attention to global instrument settings, i.e., Play.setInstrument(), unless instrument has been set explicitly locally (e.g., at Phrase level).

music.py, version 4.6 (07-Nov-2016) |  (bm)

Fixed inefficiency problem in Play.midi (took forever to play long scores, e.g., > 3000 notes). Now, things work in real time again.

music.py, version 4.5 (05-Nov-2016) |  (bm)

Fixed small but important bug in Play.midi (a missing variable in the part scheduling all notes in the chord list).

music.py, version 4.4 (21-Oct-2016) |  (bm)

Fixed clicking in Play.audio() by adding a timer to lower volume right before the ending of an audio note.

music.py, version 4.3 (28-Aug-2016) |  (bm)

Added Play.audio(), Play.audioNote(), Play.audioOn(), Play.audioOff(), Play.allAudioNotesOff() to play musical material via AudioSamples. These functions parallel the corresponding Play.note(), etc. functions.  The only difference is that audio samples are provided to be used in place of MIDI channels to render the music. Also fixed bug with rendering panning information in notes in Play.midi() and Play.audio(). Also, if panning information is not provided in Play.noteOn(), Play.audioOn(), etc., the global Play.setPanning() info is now used.


Version 4.5 (02-Sep-2016)

Moved to newer version of core JEM (provided by tk on 11-Aug-2016)


Version 4.4 (13-Aug-2016)

music.py, version 4.2 (12-Aug-2016) |  (bm)

Using Timer2() class (based on java.util.Timer) for Play.note(), etc. More reliable.

timer.py, version 1.7 (12-Aug-2016) |  (bm and tk)

Timer() is again the original Swing timer. Timer2() is the new and improved based on java.util.Timer. Timer2() now is more efficient (using only one class-level Timer, and instead of instantiating TimerTasks). Timer() is good for GUI animation. Timer2() is good for massive musical tasks (mostly internal, e.g., Play.note()) – it is available, but not advertised (yet?).


Version 4.4 (07-Aug-2016)

music.py, version 4.1 (28-Jul-2016)  | (bm and mm)

Resolved following issues with Play.midi(): (a) Playback now uses

music.py, version 4.1 (28-Jul-2016)  | (bm and mm)

Resolved following issues with Play.midi(): (a) Playback now uses length of a note (vs. its duration) to determine how long it sounds (as it should). (b) Chord durations were calculated improperly for some chord notes, due to a note sorting error. This has been fixed by sorting noteList in Play.midi() by start time, then duration, then pitch then etc. (c) Fixed race condition which caused some notes from not turning off. The dictionary used to hold instances of overlapping notes was changed to a list. Now, for every note to play, a tuple of pitch and channel is added to by frequencyOn() and removed from the list by frequencyOff(), respectively. (Race condition is still present, but due to rewritten logic, it does not cause any trouble anymore. All concurrent notes are turned off when they should.)

midi.py, version 2.0 (03-Aug-2016)  |  (mm, bm)

Updated MidiOut play() to include microtonal capability. Copied the updated music.py functions frequencyOn(), noteOn(), noteOff(), setPitchBend(), getPitchBend(), freqToNote(), noteToFreq(). Also copied frequencyOff() and noteOnPitchBend(), however, these need to be changed here (whenever copied from music.py, after another update), since they use self.sendMessage() to start and stop notes. Microtonal frequencies are floats (e.g., 440.0), whereas ordinary MIDI pitches are ints (e.g, 69). These are utilized in note creation, e.g., Note(440.0, QN) vs. Note(69, QN), which refer to the same note, A4


Version 4.3 (12-Jun-2016)

music.py, version 4.0 (14-May-2016) |  (bm and mm)

Added microtonal capabilities. Now, we can create and play notes using frequencies (float, in Hz), instead of pitch (0-127). Updated new Play.midi() function to handle microtones / frequencies (by using pitchbend). Only one frequency per channel can be played accurately (since there is only one pitchbend per channel). Regular notes can play concurrently as usual (i.e., for chords). However, for concurrent microtones on a given channel, unless they have same pitchbend, only the last microtone will be rendered accurately (all others will be affected by the latest pichbend – the one used to render the last microtone – again, only one pitchbend is available per channel). To render concurrent microtones, they have to be spread across different channels. That’s the only way to render microtonal chords using MIDI (i.e., we are pushing MIDI as far as it goes here). Also, updated Play.noteOn/Off(), and Play.frequencyOn/Off() accordingly, and added a few more error checks/warnings. Additionally, now only the last note-off event for a given note-channel is executed, thus allowing overlapping notes with same pitch (e.g., overlapping A4 notes) to render more accurately. Finally, Play.setPitchBend() changes the global pitch bend, so if a certain frequency is played, it will be pitchbended if pitch bend is NOT zero. This is similar to playing any note with pitch bend set to anything other than zero.

timer.py, version 1.6 (03-May-2016) |  (tk)

Updated code to use the java.util.Timer instead of the Swing Timer. The Timer now uses method “scheduleAtFixedRate” that repeatedly calls the task after a given time interval without regard for the duration of the task itself. Also, to avoid starting a lot of threads (and cluttering up Jython’s thread pool), added a callback “_actionPerformed” to cancel the Timer when it is no longer needed. This way, the thread is freed and everything should continue to run smoothly.

NOTE: The original Timer is still available under GUITimer, as it may be needed for GUI animation.


Version 4.2 (22-Mar-2016)

midi.py, version 1.9 (19-Mar-2016)

Updated code to handle Mac OSX Java MIDI implementation problem, which does not allow for closing and re-opening an external MIDI device. Now, we maintain existing connection(s) and reuse them. Close and re-open, on Mac, simply re-initializes existing MIDI device object(s), instead of default behavior, which is to create a new object (the latter still supported on other operating systems). Also, now, we allow for multiple callbacks to be registered for each event type (i.e., we accumulate callback registrations in a list) to be consistent with OscIn class.


Version 4.1 (04-Mar-2016)

music.py, version 3.7 (28-Feb-2016)

Updated Metronome class – set sonification sound, and volume, also change add function to state absolute beat to start and repeat (True / False).


Version 4.0c (18-Jan-2016)

music.py, version 3.6 (05-Feb-2016)

Added Metronome class – it provides for synchronization of musical tasks, especially for live coding. Methods include add(), remove(), start(), stop(), show(), hide(), soundOn(), soundOff().


Version 4.0b (18-Jan-2016)

midi.py, version 1.8 (07-Jan-2016)

Found pesky bug with closing MidiIn objects. Still, MIDI does not close well on Mac.

music.py, version 3.5 (17-Jan-2016)

Fixed Mod.invert() bug, which modified RESTs.  Now, we only invert non-REST notes.

timer.py, version 1.5 (07-Jan-2016)

Fixed minor variable naming bug in Timer.setFunction().


Version 4.0a (26-Dec-2015)

New, improved splash screen.

music.py, version 3.4 (01-Dec-2015)

Moved LiveSample to audio.py, where we can do more extensive testing for audio card formats (e.g., Little Endian), which appeared in some Windows boxes. Also, fixed problem of Java imports overriding Python’s enumerate() function.

audio.py, version 2.0 (26-Dec-2015)

Updated the jSyn engine startup to fix an error with some Windows boxes (actually, their audio cards) which do not support little endian. Now, we poll the available sound cards and let the user (i.e., programmer – whoever imported audio.py) to select which audio card they wish to use. This provides a little more visibility in the inner workings, and allows the user to try different audio cards, for different tasks (and potentially recover from the little endian error, if it is present).

gui.py, version 3.5 (26-Dec-2015)

Added setX(), getX(), setY(), getY() functions to every object. Also, changed mouse events to translate / remap coordinates for JPanel components, so, when a mouse event occurs with a GUI object’s JPanel, the global (enclosing Display) coordinates are communicated (instead of the internal JPanel coordinates, which were returned up until now). This translation / remapping makes things more natural for the end-user (programmer), as it allows them to always work using global (enclosing Display) coordinates.


Version 2S (15-Sep-2015)

Fixed major problem with garbage collection at the beginning of Play.midi(), which made all music hesitate at the beginning. Also fixed problem with deactivating and deleting existing AudioSample, OscIn/Out, MidiIn/Out objects upon re-running a program – this freed needed resources and allowed reconnecting devices on subsequent program runs.


Version 3 (05-May-2015)

Introduced several features and updated libraries. This version’s numbering was a mistake – but kept as is, since some users still have access to it.


Version 2 (04-Nov-2014)

First version to be distributed broadly.