jdk/test/javax/sound/midi/Gervill/SoftTuning/RealTimeTuning.java
changeset 6502 13b20559a04a
child 21596 0e3a39f29dbc
equal deleted inserted replaced
6501:684810d882b3 6502:13b20559a04a
       
     1 /*
       
     2  * Copyright (c) 2010, 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.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 /* @test
       
    27  @summary Test RealTime-tunings using SoftReciver.send method */
       
    28 
       
    29 import java.io.IOException;
       
    30 
       
    31 import javax.sound.midi.*;
       
    32 import javax.sound.sampled.*;
       
    33 
       
    34 import com.sun.media.sound.*;
       
    35 
       
    36 public class RealTimeTuning {
       
    37 
       
    38     private static class PitchSpy {
       
    39         public float pitch = 0;
       
    40 
       
    41         public Soundbank getSoundBank() {
       
    42             ModelOscillator osc = new ModelOscillator() {
       
    43                 public float getAttenuation() {
       
    44                     return 0;
       
    45                 }
       
    46 
       
    47                 public int getChannels() {
       
    48                     return 0;
       
    49                 }
       
    50 
       
    51                 public ModelOscillatorStream open(float samplerate) {
       
    52                     return new ModelOscillatorStream() {
       
    53                         public void close() throws IOException {
       
    54                             pitch = 0;
       
    55                         }
       
    56 
       
    57                         public void noteOff(int velocity) {
       
    58                             pitch = 0;
       
    59                         }
       
    60 
       
    61                         public void noteOn(MidiChannel channel,
       
    62                                 VoiceStatus voice, int noteNumber, int velocity) {
       
    63                             pitch = noteNumber * 100;
       
    64                         }
       
    65 
       
    66                         public int read(float[][] buffer, int offset, int len)
       
    67                                 throws IOException {
       
    68                             return len;
       
    69                         }
       
    70 
       
    71                         public void setPitch(float ipitch) {
       
    72                             pitch = ipitch;
       
    73                         }
       
    74                     };
       
    75                 }
       
    76             };
       
    77             ModelPerformer performer = new ModelPerformer();
       
    78             performer.getOscillators().add(osc);
       
    79             SimpleInstrument testinstrument = new SimpleInstrument();
       
    80             testinstrument.setPatch(new Patch(0, 0));
       
    81             testinstrument.add(performer);
       
    82             SimpleSoundbank testsoundbank = new SimpleSoundbank();
       
    83             testsoundbank.addInstrument(testinstrument);
       
    84             return testsoundbank;
       
    85         }
       
    86     }
       
    87 
       
    88     public static void sendTuningChange(Receiver recv, int channel,
       
    89             int tuningpreset, int tuningbank) throws InvalidMidiDataException {
       
    90         // Data Entry
       
    91         ShortMessage sm1 = new ShortMessage();
       
    92         sm1.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 04);
       
    93         ShortMessage sm2 = new ShortMessage();
       
    94         sm2.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);
       
    95 
       
    96         // Tuning Bank
       
    97         ShortMessage sm3 = new ShortMessage();
       
    98         sm3.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06, tuningbank);
       
    99         // Data Increment
       
   100         ShortMessage sm4 = new ShortMessage();
       
   101         sm4.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);
       
   102         // Data Decrement
       
   103         ShortMessage sm5 = new ShortMessage();
       
   104         sm5.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);
       
   105 
       
   106         // Data Entry
       
   107         ShortMessage sm6 = new ShortMessage();
       
   108         sm6.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 03);
       
   109         ShortMessage sm7 = new ShortMessage();
       
   110         sm7.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);
       
   111 
       
   112         // Tuning program
       
   113         ShortMessage sm8 = new ShortMessage();
       
   114         sm8
       
   115                 .setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06,
       
   116                         tuningpreset);
       
   117         // Data Increment
       
   118         ShortMessage sm9 = new ShortMessage();
       
   119         sm9.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);
       
   120         // Data Decrement
       
   121         ShortMessage sm10 = new ShortMessage();
       
   122         sm10.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);
       
   123 
       
   124         recv.send(sm1, -1);
       
   125         recv.send(sm2, -1);
       
   126         recv.send(sm3, -1);
       
   127         recv.send(sm4, -1);
       
   128         recv.send(sm5, -1);
       
   129         recv.send(sm6, -1);
       
   130         recv.send(sm7, -1);
       
   131         recv.send(sm8, -1);
       
   132         recv.send(sm9, -1);
       
   133         recv.send(sm10, -1);
       
   134 
       
   135     }
       
   136 
       
   137     private static void assertTrue(boolean value) throws Exception {
       
   138         if (!value)
       
   139             throw new RuntimeException("assertTrue fails!");
       
   140     }
       
   141 
       
   142     public static void testTunings(int[] msg, int tuningProgram,
       
   143             int tuningBank, int targetNote, float targetPitch, boolean realtime)
       
   144             throws Exception {
       
   145         AudioSynthesizer synth = new SoftSynthesizer();
       
   146         AudioInputStream stream = synth.openStream(null, null);
       
   147         Receiver recv = synth.getReceiver();
       
   148         MidiChannel channel = synth.getChannels()[0];
       
   149         byte[] buff = new byte[2048];
       
   150 
       
   151         // Create test instrument which we can use to monitor pitch changes
       
   152         PitchSpy pitchspy = new PitchSpy();
       
   153 
       
   154         synth.unloadAllInstruments(synth.getDefaultSoundbank());
       
   155         synth.loadAllInstruments(pitchspy.getSoundBank());
       
   156 
       
   157         SysexMessage sysex = null;
       
   158 
       
   159         // Send tuning changes
       
   160         if (msg != null) {
       
   161             byte[] bmsg = new byte[msg.length];
       
   162             for (int i = 0; i < bmsg.length; i++)
       
   163                 bmsg[i] = (byte) msg[i];
       
   164             sysex = new SysexMessage();
       
   165             sysex.setMessage(bmsg, bmsg.length);
       
   166             if (targetPitch == 0) {
       
   167                 targetPitch = (float) new SoftTuning(bmsg)
       
   168                         .getTuning(targetNote);
       
   169                 // Check if targetPitch != targetNote * 100
       
   170                 assertTrue(Math.abs(targetPitch - targetNote * 100.0) > 0.001);
       
   171             }
       
   172         }
       
   173 
       
   174         if (tuningProgram != -1)
       
   175             sendTuningChange(recv, 0, tuningProgram, tuningBank);
       
   176 
       
   177         // First test without tunings
       
   178         channel.noteOn(targetNote, 64);
       
   179         stream.read(buff, 0, buff.length);
       
   180         assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);
       
   181 
       
   182         // Test if realtime/non-realtime works
       
   183         if (sysex != null)
       
   184             recv.send(sysex, -1);
       
   185         stream.read(buff, 0, buff.length);
       
   186         if (realtime)
       
   187             assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);
       
   188         else
       
   189             assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);
       
   190 
       
   191         // Test if tunings works
       
   192         channel.noteOn(targetNote, 0);
       
   193         stream.read(buff, 0, buff.length);
       
   194         assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);
       
   195 
       
   196         channel.noteOn(targetNote, 64);
       
   197         stream.read(buff, 0, buff.length);
       
   198         assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);
       
   199 
       
   200         channel.noteOn(targetNote, 0);
       
   201         stream.read(buff, 0, buff.length);
       
   202         assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);
       
   203 
       
   204         stream.close();
       
   205     }
       
   206 
       
   207     public static void main(String[] args) throws Exception {
       
   208         // Test with no-tunings
       
   209         testTunings(null, -1, -1, 60, 6000, false);
       
   210 
       
   211         int[] msg;
       
   212         // 0x02 SINGLE NOTE TUNING CHANGE (REAL-TIME)
       
   213         msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x02, 0x10, 0x02, 36, 36, 64,
       
   214                 0, 60, 70, 0, 0, 0xf7 };
       
   215         testTunings(msg, 0x10, 0, 60, 7000, true);
       
   216 
       
   217         // 0x07 SINGLE NOTE TUNING CHANGE (NON REAL-TIME) (BANK)
       
   218         msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,
       
   219                 36, 64, 0, 60, 80, 0, 0, 0xf7 };
       
   220         testTunings(msg, 0x07, 0x05, 60, 8000, false);
       
   221 
       
   222         // 0x07 SINGLE NOTE TUNING CHANGE (REAL-TIME) (BANK)
       
   223         msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,
       
   224                 36, 64, 0, 60, 80, 0, 0, 0xf7 };
       
   225         testTunings(msg, 0x07, 0x05, 60, 8000, true);
       
   226 
       
   227         // 0x08 scale/octave tuning 1-byte form (Non Real-Time)
       
   228         msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,
       
   229                 10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };
       
   230         testTunings(msg, -1, -1, 60, 0, false);
       
   231 
       
   232         // 0x08 scale/octave tuning 1-byte form (REAL-TIME)
       
   233         msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,
       
   234                 10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };
       
   235         testTunings(msg, -1, -1, 60, 0, true);
       
   236 
       
   237         // 0x09 scale/octave tuning 2-byte form (Non Real-Time)
       
   238         msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,
       
   239                 10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,
       
   240                 30, 35, 40, 45, 50, 51, 52, 0xf7 };
       
   241         testTunings(msg, -1, -1, 60, 0, false);
       
   242 
       
   243         // 0x09 scale/octave tuning 2-byte form (REAL-TIME)
       
   244         msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,
       
   245                 10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,
       
   246                 30, 35, 40, 45, 50, 51, 52, 0xf7 };
       
   247         testTunings(msg, -1, -1, 60, 0, true);
       
   248 
       
   249     }
       
   250 }