package com.softsynth.jmsl.score.max; import com.cycling74.max.*; import com.didkovsky.portview.swing.ViewFactorySwing; import com.softsynth.jmsl.*; import com.softsynth.jmsl.score.*; import com.softsynth.jmsl.score.transcribe.*; import com.softsynth.jmsl.util.TimeSignature; /** * JMSL/Max Transcriber demo. Notate melodies generated in Max * * Capture incoming pitch and vel events from Max, transcribe as common music notation * * JMSLMaxNotate responds to these messages: startCapture, begins logging notes when bang'ed * stopCapture, stops logging printCapture, prints captured MusicShape to console transcribe, * creates a new Score and transcribes captured data bang, logs a note event using with current * pitch and current vel. * * Attributes: pitch is 0..127 vel comes in as 0..127 but is scaled to 0..1 for compatibility with * JMSL/JSyn * * JMSL is available from www.algomusic.com * * MOD 20050909, moved scoreFrame.addScore(score) the the end of transcribe(). It caused Java to * hang under OS X tiger when called before ScoreFrame was visible. * * MOD 20060207, made pitch and vel public after Max complained it could not see these attributes. * * @author Nick Didkovsky, email: didkovn@mail.rockefeller.edu, (c) 2004 Nick Didkovsky, all rights * reserved. * */ public class JMSLMaxNotate extends MaxObject implements STDOutFunction { /** pitch is 0..127 */ public double pitch = 0; /** vel is 0..127 */ public double vel = 0; private double maxClockRecordingStartTime; private MusicShape capturedMusicShape; private boolean record = false; private Score score; private ScoreFrame scoreFrame; private int scoreNumber = 0; public JMSLMaxNotate() { JMSL.setViewFactory(new ViewFactorySwing()); post("JMSLMaxNotate responds to startCapture, stopCapture, printCapture, and transcribe. bang enters a note"); post("JMSL is available from www.algomusic.com"); JMSL.out = this; declareAttribute("pitch"); declareAttribute("vel"); } /** * add an element to musicshape using current max time, current pitch, current vel (scaled 0..1) */ public void bang() { // post("JMSLMaxNotate bang"); if (capturedMusicShape != null && record) { // post("adding element " + pitch + ", " + vel); // store timestamp as double seconds where 1.0 == 1 sec double timeStamp = (MaxClock.getTime() - maxClockRecordingStartTime) / 1000.0; double amp = vel / 127.0; capturedMusicShape.add(timeStamp, pitch, amp, 0); // hold time will be tweaked later } } public void newScore() { post("new score"); score = new Score(1, 800, 600); // num staves, w, h score.addMeasure(); score.setName("JMSL_Max_Score-" + scoreNumber++); } public void startCapture() { if (!record) { post("starting capture"); maxClockRecordingStartTime = MaxClock.getTime(); capturedMusicShape = new MusicShape(4); record = true; } } public void stopCapture() { if (record) { post("stopping capture"); record = false; } } public void printCapture() { if (capturedMusicShape != null) { capturedMusicShape.print(); } } public void transcribe() { if (capturedMusicShape != null) { // post("copy and massage MusicShape"); MusicShape shapeToTranscribe = (MusicShape) capturedMusicShape.clone(); // set the hold times in dimension 4 for (int i = 1; i < shapeToTranscribe.size(); i++) { double hold = shapeToTranscribe.get(i, 0) - shapeToTranscribe.get(i - 1, 0); shapeToTranscribe.set(hold, i - 1, 3); } shapeToTranscribe.set(1.0, shapeToTranscribe.size() - 1, 3); shapeToTranscribe.transpose(-shapeToTranscribe.get(0, 0), 0, shapeToTranscribe.size() - 1, 0); // shapeToTranscribe.print(); newScore(); // post("set up transcriber"); BeatDivisionSchemeList.defaultSetup(); Transcriber transcriber = new Transcriber(); transcriber.setScore(score); // Set up time signatures. Only need to give it one 4/4 bar and // transcriber will // continue with 4/4 throughout java.util.Vector tsVector = new java.util.Vector(); tsVector.addElement(new TimeSignature(4, 4)); transcriber.setTimeSignatures(tsVector); try { score.setCurrentStaffNumber(0); score.rewind(); // post("transcribe"); transcriber.setSourceMusicShape(shapeToTranscribe); transcriber.transcribe(); } catch (SearchPathListExpansionException e) { e.printStackTrace(); } catch (ElementMissedException e) { e.printStackTrace(); } // post("add score"); if (scoreFrame == null) { scoreFrame = new ScoreFrame(); scoreFrame.setSize(800, 800); } scoreFrame.setVisible(true); scoreFrame.toFront(); scoreFrame.addScore(score); } else { post("nothing captured, nothing to do"); } } // implement STDOutFunction so JMSL.out.println() gets rerouted to max // post() public void print(String s) { post(s); } public void println(String s) { post(s); } public void println() { post("\n"); } }