Advertisement
Guest User

Untitled

a guest
Jul 27th, 2017
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 13.15 KB | None | 0 0
  1. /*
  2.  *  DumpReceiver.java
  3.  *
  4.  *  This file is part of jsresources.org
  5.  */
  6.  
  7. /*
  8.  * Copyright (c) 1999 - 2001 by Matthias Pfisterer
  9.  * Copyright (c) 2003 by Florian Bomers
  10.  * All rights reserved.
  11.  *
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  *
  16.  * - Redistributions of source code must retain the above copyright notice,
  17.  *   this list of conditions and the following disclaimer.
  18.  * - Redistributions in binary form must reproduce the above copyright
  19.  *   notice, this list of conditions and the following disclaimer in the
  20.  *   documentation and/or other materials provided with the distribution.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25.  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26.  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  29.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  31.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  32.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  33.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  34.  */
  35.  
  36. import  java.io.PrintStream;
  37.  
  38. import  javax.sound.midi.MidiSystem;
  39. import  javax.sound.midi.InvalidMidiDataException;
  40. import  javax.sound.midi.Sequence;
  41. import  javax.sound.midi.Track;
  42. import  javax.sound.midi.MidiEvent;
  43. import  javax.sound.midi.MidiMessage;
  44. import  javax.sound.midi.ShortMessage;
  45. import  javax.sound.midi.MetaMessage;
  46. import  javax.sound.midi.SysexMessage;
  47. import  javax.sound.midi.Receiver;
  48. import  javax.sound.midi.*;
  49. import java.net.*;
  50. import java.io.*;
  51.  
  52.  
  53.  
  54. /** Displays the file format information of a MIDI file.
  55.  */
  56. public class DumpReceiver
  57.     implements  Receiver
  58. {
  59.     //Receiver synthRcvr;
  60.     PrintWriter outputter;
  61.    
  62.     public static long seByteCount = 0;
  63.     public static long smByteCount = 0;
  64.     public static long seCount = 0;
  65.     public static long smCount = 0;
  66.  
  67.     private static final String[]       sm_astrKeyNames = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
  68.  
  69.     private static final String[]       sm_astrKeySignatures = {"Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#"};
  70.     private static final String[]       SYSTEM_MESSAGE_TEXT =
  71.     {
  72.         "System Exclusive (should not be in ShortMessage!)",
  73.         "MTC Quarter Frame: ",
  74.         "Song Position: ",
  75.         "Song Select: ",
  76.         "Undefined",
  77.         "Undefined",
  78.         "Tune Request",
  79.         "End of SysEx (should not be in ShortMessage!)",
  80.         "Timing clock",
  81.         "Undefined",
  82.         "Start",
  83.         "Continue",
  84.         "Stop",
  85.         "Undefined",
  86.         "Active Sensing",
  87.         "System Reset"
  88.     };
  89.  
  90.     private static final String[]       QUARTER_FRAME_MESSAGE_TEXT =
  91.     {
  92.         "frame count LS: ",
  93.         "frame count MS: ",
  94.         "seconds count LS: ",
  95.         "seconds count MS: ",
  96.         "minutes count LS: ",
  97.         "minutes count MS: ",
  98.         "hours count LS: ",
  99.         "hours count MS: "
  100.     };
  101.  
  102.     private static final String[]       FRAME_TYPE_TEXT =
  103.     {
  104.         "24 frames/second",
  105.         "25 frames/second",
  106.         "30 frames/second (drop)",
  107.         "30 frames/second (non-drop)",
  108.     };
  109.  
  110.     private PrintStream     m_printStream;
  111.     private boolean         m_bDebug;
  112.     private boolean         m_bPrintTimeStampAsTicks;
  113.  
  114.  
  115.  
  116.     public DumpReceiver(PrintStream printStream)
  117.     {
  118.         this(printStream, false);
  119.     }
  120.  
  121.  
  122.     public DumpReceiver(PrintStream printStream,
  123.                 boolean bPrintTimeStampAsTicks)
  124.     {
  125.         m_printStream = printStream;
  126.         m_bDebug = false;
  127.         m_bPrintTimeStampAsTicks = bPrintTimeStampAsTicks;
  128.        
  129.         try
  130.         {
  131.     /* Synthesizer synth = MidiSystem.getSynthesizer();
  132.         synth.open();
  133.         synthRcvr = synth.getReceiver();*/
  134.         Socket mySocket = new Socket("localhost",34101);
  135.         outputter = new PrintWriter(mySocket.getOutputStream(), true);
  136.         }
  137.         catch ( Exception e )
  138.         {
  139.         }
  140.     }
  141.  
  142.  
  143.  
  144.     public void close()
  145.     {
  146.     }
  147.  
  148.  
  149.  
  150.     public void send(MidiMessage message, long lTimeStamp)
  151.     {
  152.         String  strMessage = null;
  153.         if (message instanceof ShortMessage)
  154.         {
  155.             strMessage = decodeMessage((ShortMessage) message);
  156.         }
  157.         else if (message instanceof SysexMessage)
  158.         {
  159.             strMessage = decodeMessage((SysexMessage) message);
  160.         }
  161.         else if (message instanceof MetaMessage)
  162.         {
  163.             strMessage = decodeMessage((MetaMessage) message);
  164.         }
  165.         else
  166.         {
  167.             strMessage = "unknown message type";
  168.         }
  169.         String  strTimeStamp = null;
  170.         if (m_bPrintTimeStampAsTicks)
  171.         {
  172.             strTimeStamp = "tick " + lTimeStamp + ": ";
  173.         }
  174.         else
  175.         {
  176.             if (lTimeStamp == -1L)
  177.             {
  178.                 strTimeStamp = "timestamp [unknown]: ";
  179.             }
  180.             else
  181.             {
  182.                 strTimeStamp = "timestamp " + lTimeStamp + " us: ";
  183.             }
  184.         }
  185.         m_printStream.println(strTimeStamp + strMessage);
  186.     }
  187.  
  188.  
  189.  
  190.     public String decodeMessage(ShortMessage message)
  191.     {
  192.         String  strMessage = null;
  193.         switch (message.getCommand())
  194.         {
  195.         case 0x80:
  196.             outputter.println("0,"+message.getData1()+","+message.getData2());
  197.             //synthRcvr.send(message, -1);
  198.             strMessage = "note Off " + getKeyName(message.getData1()) + " velocity: " + message.getData2();
  199.             break;
  200.  
  201.         case 0x90:
  202.             //synthRcvr.send(message, -1);
  203.             outputter.println("1,"+message.getData1()+","+message.getData2());
  204.             strMessage = "note On " + getKeyName(message.getData1()) + " velocity: " + message.getData2();
  205.            
  206.  
  207.             break;
  208.  
  209.         case 0xa0:
  210.             strMessage = "polyphonic key pressure " + getKeyName(message.getData1()) + " pressure: " + message.getData2();
  211.             break;
  212.  
  213.         case 0xb0:
  214.             strMessage = "control change " + message.getData1() + " value: " + message.getData2();
  215.             break;
  216.  
  217.         case 0xc0:
  218.             strMessage = "program change " + message.getData1();
  219.             break;
  220.  
  221.         case 0xd0:
  222.             strMessage = "key pressure " + getKeyName(message.getData1()) + " pressure: " + message.getData2();
  223.             break;
  224.  
  225.         case 0xe0:
  226.             strMessage = "pitch wheel change " + get14bitValue(message.getData1(), message.getData2());
  227.             break;
  228.  
  229.         case 0xF0:
  230.             strMessage = SYSTEM_MESSAGE_TEXT[message.getChannel()];
  231.             switch (message.getChannel())
  232.             {
  233.             case 0x1:
  234.                 int nQType = (message.getData1() & 0x70) >> 4;
  235.                 int nQData = message.getData1() & 0x0F;
  236.                 if (nQType == 7)
  237.                 {
  238.                     nQData = nQData & 0x1;
  239.                 }
  240.                 strMessage += QUARTER_FRAME_MESSAGE_TEXT[nQType] + nQData;
  241.                 if (nQType == 7)
  242.                 {
  243.                     int nFrameType = (message.getData1() & 0x06) >> 1;
  244.                     strMessage += ", frame type: " + FRAME_TYPE_TEXT[nFrameType];
  245.                 }
  246.                 break;
  247.  
  248.             case 0x2:
  249.                 strMessage += get14bitValue(message.getData1(), message.getData2());
  250.                 break;
  251.  
  252.             case 0x3:
  253.                 strMessage += message.getData1();
  254.                 break;
  255.             }
  256.             break;
  257.  
  258.         default:
  259.             strMessage = "unknown message: status = " + message.getStatus() + ", byte1 = " + message.getData1() + ", byte2 = " + message.getData2();
  260.             break;
  261.         }
  262.         if (message.getCommand() != 0xF0)
  263.         {
  264.             int nChannel = message.getChannel() + 1;
  265.             String  strChannel = "channel " + nChannel + ": ";
  266.             strMessage = strChannel + strMessage;
  267.         }
  268.         smCount++;
  269.         smByteCount+=message.getLength();
  270.         return "["+getHexString(message)+"] "+strMessage;
  271.     }
  272.  
  273.  
  274.  
  275.     public String decodeMessage(SysexMessage message)
  276.     {
  277.         byte[]  abData = message.getData();
  278.         String  strMessage = null;
  279.         // System.out.println("sysex status: " + message.getStatus());
  280.         if (message.getStatus() == SysexMessage.SYSTEM_EXCLUSIVE)
  281.         {
  282.             strMessage = "Sysex message: F0" + getHexString(abData);
  283.         }
  284.         else if (message.getStatus() == SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE)
  285.         {
  286.             strMessage = "Continued Sysex message F7" + getHexString(abData);
  287.             seByteCount--; // do not count the F7
  288.         }
  289.         seByteCount += abData.length + 1;
  290.         seCount++; // for the status byte
  291.         return strMessage;
  292.     }
  293.  
  294.  
  295.  
  296.     public String decodeMessage(MetaMessage message)
  297.     {
  298.         byte[]  abMessage = message.getMessage();
  299.         byte[]  abData = message.getData();
  300.         int nDataLength = message.getLength();
  301.         String  strMessage = null;
  302.         // System.out.println("data array length: " + abData.length);
  303.         switch (message.getType())
  304.         {
  305.         case 0:
  306.             int nSequenceNumber = ((abData[0] & 0xFF) << 8) | (abData[1] & 0xFF);
  307.             strMessage = "Sequence Number: " + nSequenceNumber;
  308.             break;
  309.  
  310.         case 1:
  311.             String  strText = new String(abData);
  312.             strMessage = "Text Event: " + strText;
  313.             break;
  314.  
  315.         case 2:
  316.             String  strCopyrightText = new String(abData);
  317.             strMessage = "Copyright Notice: " + strCopyrightText;
  318.             break;
  319.  
  320.         case 3:
  321.             String  strTrackName = new String(abData);
  322.             strMessage = "Sequence/Track Name: " +  strTrackName;
  323.             break;
  324.  
  325.         case 4:
  326.             String  strInstrumentName = new String(abData);
  327.             strMessage = "Instrument Name: " + strInstrumentName;
  328.             break;
  329.  
  330.         case 5:
  331.             String  strLyrics = new String(abData);
  332.             strMessage = "Lyric: " + strLyrics;
  333.             break;
  334.  
  335.         case 6:
  336.             String  strMarkerText = new String(abData);
  337.             strMessage = "Marker: " + strMarkerText;
  338.             break;
  339.  
  340.         case 7:
  341.             String  strCuePointText = new String(abData);
  342.             strMessage = "Cue Point: " + strCuePointText;
  343.             break;
  344.  
  345.         case 0x20:
  346.             int nChannelPrefix = abData[0] & 0xFF;
  347.             strMessage = "MIDI Channel Prefix: " + nChannelPrefix;
  348.             break;
  349.  
  350.         case 0x2F:
  351.             strMessage = "End of Track";
  352.             break;
  353.  
  354.         case 0x51:
  355.             int nTempo = ((abData[0] & 0xFF) << 16)
  356.                     | ((abData[1] & 0xFF) << 8)
  357.                     | (abData[2] & 0xFF);           // tempo in microseconds per beat
  358.             float bpm = convertTempo(nTempo);
  359.             // truncate it to 2 digits after dot
  360.             bpm = (float) (Math.round(bpm*100.0f)/100.0f);
  361.             strMessage = "Set Tempo: "+bpm+" bpm";
  362.             break;
  363.  
  364.         case 0x54:
  365.             // System.out.println("data array length: " + abData.length);
  366.             strMessage = "SMTPE Offset: "
  367.                 + (abData[0] & 0xFF) + ":"
  368.                 + (abData[1] & 0xFF) + ":"
  369.                 + (abData[2] & 0xFF) + "."
  370.                 + (abData[3] & 0xFF) + "."
  371.                 + (abData[4] & 0xFF);
  372.             break;
  373.  
  374.         case 0x58:
  375.             strMessage = "Time Signature: "
  376.                 + (abData[0] & 0xFF) + "/" + (1 << (abData[1] & 0xFF))
  377.                 + ", MIDI clocks per metronome tick: " + (abData[2] & 0xFF)
  378.                 + ", 1/32 per 24 MIDI clocks: " + (abData[3] & 0xFF);
  379.             break;
  380.  
  381.         case 0x59:
  382.             String  strGender = (abData[1] == 1) ? "minor" : "major";
  383.             strMessage = "Key Signature: " + sm_astrKeySignatures[abData[0] + 7] + " " + strGender;
  384.             break;
  385.  
  386.         case 0x7F:
  387.             // TODO: decode vendor code, dump data in rows
  388.             String  strDataDump = getHexString(abData);
  389.             strMessage = "Sequencer-Specific Meta event: " + strDataDump;
  390.             break;
  391.  
  392.         default:
  393.             String  strUnknownDump = getHexString(abData);
  394.             strMessage = "unknown Meta event: " + strUnknownDump;
  395.             break;
  396.  
  397.         }
  398.         return strMessage;
  399.     }
  400.  
  401.  
  402.  
  403.     public static String getKeyName(int nKeyNumber)
  404.     {
  405.         if (nKeyNumber > 127)
  406.         {
  407.             return "illegal value";
  408.         }
  409.         else
  410.         {
  411.             int nNote = nKeyNumber % 12;
  412.             int nOctave = nKeyNumber / 12;
  413.             return sm_astrKeyNames[nNote] + (nOctave - 1);
  414.         }
  415.     }
  416.  
  417.  
  418.     public static int get14bitValue(int nLowerPart, int nHigherPart)
  419.     {
  420.         return (nLowerPart & 0x7F) | ((nHigherPart & 0x7F) << 7);
  421.     }
  422.  
  423.  
  424.  
  425.     private static int signedByteToUnsigned(byte b)
  426.     {
  427.         return b & 0xFF;
  428.     }
  429.  
  430.     // convert from microseconds per quarter note to beats per minute and vice versa
  431.     private static float convertTempo(float value) {
  432.         if (value <= 0) {
  433.             value = 0.1f;
  434.         }
  435.         return 60000000.0f / value;
  436.     }
  437.  
  438.  
  439.  
  440.     private static char hexDigits[] =
  441.        {'0', '1', '2', '3',
  442.         '4', '5', '6', '7',
  443.         '8', '9', 'A', 'B',
  444.         'C', 'D', 'E', 'F'};
  445.  
  446.     public static String getHexString(byte[] aByte)
  447.     {
  448.         StringBuffer    sbuf = new StringBuffer(aByte.length * 3 + 2);
  449.         for (int i = 0; i < aByte.length; i++)
  450.         {
  451.             sbuf.append(' ');
  452.             sbuf.append(hexDigits[(aByte[i] & 0xF0) >> 4]);
  453.             sbuf.append(hexDigits[aByte[i] & 0x0F]);
  454.             /*byte  bhigh = (byte) ((aByte[i] &  0xf0) >> 4);
  455.             sbuf.append((char) (bhigh > 9 ? bhigh + 'A' - 10: bhigh + '0'));
  456.             byte    blow = (byte) (aByte[i] & 0x0f);
  457.             sbuf.append((char) (blow > 9 ? blow + 'A' - 10: blow + '0'));*/
  458.         }
  459.         return new String(sbuf);
  460.     }
  461.    
  462.     private static String intToHex(int i) {
  463.         return ""+hexDigits[(i & 0xF0) >> 4]
  464.                  +hexDigits[i & 0x0F];
  465.     }
  466.  
  467.     public static String getHexString(ShortMessage sm)
  468.     {
  469.         // bug in J2SDK 1.4.1
  470.         // return getHexString(sm.getMessage());
  471.         int status = sm.getStatus();
  472.         String res = intToHex(sm.getStatus());
  473.         // if one-byte message, return
  474.         switch (status) {
  475.             case 0xF6:          // Tune Request
  476.             case 0xF7:          // EOX
  477.                 // System real-time messages
  478.             case 0xF8:          // Timing Clock
  479.             case 0xF9:          // Undefined
  480.             case 0xFA:          // Start
  481.             case 0xFB:          // Continue
  482.             case 0xFC:          // Stop
  483.             case 0xFD:          // Undefined
  484.             case 0xFE:          // Active Sensing
  485.             case 0xFF: return res;
  486.         }
  487.         res += ' '+intToHex(sm.getData1());
  488.         // if 2-byte message, return
  489.         switch (status) {
  490.             case 0xF1:          // MTC Quarter Frame
  491.             case 0xF3:          // Song Select
  492.                     return res;
  493.         }
  494.         switch (sm.getCommand()) {
  495.             case 0xC0:
  496.             case 0xD0:
  497.                     return res;
  498.         }
  499.         // 3-byte messages left
  500.         res += ' '+intToHex(sm.getData2());
  501.         return res;
  502.     }
  503. }
  504.  
  505.  
  506.  
  507. /*** DumpReceiver.java ***/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement