mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-21 19:08:31 +00:00
6943053: Gervill: failures on invalid ranges and 14-bit banks
ModelStandardIndexedDirector fails on invalid ranges. Program changes with 14-bit banks where handled incorectly as 7-bit banks. Reviewed-by: amenkov
This commit is contained in:
parent
0ffd8f54e0
commit
efedb2236a
@ -57,8 +57,7 @@ public class ModelStandardIndexedDirector implements ModelDirector {
|
||||
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 @@ public class ModelStandardIndexedDirector implements ModelDirector {
|
||||
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 @@ public class ModelStandardIndexedDirector implements ModelDirector {
|
||||
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)
|
||||
|
||||
@ -1264,7 +1264,7 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
|
||||
}
|
||||
|
||||
public void programChange(int bank, int program) {
|
||||
bank = restrict7Bit(bank);
|
||||
bank = restrict14Bit(bank);
|
||||
program = restrict7Bit(program);
|
||||
synchronized (control_mutex) {
|
||||
mainmixer.activity();
|
||||
|
||||
@ -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()])
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user