Mercurial > hg > icedtea9-forest > jdk
changeset 2859:3fa6114faa54
6943053: Gervill: failures on invalid ranges and 14-bit banks
Summary: ModelStandardIndexedDirector fails on invalid ranges. Program changes with 14-bit banks where handled incorectly as 7-bit banks.
Reviewed-by: amenkov
author | kalli |
---|---|
date | Mon, 13 Sep 2010 15:34:24 +0400 |
parents | 903f44341e34 |
children | c610f475558d |
files | src/share/classes/com/sun/media/sound/ModelStandardIndexedDirector.java src/share/classes/com/sun/media/sound/SoftChannel.java test/javax/sound/midi/Gervill/ModelStandardIndexedDirector/ModelStandardIndexedDirectorTest.java test/javax/sound/midi/Gervill/SoftChannel/ProgramAndBankChange.java |
diffstat | 4 files changed, 382 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/media/sound/ModelStandardIndexedDirector.java Mon Sep 13 15:12:31 2010 +0400 +++ b/src/share/classes/com/sun/media/sound/ModelStandardIndexedDirector.java Mon Sep 13 15:34:24 2010 +0400 @@ -57,8 +57,7 @@ buildindex(); } - private int[] lookupIndex(int x, int y) - { + private int[] lookupIndex(int x, int y) { if ((x >= 0) && (x < 128) && (y >= 0) && (y < 128)) { int xt = trantables[0][x]; int yt = trantables[1][y]; @@ -69,14 +68,30 @@ return null; } + private int restrict(int value) { + if(value < 0) return 0; + if(value > 127) return 127; + return value; + } + private void buildindex() { trantables = new byte[2][129]; counters = new int[trantables.length]; for (ModelPerformer performer : performers) { - trantables[0][performer.getKeyFrom()] = 1; - trantables[0][performer.getKeyTo() + 1] = 1; - trantables[1][performer.getVelFrom()] = 1; - trantables[1][performer.getVelTo() + 1] = 1; + int keyFrom = performer.getKeyFrom(); + int keyTo = performer.getKeyTo(); + int velFrom = performer.getVelFrom(); + int velTo = performer.getVelTo(); + if (keyFrom > keyTo) continue; + if (velFrom > velTo) continue; + keyFrom = restrict(keyFrom); + keyTo = restrict(keyTo); + velFrom = restrict(velFrom); + velTo = restrict(velTo); + trantables[0][keyFrom] = 1; + trantables[0][keyTo + 1] = 1; + trantables[1][velFrom] = 1; + trantables[1][velTo + 1] = 1; } for (int d = 0; d < trantables.length; d++) { byte[] trantable = trantables[d]; @@ -102,10 +117,20 @@ mat = new int[counters[0] * counters[1]][]; int ix = 0; for (ModelPerformer performer : performers) { - int x_from = trantables[0][performer.getKeyFrom()]; - int x_to = trantables[0][performer.getKeyTo() + 1]; - int y_from = trantables[1][performer.getVelFrom()]; - int y_to = trantables[1][performer.getVelTo() + 1]; + int keyFrom = performer.getKeyFrom(); + int keyTo = performer.getKeyTo(); + int velFrom = performer.getVelFrom(); + int velTo = performer.getVelTo(); + if (keyFrom > keyTo) continue; + if (velFrom > velTo) continue; + keyFrom = restrict(keyFrom); + keyTo = restrict(keyTo); + velFrom = restrict(velFrom); + velTo = restrict(velTo); + int x_from = trantables[0][keyFrom]; + int x_to = trantables[0][keyTo + 1]; + int y_from = trantables[1][velFrom]; + int y_to = trantables[1][velTo + 1]; if (x_to == -1) x_to = counters[0]; if (y_to == -1)
--- a/src/share/classes/com/sun/media/sound/SoftChannel.java Mon Sep 13 15:12:31 2010 +0400 +++ b/src/share/classes/com/sun/media/sound/SoftChannel.java Mon Sep 13 15:34:24 2010 +0400 @@ -1264,7 +1264,7 @@ } public void programChange(int bank, int program) { - bank = restrict7Bit(bank); + bank = restrict14Bit(bank); program = restrict7Bit(program); synchronized (control_mutex) { mainmixer.activity();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/sound/midi/Gervill/ModelStandardIndexedDirector/ModelStandardIndexedDirectorTest.java Mon Sep 13 15:34:24 2010 +0400 @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @summary Test ModelStandardIndexedDirector class */ + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + +import com.sun.media.sound.ModelConnectionBlock; +import com.sun.media.sound.ModelDirectedPlayer; +import com.sun.media.sound.ModelPerformer; +import com.sun.media.sound.ModelStandardDirector; +import com.sun.media.sound.ModelStandardIndexedDirector; + +public class ModelStandardIndexedDirectorTest { + + private static String treeToString(TreeSet<Integer> set) + { + StringBuffer buff = new StringBuffer(); + boolean first = true; + for(Integer s : set) + { + if(!first) + buff.append(";"); + buff.append(s); + first = false; + } + return buff.toString(); + } + + private static void testDirector(ModelPerformer[] performers) throws Exception + { + final TreeSet<Integer> played = new TreeSet<Integer>(); + ModelDirectedPlayer player = new ModelDirectedPlayer() + { + public void play(int performerIndex, + ModelConnectionBlock[] connectionBlocks) { + played.add(performerIndex); + } + }; + ModelStandardIndexedDirector idirector = + new ModelStandardIndexedDirector(performers, player); + ModelStandardDirector director = + new ModelStandardDirector(performers, player); + + for (int n = 0; n < 128; n++) + { + for (int v = 0; v < 128; v++) + { + director.noteOn(n, v); + String p1 = treeToString(played); + played.clear(); + idirector.noteOn(n, v); + String p2 = treeToString(played); + played.clear(); + if(!p1.equals(p2)) + throw new Exception( + "Note = " + n + ", Vel = " + v + " failed"); + } + } + } + + private static void testDirectorCombinations( + ModelPerformer[] performers) throws Exception + { + for (int i = 0; i < performers.length; i++) { + ModelPerformer[] performers2 = new ModelPerformer[i]; + for (int j = 0; j < performers2.length; j++) { + performers2[j] = performers[i]; + } + testDirector(performers2); + } + } + + private static void addPerformer( + List<ModelPerformer> performers, + int keyfrom, + int keyto, + int velfrom, + int velto) + { + ModelPerformer performer = new ModelPerformer(); + performer.setKeyFrom(keyfrom); + performer.setKeyTo(keyto); + performer.setVelFrom(velfrom); + performer.setVelTo(velto); + performers.add(performer); + } + + public static void main(String[] args) throws Exception + { + // Test collection of normal values + List<ModelPerformer> performers = new ArrayList<ModelPerformer>(); + addPerformer(performers, 0, 0, 0, 127); + addPerformer(performers, 0, 50, 0, 127); + addPerformer(performers, 0, 127, 0, 127); + addPerformer(performers, 21, 21, 0, 127); + addPerformer(performers, 21, 60, 0, 127); + addPerformer(performers, 21, 127, 0, 127); + addPerformer(performers, 50, 50, 0, 127); + addPerformer(performers, 50, 60, 0, 127); + addPerformer(performers, 50, 127, 0, 127); + addPerformer(performers, 73, 73, 0, 127); + addPerformer(performers, 73, 80, 0, 127); + addPerformer(performers, 73, 127, 0, 127); + addPerformer(performers, 127, 127, 0, 127); + addPerformer(performers, 0, 0, 60, 127); + addPerformer(performers, 0, 50, 60, 127); + addPerformer(performers, 0, 127, 60, 127); + addPerformer(performers, 21, 21, 60, 127); + addPerformer(performers, 21, 60, 60, 127); + addPerformer(performers, 21, 127, 60, 127); + addPerformer(performers, 50, 50, 60, 127); + addPerformer(performers, 50, 60, 60, 127); + addPerformer(performers, 50, 127, 60, 127); + addPerformer(performers, 73, 73, 60, 127); + addPerformer(performers, 73, 80, 60, 127); + addPerformer(performers, 73, 127, 60, 127); + addPerformer(performers, 127, 127, 60, 127); + addPerformer(performers, 0, 0, 80, 83); + addPerformer(performers, 0, 50, 80, 83); + addPerformer(performers, 0, 127, 80, 83); + addPerformer(performers, 21, 21, 80, 83); + addPerformer(performers, 21, 60, 80, 83); + addPerformer(performers, 21, 127, 80, 83); + addPerformer(performers, 50, 50, 80, 83); + addPerformer(performers, 50, 60, 80, 83); + addPerformer(performers, 50, 127, 80, 83); + addPerformer(performers, 73, 73, 80, 83); + addPerformer(performers, 73, 80, 80, 83); + addPerformer(performers, 73, 127, 80, 83); + addPerformer(performers, 127, 127, 80, 83); + + + testDirectorCombinations( + performers.toArray( + new ModelPerformer[performers.size()]) + ); + + // Test reversed values + performers.clear(); + addPerformer(performers, 50, 30, 80, 83); + addPerformer(performers, 30, 30, 50, 30); + addPerformer(performers, 37, 30, 50, 30); + testDirector( + performers.toArray( + new ModelPerformer[performers.size()]) + ); + + // Test out-of-range values + performers.clear(); + addPerformer(performers, -20, 6, 0, 127); + addPerformer(performers, 0, 300, 0, 300); + addPerformer(performers, -2, -8, -5, -9); + + testDirector( + performers.toArray( + new ModelPerformer[performers.size()]) + ); + + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/sound/midi/Gervill/SoftChannel/ProgramAndBankChange.java Mon Sep 13 15:34:24 2010 +0400 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @summary Test SoftChannel program and bank change */ + +import java.io.IOException; + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProgramAndBankChange { + + private static SimpleInstrument generateTestInstrument(Patch patch) { + ModelOscillator osc = new ModelOscillator() { + public float getAttenuation() { + return 0; + } + + public int getChannels() { + return 1; + } + + public ModelOscillatorStream open(float samplerate) { + return new ModelOscillatorStream() { + public void close() throws IOException { + } + + public void noteOff(int velocity) { + } + + public void noteOn(MidiChannel channel, VoiceStatus voice, + int noteNumber, int velocity) { + } + + public int read(float[][] buffer, int offset, int len) + throws IOException { + return len; + } + + public void setPitch(float ipitch) { + } + }; + } + }; + ModelPerformer performer = new ModelPerformer(); + performer.getOscillators().add(osc); + SimpleInstrument testinstrument = new SimpleInstrument(); + testinstrument.setPatch(patch); + testinstrument.add(performer); + return testinstrument; + } + + private static void assertTrue(boolean value) throws Exception { + if (!value) + throw new RuntimeException("assertTrue fails!"); + } + + private static void testProgramAndBank(SoftSynthesizer soft, + AudioInputStream stream, Patch patch) throws Exception { + + int program = patch.getProgram(); + int bank = patch.getBank(); + + MidiChannel channel = soft.getChannels()[0]; + byte[] buff = new byte[2048]; + + channel.programChange(bank, program); + channel.noteOn(64, 64); + stream.read(buff, 0, buff.length); + + int foundprogram = -1; + int foundbank = -1; + VoiceStatus[] vstatus = soft.getVoiceStatus(); + for (int i = 0; i < vstatus.length; i++) { + if (vstatus[i].active) { + foundprogram = vstatus[i].program; + foundbank = vstatus[i].bank; + break; + } + } + + assertTrue(foundprogram == program); + assertTrue(foundbank == bank); + + channel.noteOn(64, 0); + stream.read(buff, 0, buff.length); + + channel = soft.getChannels()[1]; + // Send MSB Bank + channel.controlChange(0x00, bank / 128); + // Send LSB Bank + channel.controlChange(0x20, bank % 128); + // Send Program Change + channel.programChange(program); + channel.noteOn(64, 64); + stream.read(buff, 0, buff.length); + + foundprogram = -1; + foundbank = -1; + vstatus = soft.getVoiceStatus(); + for (int i = 0; i < vstatus.length; i++) { + if (vstatus[i].active) { + foundprogram = vstatus[i].program; + foundbank = vstatus[i].bank; + break; + } + } + assertTrue(foundprogram == program); + assertTrue(foundbank == bank); + channel.noteOn(64, 0); + stream.read(buff, 0, buff.length); + } + + public static void main(String[] args) throws Exception { + SoftSynthesizer soft = new SoftSynthesizer(); + AudioInputStream stream = soft.openStream(null, null); + soft.unloadAllInstruments(soft.getDefaultSoundbank()); + + soft.loadInstrument(generateTestInstrument(new Patch(0, 0))); + soft.loadInstrument(generateTestInstrument(new Patch(7, 0))); + soft.loadInstrument(generateTestInstrument(new Patch(20, 10))); + soft.loadInstrument(generateTestInstrument(new Patch(3678, 15))); + soft.loadInstrument(generateTestInstrument(new Patch(4678, 15))); + + testProgramAndBank(soft, stream, new Patch(0, 0)); + testProgramAndBank(soft, stream, new Patch(7, 0)); + testProgramAndBank(soft, stream, new Patch(20, 10)); + testProgramAndBank(soft, stream, new Patch(3678, 15)); + testProgramAndBank(soft, stream, new Patch(4678, 15)); + + soft.close(); + } +}