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