Path: blob/master/test/jdk/javax/sound/midi/Gervill/SoftTuning/RealTimeTuning.java
41161 views
/*1* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24@summary Test RealTime-tunings using SoftReciver.send method25@modules java.desktop/com.sun.media.sound26*/2728import java.io.IOException;2930import javax.sound.midi.*;31import javax.sound.sampled.*;3233import com.sun.media.sound.*;3435public class RealTimeTuning {3637private static class PitchSpy {38public float pitch = 0;3940public Soundbank getSoundBank() {41ModelOscillator osc = new ModelOscillator() {42public float getAttenuation() {43return 0;44}4546public int getChannels() {47return 0;48}4950public ModelOscillatorStream open(float samplerate) {51return new ModelOscillatorStream() {52public void close() throws IOException {53pitch = 0;54}5556public void noteOff(int velocity) {57pitch = 0;58}5960public void noteOn(MidiChannel channel,61VoiceStatus voice, int noteNumber, int velocity) {62pitch = noteNumber * 100;63}6465public int read(float[][] buffer, int offset, int len)66throws IOException {67return len;68}6970public void setPitch(float ipitch) {71pitch = ipitch;72}73};74}75};76ModelPerformer performer = new ModelPerformer();77performer.getOscillators().add(osc);78SimpleInstrument testinstrument = new SimpleInstrument();79testinstrument.setPatch(new Patch(0, 0));80testinstrument.add(performer);81SimpleSoundbank testsoundbank = new SimpleSoundbank();82testsoundbank.addInstrument(testinstrument);83return testsoundbank;84}85}8687public static void sendTuningChange(Receiver recv, int channel,88int tuningpreset, int tuningbank) throws InvalidMidiDataException {89// Data Entry90ShortMessage sm1 = new ShortMessage();91sm1.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 04);92ShortMessage sm2 = new ShortMessage();93sm2.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);9495// Tuning Bank96ShortMessage sm3 = new ShortMessage();97sm3.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06, tuningbank);98// Data Increment99ShortMessage sm4 = new ShortMessage();100sm4.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);101// Data Decrement102ShortMessage sm5 = new ShortMessage();103sm5.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);104105// Data Entry106ShortMessage sm6 = new ShortMessage();107sm6.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 03);108ShortMessage sm7 = new ShortMessage();109sm7.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);110111// Tuning program112ShortMessage sm8 = new ShortMessage();113sm8114.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06,115tuningpreset);116// Data Increment117ShortMessage sm9 = new ShortMessage();118sm9.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);119// Data Decrement120ShortMessage sm10 = new ShortMessage();121sm10.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);122123recv.send(sm1, -1);124recv.send(sm2, -1);125recv.send(sm3, -1);126recv.send(sm4, -1);127recv.send(sm5, -1);128recv.send(sm6, -1);129recv.send(sm7, -1);130recv.send(sm8, -1);131recv.send(sm9, -1);132recv.send(sm10, -1);133134}135136private static void assertTrue(boolean value) throws Exception {137if (!value)138throw new RuntimeException("assertTrue fails!");139}140141public static void testTunings(int[] msg, int tuningProgram,142int tuningBank, int targetNote, float targetPitch, boolean realtime)143throws Exception {144AudioSynthesizer synth = new SoftSynthesizer();145AudioInputStream stream = synth.openStream(null, null);146Receiver recv = synth.getReceiver();147MidiChannel channel = synth.getChannels()[0];148byte[] buff = new byte[2048];149150// Create test instrument which we can use to monitor pitch changes151PitchSpy pitchspy = new PitchSpy();152153synth.unloadAllInstruments(synth.getDefaultSoundbank());154synth.loadAllInstruments(pitchspy.getSoundBank());155156SysexMessage sysex = null;157158// Send tuning changes159if (msg != null) {160byte[] bmsg = new byte[msg.length];161for (int i = 0; i < bmsg.length; i++)162bmsg[i] = (byte) msg[i];163sysex = new SysexMessage();164sysex.setMessage(bmsg, bmsg.length);165if (targetPitch == 0) {166targetPitch = (float) new SoftTuning(bmsg)167.getTuning(targetNote);168// Check if targetPitch != targetNote * 100169assertTrue(Math.abs(targetPitch - targetNote * 100.0) > 0.001);170}171}172173if (tuningProgram != -1)174sendTuningChange(recv, 0, tuningProgram, tuningBank);175176// First test without tunings177channel.noteOn(targetNote, 64);178stream.read(buff, 0, buff.length);179assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);180181// Test if realtime/non-realtime works182if (sysex != null)183recv.send(sysex, -1);184stream.read(buff, 0, buff.length);185if (realtime)186assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);187else188assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);189190// Test if tunings works191channel.noteOn(targetNote, 0);192stream.read(buff, 0, buff.length);193assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);194195channel.noteOn(targetNote, 64);196stream.read(buff, 0, buff.length);197assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);198199channel.noteOn(targetNote, 0);200stream.read(buff, 0, buff.length);201assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);202203stream.close();204}205206public static void main(String[] args) throws Exception {207// Test with no-tunings208testTunings(null, -1, -1, 60, 6000, false);209210int[] msg;211// 0x02 SINGLE NOTE TUNING CHANGE (REAL-TIME)212msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x02, 0x10, 0x02, 36, 36, 64,2130, 60, 70, 0, 0, 0xf7 };214testTunings(msg, 0x10, 0, 60, 7000, true);215216// 0x07 SINGLE NOTE TUNING CHANGE (NON REAL-TIME) (BANK)217msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,21836, 64, 0, 60, 80, 0, 0, 0xf7 };219testTunings(msg, 0x07, 0x05, 60, 8000, false);220221// 0x07 SINGLE NOTE TUNING CHANGE (REAL-TIME) (BANK)222msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,22336, 64, 0, 60, 80, 0, 0, 0xf7 };224testTunings(msg, 0x07, 0x05, 60, 8000, true);225226// 0x08 scale/octave tuning 1-byte form (Non Real-Time)227msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,22810, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };229testTunings(msg, -1, -1, 60, 0, false);230231// 0x08 scale/octave tuning 1-byte form (REAL-TIME)232msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,23310, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };234testTunings(msg, -1, -1, 60, 0, true);235236// 0x09 scale/octave tuning 2-byte form (Non Real-Time)237msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,23810, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,23930, 35, 40, 45, 50, 51, 52, 0xf7 };240testTunings(msg, -1, -1, 60, 0, false);241242// 0x09 scale/octave tuning 2-byte form (REAL-TIME)243msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,24410, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,24530, 35, 40, 45, 50, 51, 52, 0xf7 };246testTunings(msg, -1, -1, 60, 0, true);247248}249}250251252