1 /* 2 * Copyright (c) 2007, 2015, 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 SoftSynthesizer simple note rendering in many settings 26 @modules java.desktop/com.sun.media.sound 27 */ 28 29 import java.io.File; 30 import java.io.FileInputStream; 31 import java.io.BufferedInputStream; 32 import java.io.FileInputStream; 33 import java.io.IOException; 34 import java.io.InputStream; 35 import java.io.OutputStream; 36 import java.util.HashMap; 37 import java.util.Map; 38 39 import javax.sound.sampled.*; 40 import javax.sound.midi.*; 41 42 import com.sun.media.sound.*; 43 44 public class TestRender1 { 45 46 public static double send(Sequence seq, Receiver recv) { 47 float divtype = seq.getDivisionType(); 48 assert (seq.getDivisionType() == Sequence.PPQ); 49 Track[] tracks = seq.getTracks(); 50 int[] trackspos = new int[tracks.length]; 51 int mpq = 60000000 / 100; 52 int seqres = seq.getResolution(); 53 long lasttick = 0; 54 long curtime = 0; 55 while (true) { 56 MidiEvent selevent = null; 57 int seltrack = -1; 58 for (int i = 0; i < tracks.length; i++) { 59 int trackpos = trackspos[i]; 60 Track track = tracks[i]; 61 if (trackpos < track.size()) { 62 MidiEvent event = track.get(trackpos); 63 if (selevent == null 64 || event.getTick() < selevent.getTick()) { 65 selevent = event; 66 seltrack = i; 67 } 68 } 69 } 70 if (seltrack == -1) 71 break; 72 trackspos[seltrack]++; 73 long tick = selevent.getTick(); 74 if (divtype == Sequence.PPQ) 75 curtime += ((tick - lasttick) * mpq) / seqres; 76 else 77 curtime = (long) ((tick * 1000000.0 * divtype) / seqres); 78 lasttick = tick; 79 MidiMessage msg = selevent.getMessage(); 80 if (msg instanceof MetaMessage) { 81 if (divtype == Sequence.PPQ) 82 if (((MetaMessage) msg).getType() == 0x51) { 83 byte[] data = ((MetaMessage) msg).getData(); 84 mpq = ((data[0] & 0xff) << 16) 85 | ((data[1] & 0xff) << 8) | (data[2] & 0xff); 86 } 87 } else { 88 if (recv != null) 89 recv.send(msg, curtime); 90 } 91 } 92 93 return curtime / 1000000.0; 94 } 95 96 public static void test(AudioFormat format, Map<String, Object> info) 97 throws Exception { 98 OutputStream nullout = new OutputStream() { 99 public void write(int b) throws IOException { 100 } 101 102 public void write(byte[] b, int off, int len) throws IOException { 103 } 104 105 public void write(byte[] b) throws IOException { 106 } 107 }; 108 render(nullout, format, info); 109 } 110 111 public static void render(OutputStream os, AudioFormat format, 112 Map<String, Object> info) throws Exception { 113 AudioSynthesizer synth = (AudioSynthesizer) new SoftSynthesizer(); 114 AudioInputStream stream = synth.openStream(format, info); 115 Receiver recv = synth.getReceiver(); 116 Soundbank defsbk = synth.getDefaultSoundbank(); 117 if (defsbk != null) 118 synth.unloadAllInstruments(defsbk); 119 synth.loadAllInstruments(soundbank); 120 121 double totalTime = 5; 122 send(sequence, recv); 123 124 long len = (long) (stream.getFormat().getFrameRate() * (totalTime + 4)); 125 stream = new AudioInputStream(stream, stream.getFormat(), len); 126 127 long t = System.currentTimeMillis(); 128 AudioSystem.write(stream, AudioFileFormat.Type.WAVE, os); 129 t = System.currentTimeMillis() - t; 130 stream.close(); 131 } 132 133 134 static Soundbank soundbank; 135 136 static Sequence sequence; 137 138 public static InputStream getInputStream(String filename) throws IOException 139 { 140 File file = new File(System.getProperty("test.src", "."), filename); 141 FileInputStream fis = new FileInputStream(file); 142 return new BufferedInputStream(fis); 143 } 144 145 public static void main(String[] args) throws Exception { 146 147 InputStream sb = getInputStream("ding.sf2"); 148 soundbank = MidiSystem.getSoundbank(sb); 149 sb.close(); 150 151 InputStream si = getInputStream("expresso.mid"); 152 sequence = MidiSystem.getSequence(si); 153 si.close(); 154 155 AudioFormat format; 156 Map<String, Object> info = new HashMap<String, Object>(); 157 { 158 format = new AudioFormat(22050, 16, 2, true, false); 159 test(format, info); 160 format = new AudioFormat(44100, 16, 2, true, false); 161 test(format, info); 162 } 163 { 164 format = new AudioFormat(44100, 8, 2, true, false); 165 test(format, info); 166 format = new AudioFormat(44100, 16, 2, true, false); 167 test(format, info); 168 format = new AudioFormat(44100, 24, 2, true, false); 169 test(format, info); 170 } 171 { 172 format = new AudioFormat(44100, 16, 1, true, false); 173 test(format, info); 174 format = new AudioFormat(44100, 16, 2, true, false); 175 test(format, info); 176 } 177 { 178 format = new AudioFormat(44100, 16, 2, true, false); 179 180 info.clear(); 181 info.put("control rate", 100f); 182 test(format, info); 183 info.clear(); 184 info.put("control rate", 147f); 185 test(format, info); 186 187 } 188 { 189 format = new AudioFormat(44100, 16, 2, true, false); 190 191 info.clear(); 192 info.put("interpolation", "point"); 193 test(format, info); 194 info.clear(); 195 info.put("interpolation", "linear"); 196 test(format, info); 197 info.clear(); 198 info.put("interpolation", "cubic"); 199 test(format, info); 200 } 201 { 202 format = new AudioFormat(44100, 16, 2, true, false); 203 info.clear(); 204 info.put("max polyphony", 4); 205 test(format, info); 206 info.clear(); 207 info.put("max polyphony", 16); 208 test(format, info); 209 info.clear(); 210 211 } 212 213 } 214 }