1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25    @summary Test SoftChannel program and bank change */
  26 
  27 import java.io.IOException;
  28 
  29 import javax.sound.midi.*;
  30 import javax.sound.sampled.*;
  31 
  32 import com.sun.media.sound.*;
  33 
  34 public class ProgramAndBankChange {
  35 
  36     private static SimpleInstrument generateTestInstrument(Patch patch) {
  37         ModelOscillator osc = new ModelOscillator() {
  38             public float getAttenuation() {
  39                 return 0;
  40             }
  41 
  42             public int getChannels() {
  43                 return 1;
  44             }
  45 
  46             public ModelOscillatorStream open(float samplerate) {
  47                 return new ModelOscillatorStream() {
  48                     public void close() throws IOException {
  49                     }
  50 
  51                     public void noteOff(int velocity) {
  52                     }
  53 
  54                     public void noteOn(MidiChannel channel, VoiceStatus voice,
  55                             int noteNumber, int velocity) {
  56                     }
  57 
  58                     public int read(float[][] buffer, int offset, int len)
  59                             throws IOException {
  60                         return len;
  61                     }
  62 
  63                     public void setPitch(float ipitch) {
  64                     }
  65                 };
  66             }
  67         };
  68         ModelPerformer performer = new ModelPerformer();
  69         performer.getOscillators().add(osc);
  70         SimpleInstrument testinstrument = new SimpleInstrument();
  71         testinstrument.setPatch(patch);
  72         testinstrument.add(performer);
  73         return testinstrument;
  74     }
  75 
  76     private static void assertTrue(boolean value) throws Exception {
  77         if (!value)
  78             throw new RuntimeException("assertTrue fails!");
  79     }
  80 
  81     private static void testProgramAndBank(SoftSynthesizer soft,
  82             AudioInputStream stream, Patch patch) throws Exception {
  83 
  84         int program = patch.getProgram();
  85         int bank = patch.getBank();
  86 
  87         MidiChannel channel = soft.getChannels()[0];
  88         byte[] buff = new byte[2048];
  89 
  90         channel.programChange(bank, program);
  91         channel.noteOn(64, 64);
  92         stream.read(buff, 0, buff.length);
  93 
  94         int foundprogram = -1;
  95         int foundbank = -1;
  96         VoiceStatus[] vstatus = soft.getVoiceStatus();
  97         for (int i = 0; i < vstatus.length; i++) {
  98             if (vstatus[i].active) {
  99                 foundprogram = vstatus[i].program;
 100                 foundbank = vstatus[i].bank;
 101                 break;
 102             }
 103         }
 104 
 105         assertTrue(foundprogram == program);
 106         assertTrue(foundbank == bank);
 107 
 108         channel.noteOn(64, 0);
 109         stream.read(buff, 0, buff.length);
 110 
 111         channel = soft.getChannels()[1];
 112         // Send MSB Bank
 113         channel.controlChange(0x00, bank / 128);
 114         // Send LSB Bank
 115         channel.controlChange(0x20, bank % 128);
 116         // Send Program Change
 117         channel.programChange(program);
 118         channel.noteOn(64, 64);
 119         stream.read(buff, 0, buff.length);
 120 
 121         foundprogram = -1;
 122         foundbank = -1;
 123         vstatus = soft.getVoiceStatus();
 124         for (int i = 0; i < vstatus.length; i++) {
 125             if (vstatus[i].active) {
 126                 foundprogram = vstatus[i].program;
 127                 foundbank = vstatus[i].bank;
 128                 break;
 129             }
 130         }
 131         assertTrue(foundprogram == program);
 132         assertTrue(foundbank == bank);
 133         channel.noteOn(64, 0);
 134         stream.read(buff, 0, buff.length);
 135     }
 136 
 137     public static void main(String[] args) throws Exception {
 138         SoftSynthesizer soft = new SoftSynthesizer();
 139         AudioInputStream stream = soft.openStream(null, null);
 140         soft.unloadAllInstruments(soft.getDefaultSoundbank());
 141 
 142         soft.loadInstrument(generateTestInstrument(new Patch(0, 0)));
 143         soft.loadInstrument(generateTestInstrument(new Patch(7, 0)));
 144         soft.loadInstrument(generateTestInstrument(new Patch(20, 10)));
 145         soft.loadInstrument(generateTestInstrument(new Patch(3678, 15)));
 146         soft.loadInstrument(generateTestInstrument(new Patch(4678, 15)));
 147 
 148         testProgramAndBank(soft, stream, new Patch(0, 0));
 149         testProgramAndBank(soft, stream, new Patch(7, 0));
 150         testProgramAndBank(soft, stream, new Patch(20, 10));
 151         testProgramAndBank(soft, stream, new Patch(3678, 15));
 152         testProgramAndBank(soft, stream, new Patch(4678, 15));
 153 
 154         soft.close();
 155     }
 156 }