★ wanayoo — archive 1999 http://developer.java.sun.com/developer/technicalArticles/Media/JavaSoundAPI/code.htmlNouvelle recherche | Portail wanayoo
Java Technology Home Page
A-Z Index

Java Developer Connection(SM)
Technical Articles

Downloads, APIs, Documentation
Java Developer Connection
Tutorials, Tech Articles, Training
Online Support
Community Discussion
News & Events from Everywhere
Products from Everywhere
How Java Technology is Used Worldwide
Print Button
 
Articles Index

The Science of JavaTM Sound
Code Samples

Michael D. Meloan

ToySynth.java listing

This application brings up a graphical representation of a typical synthesizer keyboard. Clicking on the keys with the mouse, plays the notes. You can adjust voice settings and other options to vary the sounds produced. Have fun!
import java.awt.*;
import java.awt.event.*;
  
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
  
import java.net.URL;
import java.net.MalformedURLException;
  
import javax.media.sound.midi.*;
  
public class ToySynth extends Frame 
    implements MouseListener {
  
  static int  VOLUME_CONTROLLER    = 7;
  static int  PAN_CONTROLLER      = 10;
  static int  EXPRESSION_CONTROLLER  = 11;
  static int  SUSTAIN_CONTROLLER    = 64;
  static int  REVERB_CONTROLLER    = 90;
  static int  REVERB_LEVEL_CONTROLLER = 91;
  
  Synthesizer synth = null;
  Soundbank soundbank = null;
  MidiChannel midiChannels[]; 
  Instrument instruments[];
        
  int transpose = 24;
  int pan = 64;
  int programNumber = 5;
  int  lastKeyNumber = 0;
  int channelNumber = 0;
  int velocity = 64;
  
  Button setChannelButton = new Button("Set Channel");
  
  Label instrumentLabel = new Label("                 ");
  Label velocityLabel = new Label("64   ");
  Label pressureLabel = new Label("64   ");
  Label bendLabel = new Label("64   ");
  Label volLabel = new Label("100  ");
  Label panLabel = new Label("64   ");
  Label revLabel = new Label("64   ");
  
  Scrollbar velocityScrollbar = null;
  Scrollbar pressureScrollbar = null;
  Scrollbar bendScrollbar = null;
  Scrollbar volScrollbar = null;
  Scrollbar panScrollbar = null;
  Scrollbar revScrollbar = null;
  
  Checkbox muteCheckbox = null;
  Checkbox monoCheckbox = null;
  Checkbox soloCheckbox = null;
  Checkbox sustainCheckbox = null;
  
  Button soundOffButton = null;
  Button quitButton = null;
  Button statusButton = null;
    
  static Choice []instr = new Choice [8];
  static Choice channelChoice;
  
  Panel instrumentsPanel = new Panel();
  Panel instrumentsPanel1 = new Panel();
  Panel instrumentsPanel2 = new Panel();
  Panel instrumentsPanel3 = new Panel();
  
  Panel keyboardPanel = new Panel();
  
  boolean singleNoteMode = true;
  
  
  public ToySynth() {
  
    // -----------------------------------------------
    // create the Synthesizer and get our MidiChannels
    // -----------------------------------------------
  
    synth = MidiSystem.getSynthesizer(null);
    if( synth == null ) {
      System.out.println(
        "Could not get default synthesizer");
      System.exit(1);
    }
  
    // load the soundbank
  
    try{
      soundbank = synth.getDefaultSoundbank();
    } catch (Exception e) {
      System.out.println(
        "Exception getting soundbank url: " + e);
      System.exit(1);
    }
  
    // populate the instrument choice boxes
    instruments = soundbank.getInstruments();
    int index = 0;
    for(int i=0; i<8; i++) {
      instr[i] = new Choice();
      for(int j=0; j<16; j++) {
        instr[i].add( instruments[index].getName() );
        index++;
      }
    }
  
    // load the first instrument
    synth.loadInstrument( instruments[0] );
  
    midiChannels = synth.getChannels();
    channelNumber = 0;
      
    instrumentLabel.setText ( "Instrument: " + 
      instruments[midiChannels[
      channelNumber].getProgram()].getName() );
      
    // Make sure we can release our resources and 
    // exit cleanly.
  
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  
    // --------------
    // set up the GUI
    // --------------
  
    setLayout(new GridLayout(4, 1));
    setBackground(Color.lightGray);
    
    // keyboard panel
  
    keyboardPanel.setLayout(null);  
    // absolutely no layout
  
    // create the 6 octaves
    for (int i = 0; i < 6; i++) {
      // black key first
      for (int j = 0; j < 6; j++) {
        if (j == 2)
          continue; // there's no E# in black
        int keyOffset = 1;
        switch(j) {
          case 0:
            keyOffset = 1; break;
          case 1:
            keyOffset = 3; break;
          case 2:
            System.out.println(
            "Something's very Wrong!");
          System.exit(1);
          case 3:
            keyOffset = 6; break;
          case 4:
            keyOffset = 8; break;
          case 5:
            keyOffset = 10; break;
        }
        pianoKey k = 
          new pianoKey(i*12 + keyOffset, false);
        k.setBounds(X(i*28 + j*4 + 3), 
          Y(0), D(2), D(11));
        k.addMouseListener(this);
        keyboardPanel.add(k);
      }
  
      for (int j = 0; j < 7; j++) {
        int keyOffset = 1;
        switch(j) {
          case 0:
            keyOffset = 0; break;
          case 1:
            keyOffset = 2; break;
          case 2:
            keyOffset = 4; break;
          case 3:
            keyOffset = 5; break;
          case 4:
            keyOffset = 7; break;
          case 5:
            keyOffset = 9; break;
          case 6:
            keyOffset = 11; break;
        }
        int keyNumber = i*12 + keyOffset;
        pianoKey k = 
          new pianoKey(i*12 + keyOffset, true);
        k.setBounds(X(i*28 + j*4), Y(0), D(4), D(20));
        k.addMouseListener(this);
        keyboardPanel.add(k);
      }
    }
  
    add(keyboardPanel);
  
    // instruments panel
  
    instrumentsPanel = new Panel(new GridLayout(3,1));
  
    instrumentsPanel1 = new Panel(new FlowLayout());
    instrumentsPanel2 = new Panel(new GridLayout(1,4));
    instrumentsPanel3 = new Panel(new GridLayout(1,4));
  
    for(int i=0; i<8; i++) {
      instr[i].addItemListener(new programChange(this));
    }
  
    channelChoice = new Choice();
    for(int i=0;i<16;i++) {
      channelChoice.add(Integer.toString(i+1));
    }
    channelChoice.addItemListener(
      new channelChange(this));
  
    instrumentsPanel1.add(instrumentLabel);
    instrumentsPanel1.add(new Label("Channel: "));
    instrumentsPanel1.add(channelChoice);
  
    instrumentsPanel2.add(instr[0]);
    instrumentsPanel2.add(instr[1]);
    instrumentsPanel2.add(instr[2]);
    instrumentsPanel2.add(instr[3]);
    instrumentsPanel3.add(instr[4]);
    instrumentsPanel3.add(instr[5]);
    instrumentsPanel3.add(instr[6]);
    instrumentsPanel3.add(instr[7]);
  
    instrumentsPanel.add(instrumentsPanel1);
    instrumentsPanel.add(instrumentsPanel2);
    instrumentsPanel.add(instrumentsPanel3);
  
    instrumentsPanel.validate();
    
    add(instrumentsPanel);
  
    
  /////////////////////////////////////////////////////
  
    Panel p = new Panel(new FlowLayout());
    Panel p1 = new Panel(new FlowLayout());
  
    velocityScrollbar = 
      new Scrollbar(Scrollbar.VERTICAL, -64, 1, -127, 0);
    velocityScrollbar.addAdjustmentListener (
        new AdjustmentListener() {
      public void adjustmentValueChanged (
          AdjustmentEvent e) {
    
        velocity = 
          -((Scrollbar)e.getSource()).getValue ();
        velocityLabel.setText(
          Integer.toString(velocity) );
      }
    });
  
    pressureScrollbar = 
      new Scrollbar(Scrollbar.VERTICAL, -64, 1, -127, 0);
    pressureScrollbar.addAdjustmentListener (
        new AdjustmentListener() {
      public void adjustmentValueChanged (
          AdjustmentEvent e) {
        int pressure = 
          -((Scrollbar)e.getSource()).getValue ();
        pressureLabel.setText( 
          Integer.toString(pressure) );
        
        midiChannels[channelNumber].setChannelPressure(
          pressure);
      }
    });
  
    bendScrollbar = 
      new Scrollbar(Scrollbar.VERTICAL, -64, 1, -127, 0);
    bendScrollbar.addAdjustmentListener (
        new AdjustmentListener() {
      public void adjustmentValueChanged (
          AdjustmentEvent e) {
        int bend = 
          -((Scrollbar)e.getSource()).getValue ();
        bendLabel.setText( Integer.toString(bend) );
        midiChannels[channelNumber].setPitchBend(bend);
      }
    });
  
    volScrollbar = new Scrollbar(
      Scrollbar.VERTICAL, -100, 1, -127, 0);
    volScrollbar.addAdjustmentListener (
        new AdjustmentListener() {
      public void adjustmentValueChanged (
          AdjustmentEvent e) {
        int vol = 
          -((Scrollbar)e.getSource()).getValue ();
        volLabel.setText( Integer.toString(vol) );
        
        midiChannels[channelNumber].controlChange(
          VOLUME_CONTROLLER,vol);
      }
    });
  
    panScrollbar = 
      new Scrollbar(Scrollbar.VERTICAL, -64, 1, -127, 0);
    panScrollbar.addAdjustmentListener (
        new AdjustmentListener() {
      public void adjustmentValueChanged (
          AdjustmentEvent e) {
        int pan = 
          -((Scrollbar)e.getSource()).getValue ();
        panLabel.setText( Integer.toString(pan) );
        
        midiChannels[channelNumber].controlChange(
          PAN_CONTROLLER,pan);
      }
    });
  
    revScrollbar = 
      new Scrollbar(Scrollbar.VERTICAL, -64, 1, -127, 0);
    revScrollbar.addAdjustmentListener (
        new AdjustmentListener() {
      public void adjustmentValueChanged (
          AdjustmentEvent e) {
        int rev = 
          -((Scrollbar)e.getSource()).getValue ();
        revLabel.setText( Integer.toString(rev) );
        
        midiChannels[channelNumber].controlChange(
          REVERB_LEVEL_CONTROLLER, rev);
      }
    });
  
    muteCheckbox = new Checkbox ("Mute", false);
    muteCheckbox.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        if (muteCheckbox.getState()) {
  
          midiChannels[channelNumber].setMute(true);
          
        } else {
          
          midiChannels[channelNumber].setMute(false);
            
        }
      }
    });
      
    monoCheckbox = new Checkbox ("Mono", false);
    monoCheckbox.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        if (monoCheckbox.getState()) {
  
          midiChannels[channelNumber].setMono(true);
          
        } else {
          
          midiChannels[channelNumber].setMono(false);
            
        }
      }
    });
      
    soloCheckbox = new Checkbox ("Solo", false);
    soloCheckbox.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        if (soloCheckbox.getState()) {
  
          midiChannels[channelNumber].setSolo(true);
          
        } else {
          
          midiChannels[channelNumber].setSolo(false);
            
        }
      }
    });
  
    sustainCheckbox = new Checkbox ("Sustain", false);
    sustainCheckbox.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        if (sustainCheckbox.getState())
              
          midiChannels[channelNumber].controlChange(
          SUSTAIN_CONTROLLER,127);
        else
              
          midiChannels[channelNumber].controlChange(
          SUSTAIN_CONTROLLER,0);
      }
    });
    
    soundOffButton = new Button("Sound OFF");
    soundOffButton.setBackground(Color.yellow);
    soundOffButton.addActionListener(
        new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        for(int i=0;i<16;i++) 
          midiChannels[i].allNotesOff();
      }
    });
    
    quitButton = new Button("QUIT");
    quitButton.setBackground(Color.red);
    quitButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.exit(0);
      }
    });
    
      
    statusButton = new Button("Status");
    statusButton.setBackground(Color.lightGray);
    statusButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        printStatus();
      }
    });
    
    p.add(new Label("Ch Vol:"));
    p.add(volScrollbar);
    p.add(volLabel);
    p.add(new Label("Ch Pan:"));
    p.add(panScrollbar);
    p.add(panLabel);
    p.add(new Label("Ch Rev:"));
    p.add(revScrollbar);
    p.add(revLabel);
    p.add(new Label("Ch Bend:"));
    p.add(bendScrollbar);
    p.add(bendLabel);
    p.add(new Label("Vel:"));
    p.add(velocityScrollbar);
    p.add(velocityLabel);
    p.add(new Label("Press:"));
    p.add(pressureScrollbar);
    p.add(pressureLabel);
    
    p1.add(sustainCheckbox);
    p1.add(muteCheckbox);
    p1.add(monoCheckbox);
    p1.add(soloCheckbox);
    p1.add(statusButton);
    p1.add(soundOffButton);
    p1.add(quitButton);
    
    add(p);
    add(p1);
      
    setTitle("General MIDI");
    setSize(800, 400);
    setVisible(true);
  
    pack();
    show();
  
    updateGUIStatus();
  
  } // end ToySynth()
  
  final int xOffset = 40;
  final int yOffset = 10;
  
  int X (int x) {
    return (x*4 + xOffset);
  }
  
  int Y (int x) {
    return (x*4 + yOffset);
  }
  
  int D (int x) {
    return (x*4);
  }
  
  public void updateGUIStatus() {
  
    // update all the GUI fields to reflect the status 
    // of the current channel
    // NOTE: THIS IS NOT FUNCTIONAL IN JAVA SOUND 
    // 0.85 EA RELEASE
  
    //int temp;
      
    //// volume
    //temp = 
    midiChannels[channelNumber].getController(
      VOLUME_CONTROLLER);
    //volScrollbar.setValue( - temp );
    //volLabel.setText( Integer.toString( temp ));
    //// pan
    //temp = 
    midiChannels[channelNumber].getController(
      PAN_CONTROLLER);
    //panScrollbar.setValue( - temp );
    //panLabel.setText( Integer.toString( temp ));
    //// pitch bend
    //temp = midiChannels[channelNumber].getPitchBend();
    //bendScrollbar.setValue( - temp );
    //bendLabel.setText( Integer.toString( temp ));
    //// reverb
    //temp = 
    midiChannels[channelNumber].getController(
      REVERB_LEVEL_CONTROLLER);
    //revScrollbar.setValue( - temp );
    //revLabel.setText( Integer.toString( temp ));
    //// pressure
    //temp = 
    //midiChannels[channelNumber].getChannelPressure();
    //pressureScrollbar.setValue( - temp );
    //pressureLabel.setText( Integer.toString( temp ));
    //// mute
    //muteCheckbox.setState( 
    midiChannels[channelNumber].getMute() );
    //// sustain
    //sustainCheckbox.setState( 
    midiChannels[channelNumber].getController(
      SUSTAIN_CONTROLLER)==0 ? false : true  );
    //// mono
    //monoCheckbox.setState( 
    midiChannels[channelNumber].getMono() );
    //// solo
    //soloCheckbox.setState( 
    midiChannels[channelNumber].getSolo() );
  
  }
  
  public void printStatus() {
  
    System.out.println(
      "CURRENT STATUS - note that some 
      functionality here is not");
    System.out.println(
      "                 implemented in Java 
      Sound 0.86");
    System.out.println("  Current channel     : " + 
      channelNumber);
    System.out.println("  Program             : " + 
      midiChannels[channelNumber].getProgram() );
    System.out.println("  Channel volume      : " + 
      midiChannels[channelNumber].getController(
      VOLUME_CONTROLLER) );
    System.out.println("  Channel pan         : " + 
    midiChannels[channelNumber].getController(
      PAN_CONTROLLER) );
    System.out.println("  Channel bend        : " + 
      midiChannels[channelNumber].getPitchBend() );
    System.out.println("  Channel pressure    : " + 
      midiChannels[channelNumber].getChannelPressure() );
    System.out.println("  Channel reverb      : " + 
      midiChannels[channelNumber].getController(
      REVERB_CONTROLLER) );
    System.out.println("  Channel reverb level: " + 
      midiChannels[channelNumber].getController(
      REVERB_LEVEL_CONTROLLER) );
    System.out.println("  Channel sustain     : " + 
      midiChannels[channelNumber].getController(
      SUSTAIN_CONTROLLER) );
    System.out.println("  Channel mute        : " + 
      midiChannels[channelNumber].getMute() );
    System.out.println("  Channel mono        : " + 
      midiChannels[channelNumber].getMono() );
    System.out.println("  Channel solo        : " + 
      midiChannels[channelNumber].getSolo() );
  
  }
  
  public void mouseClicked(MouseEvent e) {
    
  }

  public void mousePressed(MouseEvent e) {
  
    Component component = e.getComponent();    
    if ( ! (component instanceof Label) )
      return;
  
    int keyNumber = 
      ((pianoKey) component).keyNumber + transpose;
  
    if (singleNoteMode) {
      lastKeyNumber = keyNumber;
      midiChannels[channelNumber].noteOn( 
        keyNumber, velocity);
      return;
    }
  }
  
  public void mouseReleased(MouseEvent e) {
  
    Component component = e.getComponent();    
    if ( ! (component instanceof Label) )
      return;
  
    if (singleNoteMode) {
      midiChannels[channelNumber].noteOff( 
        lastKeyNumber, velocity);
      return;
    }
  }
  
  public void mouseEntered(MouseEvent e) {
      
    //System.out.println(
    //  "mouseEntered event handler...");
  }
  
  public void mouseExited(MouseEvent e) {
  
    //System.out.println("mouseExited event handler...");
  }
  
  // -------------------
  // class programChange
  // -------------------
  
  class programChange implements ItemListener {
  
    ToySynth ts = null;
  
    public programChange( ToySynth ts ) {
      this.ts = ts;
    }
    public void itemStateChanged(ItemEvent e) {
  
      Object component = e.getSource();
      if( ! (component instanceof Choice) ) return;
  
      Choice c = (Choice)component;
      int index=0;
  
      if (c.equals(instr[0]))
        index = 0 + c.getSelectedIndex();
      else if (c.equals(instr[1]))      
        index = 16 + c.getSelectedIndex();
      else if (c.equals(instr[2]))
        index = 32 + c.getSelectedIndex();
      else if (c.equals(instr[3]))
        index = 48 + c.getSelectedIndex();
      else if (c.equals(instr[4]))
        index = 64 + c.getSelectedIndex();
      else if (c.equals(instr[5]))
        index = 80 + c.getSelectedIndex();
      else if (c.equals(instr[6]))
        index = 96 + c.getSelectedIndex();
      else if (c.equals(instr[7]))
        index = 112 + c.getSelectedIndex();
            
  
      synth.loadInstrument( instruments[index] );
      midiChannels[channelNumber].programChange(index);
        
        
      instrumentLabel.setText ( "Instrument: " + 
        instruments[index].getName() );
  
      ts.validate();
    }
  }
  
  class channelChange implements ItemListener {
  
    ToySynth ts;
  
    public channelChange( ToySynth ts ) {
      this.ts = ts;
    }
    public void itemStateChanged(ItemEvent e) {
  
      Object component = e.getSource();
      if( ! (component instanceof Choice) ) return;
      Choice c = (Choice)component;
      int newchannel = c.getSelectedIndex();
  
      // update the channel
      channelNumber = newchannel;
        
      // update GUI fields for status of this channel
      instrumentLabel.setText ( "Instrument: " +  
        instruments[midiChannels[
        channelNumber].getProgram()].getName() );
  
      ts.updateGUIStatus();
      ts.validate();
    }
  }
  
  // --------------
  // class pianoKey
  // --------------
  
  class pianoKey extends Label {
    public int keyNumber;
  
    pianoKey(int keyNumber, boolean white) {
      this.keyNumber = keyNumber;
      if (white) {
        setBackground(Color.white);
      }
      else
        setBackground(Color.black);
    }
    public void paint (Graphics g) {
      g.drawRect(0, 0, getSize().width - 1, 
        getSize().height -1 );
    }
    public void middleC(Graphics g) {
      Graphics2D g2 = (Graphics2D) g;
      int x = getSize().width / 2;
      int y = getSize().height - getSize().height / 4;
      g2.setRenderingHint(
        RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(Color.blue);
      g2.fillOval(x, y, 3, 3);
    }
  } 
  
  // ----
  // MAIN
  // ----
  
  public static void main( String[] args) {           
    ToySynth ts = new ToySynth();
  }
}
  
  /*
   * "@(#)ToySynth.java  1.6 99/04/22
   *
   * Copyright (c) 1999 Sun Microsystems, Inc. All 
   * Rights Reserved.
   *
   * Sun grants you ("Licensee") a non-exclusive, 
   * royalty free, license to use, modify and 
   * redistribute this software in source and binary 
   * code form, provided that i) this copyright notice 
   * and license appear on all copies of the software; 
   * and ii) Licensee does not utilize the software in 
   * a manner which is disparaging to Sun.
   *
   * This software is provided "AS IS," without a 
   * warranty of any kind. ALL EXPRESS OR IMPLIED 
   * CONDITIONS, REPRESENTATIONS AND WARRANTIES, 
   * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
   * FITNESS FOR A PARTICULAR PURPOSE OR
   * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS 
   * LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES 
   * SUFFERED BY LICENSEE AS A RESULT OF USING, 
   * MODIFYING OR DISTRIBUTING THE SOFTWARE OR ITS 
   * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS 
   * BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR 
   * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, 
   * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED 
   * AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING 
   * OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, 
   * EVEN IF SUN HAS BEEN ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGES.
   *
   * This software is not designed or intended for use 
   * in on-line control of aircraft, air traffic, 
   * aircraft navigation or aircraft communications; or 
   * in the design, construction, operation or 
   * maintenance of any nuclear facility. Licensee 
   * represents and warrants that it will not use or
   * redistribute the Software for such purposes.
   */

Print Button
[ This page was updated: 30-Mar-2000 ]
Products & APIs | Developer Connection | Docs & Training | Online Support
Community Discussion | Industry News | Solutions Marketplace | Case Studies
Glossary - Applets - Tutorial - Employment - Business & Licensing - Java Store - Java in the Real World
FAQ | Feedback | Map | A-Z Index
For more information on Java technology
and other software from Sun Microsystems, call:
(800) 786-7638
Outside the U.S. and Canada, dial your country's AT&T Direct Access Number first.
Sun Microsystems, Inc.
Copyright © 1995-2000 Sun Microsystems, Inc.
All Rights Reserved. Terms of Use. Privacy Policy.