# HG changeset patch # User Mark Wielaard # Date 1209586148 -7200 # Node ID bcba163568acd2e76dfebdd86d356f9ed143828d # Parent 1b845dd20b86a51366f96c574049d8a4744e3dea Integrate Gervill. 2008-04-30 Mark Wielaard * Makefile.am (ICEDTEA_PATCHES): Add patches/icedtea-gervill.patch. * Makefile.in: Regenerated. * patches/icedtea-gervill.patch: New patch. * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/*: New Gervill files. diff -r 1b845dd20b86 -r bcba163568ac ChangeLog --- a/ChangeLog Tue Apr 29 12:47:53 2008 -0400 +++ b/ChangeLog Wed Apr 30 22:09:08 2008 +0200 @@ -1,3 +1,11 @@ +2008-04-30 Mark Wielaard + + * Makefile.am (ICEDTEA_PATCHES): Add patches/icedtea-gervill.patch. + * Makefile.in: Regenerated. + * patches/icedtea-gervill.patch: New patch. + * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/*: + New Gervill files. + 2008-04-29 Lillian Angel * Makefile.am diff -r 1b845dd20b86 -r bcba163568ac Makefile.am --- a/Makefile.am Tue Apr 29 12:47:53 2008 -0400 +++ b/Makefile.am Wed Apr 30 22:09:08 2008 +0200 @@ -309,6 +309,7 @@ patches/icedtea-color-createcontext.patch \ patches/icedtea-color-profiles.patch \ patches/icedtea-fonts.patch \ + patches/icedtea-gervill.patch \ $(GCC_PATCH) \ $(DISTRIBUTION_PATCHES) diff -r 1b845dd20b86 -r bcba163568ac Makefile.in --- a/Makefile.in Tue Apr 29 12:47:53 2008 -0400 +++ b/Makefile.in Wed Apr 30 22:09:08 2008 +0200 @@ -412,8 +412,8 @@ patches/icedtea-LCMS-setTagData.patch \ patches/icedtea-color-createcontext.patch \ patches/icedtea-color-profiles.patch \ - patches/icedtea-fonts.patch $(GCC_PATCH) \ - $(DISTRIBUTION_PATCHES) $(am__append_7) + patches/icedtea-fonts.patch patches/icedtea-gervill.patch \ + $(GCC_PATCH) $(DISTRIBUTION_PATCHES) $(am__append_7) # Patch OpenJDK for plug replacements and ecj. ICEDTEA_ECJ_PATCH = patches/icedtea-ecj.patch diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,141 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Soundbank; +import javax.sound.midi.spi.SoundbankReader; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; + +/** + * Soundbank reader that uses audio files as soundbanks. + * + * @version %I%, %E% + * @author Karl Helgason + * + */ +public class AudioFileSoundbankReader extends SoundbankReader { + + public Soundbank getSoundbank(URL url) throws InvalidMidiDataException, + IOException { + try { + AudioInputStream ais = AudioSystem.getAudioInputStream(url); + Soundbank sbk = getSoundbank(ais); + ais.close(); + return sbk; + } catch (UnsupportedAudioFileException e) { + return null; + } catch (IOException e) { + return null; + } + } + + public Soundbank getSoundbank(InputStream stream) + throws InvalidMidiDataException, IOException { + + stream.mark(512); + try { + AudioInputStream ais = AudioSystem.getAudioInputStream(stream); + Soundbank sbk = getSoundbank(ais); + if (sbk != null) + return sbk; + } catch (UnsupportedAudioFileException e) { + } catch (IOException e) { + } + stream.reset(); + return null; + } + + public Soundbank getSoundbank(AudioInputStream ais) + throws InvalidMidiDataException, IOException { + + try { + try { + byte[] buffer; + if (ais.getFrameLength() == -1) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buff = new byte[1024 - (1024 % ais.getFormat().getFrameSize())]; + int ret; + while ((ret = ais.read(buff)) != -1) + baos.write(buff, 0, ret); + ais.close(); + buffer = baos.toByteArray(); + } else { + buffer = new byte[(int) (ais.getFrameLength() * ais + .getFormat().getFrameSize())]; + ais.read(buffer); + } + ModelByteBufferWavetable osc = new ModelByteBufferWavetable( + new ModelByteBuffer(buffer), ais.getFormat(), -4800); + ModelPerformer performer = new ModelPerformer(); + ; + performer.getOscillators().add(osc); + + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.add(performer); + sbk.addInstrument(ins); + return sbk; + } finally { + } + } catch (Exception e) { + return null; + } + } + + public Soundbank getSoundbank(File file) throws InvalidMidiDataException, + IOException { + + try { + AudioInputStream ais = AudioSystem.getAudioInputStream(file); + ais.close(); + ModelByteBufferWavetable osc = new ModelByteBufferWavetable( + new ModelByteBuffer(file, 0, file.length()), -4800); + ModelPerformer performer = new ModelPerformer(); + performer.getOscillators().add(osc); + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.add(performer); + sbk.addInstrument(ins); + return sbk; + } catch (UnsupportedAudioFileException e1) { + return null; + } catch (IOException e) { + return null; + } + + } + + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,670 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +/** + * This class is used to convert between 8,16,24,32 bit signed/unsigned + * big/litle endian fixed/floating point byte buffers and float buffers. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public abstract class AudioFloatConverter { + + public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT"); + + /*************************************************************************** + * + * 32 bit float, little/big-endian + * + **************************************************************************/ + + // PCM 32 bit float, little-endian + private static class AudioFloatConversion32L extends AudioFloatConverter { + ByteBuffer bytebuffer = null; + + FloatBuffer floatbuffer = null; + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int in_len = out_len * 4; + if (bytebuffer == null || bytebuffer.capacity() < in_len) { + bytebuffer = ByteBuffer.allocate(in_len).order( + ByteOrder.LITTLE_ENDIAN); + floatbuffer = bytebuffer.asFloatBuffer(); + } + bytebuffer.position(0); + floatbuffer.position(0); + bytebuffer.put(in_buff, in_offset, in_len); + floatbuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int out_len = in_len * 4; + if (bytebuffer == null || bytebuffer.capacity() < out_len) { + bytebuffer = ByteBuffer.allocate(out_len).order( + ByteOrder.LITTLE_ENDIAN); + floatbuffer = bytebuffer.asFloatBuffer(); + } + floatbuffer.position(0); + bytebuffer.position(0); + floatbuffer.put(in_buff, in_offset, in_len); + bytebuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + } + + // PCM 32 bit float, big-endian + private static class AudioFloatConversion32B extends AudioFloatConverter { + ByteBuffer bytebuffer = null; + + FloatBuffer floatbuffer = null; + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int in_len = out_len * 4; + if (bytebuffer == null || bytebuffer.capacity() < in_len) { + bytebuffer = ByteBuffer.allocate(in_len).order( + ByteOrder.BIG_ENDIAN); + floatbuffer = bytebuffer.asFloatBuffer(); + } + bytebuffer.position(0); + floatbuffer.position(0); + bytebuffer.put(in_buff, in_offset, in_len); + floatbuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int out_len = in_len * 4; + if (bytebuffer == null || bytebuffer.capacity() < out_len) { + bytebuffer = ByteBuffer.allocate(out_len).order( + ByteOrder.BIG_ENDIAN); + floatbuffer = bytebuffer.asFloatBuffer(); + } + floatbuffer.position(0); + bytebuffer.position(0); + floatbuffer.put(in_buff, in_offset, in_len); + bytebuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + } + + /*************************************************************************** + * + * 8 bit signed/unsigned + * + **************************************************************************/ + + // PCM 8 bit, signed + private static class AudioFloatConversion8S extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) + out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) + out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f); + return out_buff; + } + } + + // PCM 8 bit, unsigned + private static class AudioFloatConversion8U extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) + out_buff[ox++] = ((in_buff[ix++]&0xFF) - 127) * (1.0f / 127.0f); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) + out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f); + return out_buff; + } + } + + /*************************************************************************** + * + * 16 bit signed/unsigned, little/big-endian + * + **************************************************************************/ + + // PCM 16 bit, signed, little-endian + private static class AudioFloatConversion16SL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + /* + int ox = out_offset; + for (int i = 0; i < out_len; i++) + out_buff[ox++] = ((short) ((in_buff[ix++] & 0xFF) | (in_buff[ix++] << 8))) + * (1.0f / 32767.0f); + */ + int len = out_offset + out_len; + for (int ox = out_offset; ox < len; ox++) + out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) | (in_buff[ix++] << 8))) + * (1.0f / 32767.0f); + + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ox = out_offset; + int len = in_offset + in_len; + for (int ix = in_offset; ix < len; ix++) { + int x = (int) (in_buff[ix] * 32767.0); + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + } + return out_buff; + } + } + + // PCM 16 bit, signed, big-endian + private static class AudioFloatConversion16SB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) + out_buff[ox++] = ((short) ((in_buff[ix++] << 8) | (in_buff[ix++] & 0xFF))) + * (1.0f / 32767.0f); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 32767.0); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + // PCM 16 bit, unsigned, little-endian + private static class AudioFloatConversion16UL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) + out_buff[ox++] = (( ((in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8))) - 32767) + * (1.0f / 32767.0f); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = 32767 + (int) (in_buff[ix++] * 32767.0); + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + } + return out_buff; + } + } + + // PCM 16 bit, unsigned, big-endian + private static class AudioFloatConversion16UB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) + out_buff[ox++] = (( (((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF))) - 32767) + * (1.0f / 32767.0f); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = 32767 + (int) (in_buff[ix++] * 32767.0); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + /*************************************************************************** + * + * 24 bit signed/unsigned, little/big-endian + * + **************************************************************************/ + + // PCM 24 bit, signed, little-endian + private static class AudioFloatConversion24SL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) + | ((in_buff[ix++] & 0xFF) << 16); + if (x > 8388607) + x -= 16777216; + out_buff[ox++] = x * (1.0f / 8388607.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 8388607.0); + if (x < 0) + x += 16777216; + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + } + return out_buff; + } + } + + // PCM 24 bit, signed, big-endian + private static class AudioFloatConversion24SB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 8) + | (in_buff[ix++] & 0xFF); + if (x > 8388607) + x -= 16777216; + out_buff[ox++] = x * (1.0f / 8388607.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 8388607.0); + if (x < 0) + x += 16777216; + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + // PCM 24 bit, unsigned, little-endian + private static class AudioFloatConversion24UL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) + | ((in_buff[ix++] & 0xFF) << 16); + x -= 8388607; + out_buff[ox++] = x * (1.0f / 8388607.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 8388607.0); + x += 8388607; + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + } + return out_buff; + } + } + + // PCM 24 bit, unsigned, big-endian + private static class AudioFloatConversion24UB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 8) + | (in_buff[ix++] & 0xFF); + x -= 8388607; + out_buff[ox++] = x * (1.0f / 8388607.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 8388607.0); + x += 8388607; + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + /*************************************************************************** + * + * 32 bit signed/unsigned, little/big-endian + * + **************************************************************************/ + + // PCM 32 bit, signed, little-endian + private static class AudioFloatConversion32SL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) + | ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 24); + out_buff[ox++] = x * (1.0f / 2147483647.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 2147483647.0); + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 24); + } + return out_buff; + } + } + + // PCM 32 bit, signed, big-endian + private static class AudioFloatConversion32SB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 24) + | ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 8) + | (in_buff[ix++] & 0xFF); + out_buff[ox++] = x * (1.0f / 2147483647.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 2147483647.0); + out_buff[ox++] = (byte) (x >>> 24); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + // PCM 32 bit, unsigned, little-endian + private static class AudioFloatConversion32UL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) + | ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 24); + x -= 2147483647; + out_buff[ox++] = x * (1.0f / 2147483647.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 2147483647.0); + x += 2147483647; + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 24); + } + return out_buff; + } + } + + // PCM 32 bit, unsigned, big-endian + private static class AudioFloatConversion32UB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 24) + | ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 8) + | (in_buff[ix++] & 0xFF); + x -= 2147483647; + out_buff[ox++] = x * (1.0f / 2147483647.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 2147483647.0); + x += 2147483647; + out_buff[ox++] = (byte) (x >>> 24); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + public static AudioFloatConverter getConverter(AudioFormat format) { + AudioFloatConverter conv = null; + if (format.getFrameSize() != (format.getSampleSizeInBits() / 8) + * format.getChannels()) + return null; + if (format.getEncoding().equals(Encoding.PCM_SIGNED)) { + if (format.isBigEndian()) { + if (format.getSampleSizeInBits() == 8) + conv = new AudioFloatConversion8S(); + else if (format.getSampleSizeInBits() > 8 + && format.getSampleSizeInBits() <= 16) + conv = new AudioFloatConversion16SB(); + else if (format.getSampleSizeInBits() > 16 + && format.getSampleSizeInBits() <= 24) + conv = new AudioFloatConversion24SB(); + else if (format.getSampleSizeInBits() > 24 + && format.getSampleSizeInBits() <= 32) + conv = new AudioFloatConversion32SB(); + } else { + if (format.getSampleSizeInBits() == 8) + conv = new AudioFloatConversion8S(); + else if (format.getSampleSizeInBits() > 8 + & format.getSampleSizeInBits() <= 16) + conv = new AudioFloatConversion16SL(); + else if (format.getSampleSizeInBits() > 16 + && format.getSampleSizeInBits() <= 24) + conv = new AudioFloatConversion24SL(); + else if (format.getSampleSizeInBits() > 24 + && format.getSampleSizeInBits() <= 32) + conv = new AudioFloatConversion32SL(); + } + } else if (format.getEncoding().equals(Encoding.PCM_UNSIGNED)) { + if (format.isBigEndian()) { + if (format.getSampleSizeInBits() == 8) + conv = new AudioFloatConversion8U(); + else if (format.getSampleSizeInBits() > 8 + && format.getSampleSizeInBits() <= 16) + conv = new AudioFloatConversion16UB(); + else if (format.getSampleSizeInBits() > 16 + && format.getSampleSizeInBits() <= 24) + conv = new AudioFloatConversion24UB(); + else if (format.getSampleSizeInBits() > 24 + && format.getSampleSizeInBits() <= 32) + conv = new AudioFloatConversion32UB(); + } else { + if (format.getSampleSizeInBits() == 8) + conv = new AudioFloatConversion8U(); + else if (format.getSampleSizeInBits() > 8 + && format.getSampleSizeInBits() <= 16) + conv = new AudioFloatConversion16UL(); + else if (format.getSampleSizeInBits() > 16 + && format.getSampleSizeInBits() <= 24) + conv = new AudioFloatConversion24UL(); + else if (format.getSampleSizeInBits() > 24 + && format.getSampleSizeInBits() <= 32) + conv = new AudioFloatConversion32UL(); + } + } else if (format.getEncoding().equals(PCM_FLOAT)) { + if (format.getSampleSizeInBits() == 32) { + if (format.isBigEndian()) + conv = new AudioFloatConversion32B(); + else + conv = new AudioFloatConversion32L(); + } + } + + if (conv != null) + conv.format = format; + return conv; + } + + private AudioFormat format; + + public AudioFormat getFormat() { + return format; + } + + public abstract float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len); + + public float[] toFloatArray(byte[] in_buff, float[] out_buff, + int out_offset, int out_len) { + return toFloatArray(in_buff, 0, out_buff, out_offset, out_len); + } + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_len) { + return toFloatArray(in_buff, in_offset, out_buff, 0, out_len); + } + + public float[] toFloatArray(byte[] in_buff, float[] out_buff, int out_len) { + return toFloatArray(in_buff, 0, out_buff, 0, out_len); + } + + public float[] toFloatArray(byte[] in_buff, float[] out_buff) { + return toFloatArray(in_buff, 0, out_buff, 0, out_buff.length); + } + + public abstract byte[] toByteArray(float[] in_buff, int in_offset, + int in_len, byte[] out_buff, int out_offset); + + public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff, + int out_offset) { + return toByteArray(in_buff, 0, in_len, out_buff, out_offset); + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff) { + return toByteArray(in_buff, in_offset, in_len, out_buff, 0); + } + + public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff) { + return toByteArray(in_buff, 0, in_len, out_buff, 0); + } + + public byte[] toByteArray(float[] in_buff, byte[] out_buff) { + return toByteArray(in_buff, 0, in_buff.length, out_buff, 0); + } +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatInputStream.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,297 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; + +/** + * This class is used to create AudioFloatInputStream from AudioInputStream and + * byte buffers. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public abstract class AudioFloatInputStream { + + private static class BytaArrayAudioFloatInputStream extends + AudioFloatInputStream { + + private int pos = 0; + + private int markpos = 0; + + private AudioFloatConverter converter; + + private AudioFormat format; + + private byte[] buffer; + + private int buffer_offset; + + private int buffer_len; + + private int framesize_pc; + + public BytaArrayAudioFloatInputStream(AudioFloatConverter converter, + byte[] buffer, int offset, int len) { + this.converter = converter; + this.format = converter.getFormat(); + this.buffer = buffer; + this.buffer_offset = offset; + framesize_pc = format.getFrameSize() / format.getChannels(); + this.buffer_len = len / framesize_pc; + + } + + public AudioFormat getFormat() { + return format; + } + + public long getFrameLength() { + return buffer_len;// / format.getFrameSize(); + } + + public int read(float[] b, int off, int len) throws IOException { + if (b == null) + throw new NullPointerException(); + if (off < 0 || len < 0 || len > b.length - off) + throw new IndexOutOfBoundsException(); + if (pos >= buffer_len) + return -1; + if (len == 0) + return 0; + if (pos + len > buffer_len) + len = buffer_len - pos; + converter.toFloatArray(buffer, buffer_offset + pos * framesize_pc, + b, off, len); + pos += len; + return len; + } + + public long skip(long len) throws IOException { + if (pos >= buffer_len) + return -1; + if (len <= 0) + return 0; + if (pos + len > buffer_len) + len = buffer_len - pos; + pos += len; + return len; + } + + public int available() throws IOException { + return buffer_len - pos; + } + + public void close() throws IOException { + } + + public void mark(int readlimit) { + markpos = pos; + } + + public boolean markSupported() { + return true; + } + + public void reset() throws IOException { + pos = markpos; + } + + } + + private static class DirectAudioFloatInputStream extends + AudioFloatInputStream { + private AudioInputStream stream; + + private AudioFloatConverter converter; + + private int framesize_pc; // framesize / channels + + private byte[] buffer; + + public DirectAudioFloatInputStream(AudioInputStream stream) { + converter = AudioFloatConverter.getConverter(stream + .getFormat()); + if (converter == null) { + AudioFormat format = stream.getFormat(); + AudioFormat newformat; + + AudioFormat[] formats = AudioSystem.getTargetFormats( + AudioFormat.Encoding.PCM_SIGNED, format); + if (formats.length != 0) { + newformat = formats[0]; + } else { + + float samplerate = format.getSampleRate(); + int samplesizeinbits = format.getSampleSizeInBits(); + int framesize = format.getFrameSize(); + float framerate = format.getFrameRate(); + samplesizeinbits = 16; + framesize = format.getChannels() * (samplesizeinbits / 8); + framerate = samplerate; + + newformat = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, samplerate, + samplesizeinbits, format.getChannels(), framesize, + framerate, false); + } + + stream = AudioSystem.getAudioInputStream(newformat, stream); + converter = AudioFloatConverter.getConverter(stream + .getFormat()); + } + framesize_pc = stream.getFormat().getFrameSize() + / stream.getFormat().getChannels(); + this.stream = stream; + } + + public AudioFormat getFormat() { + return stream.getFormat(); + } + + public long getFrameLength() { + return stream.getFrameLength(); + } + + public int read(float[] b, int off, int len) throws IOException { + int b_len = len * framesize_pc; + if (buffer == null || buffer.length < b_len) + buffer = new byte[b_len]; + int ret = stream.read(buffer, 0, b_len); + if (ret == -1) + return -1; + converter.toFloatArray(buffer, b, off, ret / framesize_pc); + return ret / framesize_pc; + } + + public long skip(long len) throws IOException { + long b_len = len * framesize_pc; + long ret = stream.skip(b_len); + if (ret == -1) + return -1; + return ret / framesize_pc; + } + + public int available() throws IOException { + return stream.available() / framesize_pc; + } + + public void close() throws IOException { + stream.close(); + } + + public void mark(int readlimit) { + stream.mark(readlimit * framesize_pc); + } + + public boolean markSupported() { + return stream.markSupported(); + } + + public void reset() throws IOException { + stream.reset(); + } + + } + + public static AudioFloatInputStream getInputStream(URL url) + throws UnsupportedAudioFileException, IOException { + return new DirectAudioFloatInputStream(AudioSystem + .getAudioInputStream(url)); + } + + public static AudioFloatInputStream getInputStream(File file) + throws UnsupportedAudioFileException, IOException { + return new DirectAudioFloatInputStream(AudioSystem + .getAudioInputStream(file)); + } + + public static AudioFloatInputStream getInputStream(InputStream stream) + throws UnsupportedAudioFileException, IOException { + return new DirectAudioFloatInputStream(AudioSystem + .getAudioInputStream(stream)); + } + + public static AudioFloatInputStream getInputStream( + AudioInputStream stream) { + return new DirectAudioFloatInputStream(stream); + } + + public static AudioFloatInputStream getInputStream(AudioFormat format, + byte[] buffer, int offset, int len) { + AudioFloatConverter converter = AudioFloatConverter + .getConverter(format); + if (converter != null) + return new BytaArrayAudioFloatInputStream(converter, buffer, + offset, len); + + InputStream stream = new ByteArrayInputStream(buffer, offset, len); + AudioInputStream astream = new AudioInputStream(stream, format, format + .getFrameSize() == -1 ? -1 : (len / format.getFrameSize())); + return getInputStream(astream); + } + + public abstract AudioFormat getFormat(); + + public abstract long getFrameLength(); + + public abstract int read(float[] b, int off, int len) throws IOException; + + public int read(float[] b) throws IOException { + return read(b, 0, b.length); + } + + public float read() throws IOException { + float[] b = new float[1]; + int ret = read(b, 0, 1); + if (ret == -1 || ret == 0) + return 0; + return b[0]; + } + + public abstract long skip(long len) throws IOException; + + public abstract int available() throws IOException; + + public abstract void close() throws IOException; + + public abstract void mark(int readlimit); + + public abstract boolean markSupported(); + + public abstract void reset() throws IOException; +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,132 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.Map; + +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Synthesizer; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.SourceDataLine; + +/** + * + * AudioSynthesizer is a Synthesizer + * which renders it's output audio into SourceDataLine + * or AudioInputStream. + * + * @see MidiSystem#getSynthesizer + * @see Synthesizer + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface AudioSynthesizer extends Synthesizer { + + /** + * Obtains the current format (encoding, sample rate, number of channels, + * etc.) of the synthesizer audio data. + * + *

If the synthesizer is not open and has never been opened, it returns + * the default format. + * + * @return current audio data format + * @see AudioFormat + */ + public AudioFormat getFormat(); + + /** + * Gets information about the possible properties for this synthesizer. + * + * @param info a proposed list of tag/value pairs that will be sent on open + * @return an array of AudioSynthesizerPropertyInfo objects describing + * possible properties. This array may be an empty array if + * no properties are required. + */ + public AudioSynthesizerPropertyInfo[] getPropertyInfo(Map info); + + /** + * Opens the synthesizer and starts rendering audio into SourceDataLine. + * + *

An application opening a synthesizer explicitly with this call + * has to close the synthesizer by calling {@link #close}. This is + * necessary to release system resources and allow applications to + * exit cleanly. + * + *

+ * Note that some synthesizers, once closed, cannot be reopened. Attempts + * to reopen such a synthesizer will always result in a MidiUnavailableException. + * + * @param line which AudioSynthesizer writes output audio into. + * If line is null, then line from system default mixer is used. + * + * @param info is a Map object containing properties + * for additional configuration supported by synthesizer. + * If info is null then default settings are used. + * + * @throws MidiUnavailableException thrown if the synthesizer cannot be + * opened due to resource restrictions. + * @throws SecurityException thrown if the synthesizer cannot be + * opened due to security restrictions. + * + * @see #close + * @see #isOpen + */ + public void open(SourceDataLine line, Map info) throws MidiUnavailableException; + + /** + * Opens the synthesizer and renders audio into returned + * AudioInputStream. + * + *

An application opening a synthesizer explicitly with this call + * has to close the synthesizer by calling {@link #close}. This is + * necessary to release system resources and allow applications to + * exit cleanly. + * + *

+ * Note that some synthesizers, once closed, cannot be reopened. Attempts + * to reopen such a synthesizer will always result in a MidiUnavailableException. + * + * @param targetFormat specifies the AudioFormat + * used in returned AudioInputStream. + * + * @param info is a Map object containing properties + * for additional configuration supported by synthesizer. + * If info is null then default settings are used. + * + * @throws MidiUnavailableException thrown if the synthesizer cannot be + * opened due to resource restrictions. + * @throws SecurityException thrown if the synthesizer cannot be + * opened due to security restrictions. + * + * @see #close + * @see #isOpen + */ + public AudioInputStream openStream(AudioFormat targetFormat, Map info) throws MidiUnavailableException; + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + *

Information about property used in + * opening AudioSynthesizer. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class AudioSynthesizerPropertyInfo { + + /** + * Constructs a AudioSynthesizerPropertyInfo object with a given + * name and value. The description and choices + * are intialized to null. + * + * @param name the name of the property + * @param value the current value or class used for values. + * + */ + public AudioSynthesizerPropertyInfo(String name, Object value) { + this.name = name; + this.value = value; + if(value instanceof Class) + valueClass = (Class)value; + else + if(value != null) valueClass = value.getClass(); + } + + /** + * The name of the property. + */ + public String name; + + /** + * A brief description of the property, which may be null. + */ + public String description = null; + + /** + * The value field specifies the current value of + * the property. + */ + public Object value = null; + + /** + * The valueClass field specifies class + * used in value field. + */ + public Class valueClass = null; + + /** + * An array of possible values if the value for the field + * AudioSynthesizerPropertyInfo.value may be selected + * from a particular set of values; otherwise null. + */ + public Object[] choices = null; + +} \ No newline at end of file diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,179 @@ + - Fix: Default tempo in SoftMidiFileReader was supposed to be 500000 mpq or 120 bpm + - Fix: Change type of info variable in SoftSynthesize into MidiDevice.Info + - Fix: Fix instanceof check of p1 variable in ModelInstrumentComparator + - Fix: Remove redundant constant variable in ModelByteBufferWaveTable + +Version 0.9 + - Fix: JTreg SoftSynthesizer\ImplicitOpenClose.java + did not test correctly. + - Fix: SoftSynthesizer.isSoundbankSupported + now only returns false if + there is any instrument which is not supported. + - Fix: SoftSynthesizer.remapInstrument + did not work correctly. + - Fix: SoftSynthesizer.loadInstrument + SoftSynthesizer.loadInstruments + SoftSynthesizer.loadAllInstruments + SoftSynthesizer.unloadInstrument + SoftSynthesizer.unloadInstruments + SoftSynthesizer.unloadAllInstruments + SoftSynthesizer.getAvailableInstruments + SoftSynthesizer.getLoadedInstruments + now throws IllegalArgumentException + if instrument is not supported + and false if instrument can't be loaded + for some other reason. + - Fix: SoftSynthesizer.getReceivers() + SoftSynthesizer.getMicrosecondPosition() + SoftSynthesizer.getVoiceStatus() + SoftSynthesizer.getChannels() + SoftMidiAudioFileReader.getAudioInputStream(Sequence seq) + now no longer throw IllegalStateException. + - Fix: SoftSynthesizer.getChannels() and + SoftSynthesizer.getVoiceStatus() + now no longer return internal array. + - Fix: CPU spiking caused by denormal floats in SoftReverb. + - Fix: Calling getReceiver before opening the synthesizer results in NullPointerException. + JTreg test added: SoftSynthesizer/GetReceiver2 + - Fix: Removed checksum check on + BULK TUNING DUMP (NON-REAL-TIME) + Because MIDI Tuning Spec was ambigous about + how to calculate the checksum + and different programs tested calculated + different checksum. + JTreg test SoftTuning/Load1 fixed. + +VERSION 0.8 + - Fix: Active Sense Messages where incorrectly handled. + JTreg test: SoftReceiver/Send_ActiveSense.java + - Fix: SoftAudioPusher doesn't longer try to prevent blocking. + - Added: SoftJitterCorrector added to fix jitter on long buffers. + +VERSION 0.7 + - Fix: General MIDI mode, + and voice_allocation_mode flag wasn't reseted on open/close cycle. + - Fix: Added support for implicit open/close + (as described in http://java.sun.com/javase/6/docs/api/javax/sound/midi/MidiDevice.html) + (JTreg test also added) + This done by implementing com.sun.media.sound.ReferenceCountingDevice interface. + - Fix: SoftReceiver.close doesn't throw exception if closed. + (now behaves like SoftSynthesizer.close) + - Fix: Close variable wasn't accessed in Thread safe way in: + SoftReceiver, SoftSynthesizer. + - Fix: Hang in SoftSynthesizer.close. + SoftAudioPusher must not be closed synchronized against control_mutex + this may result in synchronized conflict between pusher and caller thread. + - Fix: Bad handling of mono output in SoftVoice.processAudioLogic, + this error was found running the new SoftSynthesizer/TestRender1 jtreg test. + - Added: ModelDirector to support conditional layers/performers. + - Added: ReleaseTrigger property to ModelPerformer. + - Added: ModelAbstractOscillator to simplify creation custom oscillators. + - Added: ModelChannelMixer to support for example non-voice oriented instruments. + - Added: Support for more than 16 midi channels. + - Added: JARSoundBankReader. + - Change default latency from 400 to 200 mec. + +VERSION 0.6 + - Added RIFFWriter(OutputStream) constructor. + - Added save(OutputStream out) to DLSSoundbank and SF2Soundbank. + - Renamed : isAddDefaultConnections to setDefaultConnectionsEnabled + - Renamed : getAddDefaultConnections to isDefaultConnectionsEnabled + - Created JTreg Unit Tests + - Fixed error found in Unit Tests + * AudioFloatConversion8U.toFloatArray, did not convert correctly + * SoftSynthesizer.remapInstrument did not work + The error was in ModelMappedInstrument + * SoftSynthesizer.getMaxReceivers did not return -1 + * SoftTuning.checksumOK calculated incorrect checksums. + * RIFFReader.close didn't work + * AudioFloatInputStream.getFrameLength returned incorrect value. + * ModelByteBuffer.writeTo didn't work when ModelByteBuffer uses file pointer. + * ModelIdentifier.equals, didn't compare the variable "instance". + * SimpleSoundbank.removeResource did not remove resource. + * RIFFWriter.close never closed underlying stream. + +VERSION 0.5 + - New instruments in Emergency Soundbank: + * Acoustic Grand Piano + * Bright Acoustic Piano + * Honky-tonk Piano + * Guitar + * Distortion Guitar + * Trumpet + * Trombone + * Brass Section + * Horn + * Sax + * Oboe + * Bassoon + * Clarinet + * Flute + * Timpani + * Melodic Toms + * Reverse Cymbal + * Orch Hit + - Faster Linear Interpolation + with no float to int casting. + Thanks to Bruno Schoedlbauer for + pointing out that float to int casting + can be costly. + - LargeSoundBankReader removed, + Loading soundbank in large mode using urls removed. + - Soundbank aren't loaded into memory + until loadInstrument/loadAllInstrument + is called in SoftSynthesizer. + This enable loading only single instrument + from soundbank collection into memory. + - New "large mode" property added to SoftSynthesizer. + - "getInstrument" method in DLS/SF2/SimpleSoundbank + now returns ordered list by program,bank,percussion. + - Fix AccessControlException in "SoftSynthesizer.getDefaultSoundbank", + which occurred when using SoftSynthesizer in Applets. + +VERSION 0.4 + - Fixed ArrayOutOfBoundsException in SoftAbstractResmpler. + - Fixed NullPointerException in SoundFont.save(File). + Saving global zone for layers resulted in NullPointerException. + - Fixed PATSoundbankReader.getInputStream + so it doesn't throw InvalidFormatException. + This prevented use of MidiSystem.getSoundBank(InputStream). + - Fix: Delay wasn't implemented in AHDSR envelopes. + - Loading soundbank in large mode supported using + MidiSystem.getSoundBank(URL) + Where url is on the form: + file:/C:/soundbank.sf2?largemode=true + - Reverb,Chorus,AGC can be turned on/off. + - MIDI files can be opened as audio streams + thru javax.sound.sampled.spi.AudioFileReader. + - Optimizations, rendering is up to 50 percent faster. + - Emergency SoundBank. + +VERSION 0.3 + - SoftSynthesizer doesn't implement mixer interface anymore, + instead the method "openStream" has been added. + - New AudioSynthesizer interface. + - SoftSynthesizer.getVoiceStatus() is now thread-safe. + - SoftAudioFeeder renamed to SoftAudioPusher + and made more generic. + - Support for multi-receiver in SoftSynthesizer. + - More cleanup in SoftSynthesizer. + - Fixed loops in large soundbanks. + - WaveFloatFileReader added to META-INF/services + +VERSION 0.2 + - Large format support see: LargeSoundbankReader + - Fix soundfont modulator mapping + direction mapping was wrong + - Fix handling of unsigned 16 bit streams + - Improved GUS patch support + - Add support for ping-pong/bi-directional and reverse loops + +VERSION 0.1 + - Downloadable Sound Level 2.2. + - SoundFont 2.04 (24 bit) + - Gravis Ultrasound-compatible patches + - Use Audio files (AIFF, AU and WAV) as SoundBanks + - General Midi Level 2 + - MIDI Tuning Standard + - Drumkits can be used on any channel + - Sinc interpolation with anti-aliasing \ No newline at end of file diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSInfo.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,115 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * This class is used to store information + * to describe soundbanks, instruments and samples. + * It is stored inside a "INFO" List Chunk inside DLS files. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class DLSInfo { + + /** + * (INAM) Title or subject. + */ + public String name = "untitled"; + /** + * (ICRD) Date of creation, the format is: YYYY-MM-DD. + * For example 2007-01-01 for 1. januar of year 2007. + */ + public String creationDate = null; + /** + * (IENG) Name of engineer who created the object. + */ + public String engineers = null; + /** + * (IPRD) Name of the product which the object is + * intended for. + */ + public String product = null; + /** + * (ICOP) Copyright information. + */ + public String copyright = null; + /** + * (ICMT) General comments. Doesn't contain newline characters. + */ + public String comments = null; + /** + * (ISFT) Name of software package used to create the file. + */ + public String tools = null; + /** + * (IARL) Where content is archived. + */ + public String archival_location = null; + /** + * (IART) Artists of original content. + */ + public String artist = null; + /** + * (ICMS) Names of persons or orginizations who + * commissioned the file. + */ + public String commissioned = null; + /** + * (IGNR) Genre of the work. + * Example: jazz, classical, rock, etc. + */ + public String genre = null; + /** + * (IKEY) List of keyword that describe the content. + * Examples: FX, bird, piano, etc. + */ + public String keywords = null; + /** + * (IMED) Describes original medium of the data, + * for example: record, CD, etc. + */ + public String medium = null; + /** + * (ISBJ) Description of the content. + */ + public String subject = null; + /** + * (ISRC) Name of person or orginization who supplied + * orginal material for the file. + */ + public String source = null; + /** + * (ISRF) Source media for sample data is from. + * For example: CD, TV, etc. + */ + public String source_form = null; + /** + * (ITCH) Technician who sample the file/object. + */ + public String technician = null; + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSInstrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSInstrument.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,384 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.Patch; + +/** + * This class is used to store information + * to describe instrument. I contains list of regions and modulators. + * It is stored inside a "ins " List Chunk inside DLS files. + * In the DLS documentation a modulator is called articulator. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class DLSInstrument extends ModelInstrument { + + protected int preset = 0; + protected int bank = 0; + + protected boolean druminstrument = false; + protected byte[] guid = null; + + protected DLSInfo info = new DLSInfo(); + + protected List regions = new ArrayList(); + protected List modulators = new ArrayList(); + + public DLSInstrument() { + super(null, null, null, null); + } + + public DLSInstrument(DLSSoundbank soundbank) { + super(soundbank, null, null, null); + } + + public DLSInfo getInfo() { + return info; + } + + public String getName() { + return info.name; + } + + public void setName(String name) + { + info.name = name; + } + + public ModelPatch getPatch() { + return new ModelPatch(bank, preset, druminstrument); + } + + public void setPatch(Patch patch) + { + if(patch instanceof ModelPatch && ((ModelPatch)patch).isPercussion()) + { + druminstrument = true; + bank = patch.getBank(); + preset = patch.getProgram(); + } + else + { + druminstrument = false; + bank = patch.getBank(); + preset = patch.getProgram(); + } + } + + public Object getData() { + return null; + } + + public List getRegions() { + return regions; + } + + public List getModulators() { + return modulators; + } + + public String toString() + { + if(druminstrument) + return "Drumkit: " + info.name + " bank #" + bank + " preset #" + preset; + else + return "Instrument: " + info.name + " bank #" + bank + " preset #" + preset; + } + + private ModelIdentifier convertToModelDest(int dest) + { + if(dest == DLSModulator.CONN_DST_NONE) return null; + if(dest == DLSModulator.CONN_DST_GAIN) return ModelDestination.DESTINATION_GAIN; + if(dest == DLSModulator.CONN_DST_PITCH) return ModelDestination.DESTINATION_PITCH; + if(dest == DLSModulator.CONN_DST_PAN) return ModelDestination.DESTINATION_PAN; + + if(dest == DLSModulator.CONN_DST_LFO_FREQUENCY) return ModelDestination.DESTINATION_LFO1_FREQ; + if(dest == DLSModulator.CONN_DST_LFO_STARTDELAY) return ModelDestination.DESTINATION_LFO1_DELAY; + + if(dest == DLSModulator.CONN_DST_EG1_ATTACKTIME) return ModelDestination.DESTINATION_EG1_ATTACK; + if(dest == DLSModulator.CONN_DST_EG1_DECAYTIME) return ModelDestination.DESTINATION_EG1_DECAY; + if(dest == DLSModulator.CONN_DST_EG1_RELEASETIME) return ModelDestination.DESTINATION_EG1_RELEASE; + if(dest == DLSModulator.CONN_DST_EG1_SUSTAINLEVEL) return ModelDestination.DESTINATION_EG1_SUSTAIN; + + if(dest == DLSModulator.CONN_DST_EG2_ATTACKTIME) return ModelDestination.DESTINATION_EG2_ATTACK; + if(dest == DLSModulator.CONN_DST_EG2_DECAYTIME) return ModelDestination.DESTINATION_EG2_DECAY; + if(dest == DLSModulator.CONN_DST_EG2_RELEASETIME) return ModelDestination.DESTINATION_EG2_RELEASE; + if(dest == DLSModulator.CONN_DST_EG2_SUSTAINLEVEL) return ModelDestination.DESTINATION_EG2_SUSTAIN; + + // DLS2 Destinations + if(dest == DLSModulator.CONN_DST_KEYNUMBER) return ModelDestination.DESTINATION_KEYNUMBER; + + if(dest == DLSModulator.CONN_DST_CHORUS) return ModelDestination.DESTINATION_CHORUS; + if(dest == DLSModulator.CONN_DST_REVERB) return ModelDestination.DESTINATION_REVERB; + + if(dest == DLSModulator.CONN_DST_VIB_FREQUENCY) return ModelDestination.DESTINATION_LFO2_FREQ; + if(dest == DLSModulator.CONN_DST_VIB_STARTDELAY) return ModelDestination.DESTINATION_LFO2_DELAY; + + if(dest == DLSModulator.CONN_DST_EG1_DELAYTIME) return ModelDestination.DESTINATION_EG1_DELAY; + if(dest == DLSModulator.CONN_DST_EG1_HOLDTIME) return ModelDestination.DESTINATION_EG1_HOLD; + if(dest == DLSModulator.CONN_DST_EG1_SHUTDOWNTIME) return ModelDestination.DESTINATION_EG1_SHUTDOWN; + + if(dest == DLSModulator.CONN_DST_EG2_DELAYTIME) return ModelDestination.DESTINATION_EG2_DELAY; + if(dest == DLSModulator.CONN_DST_EG2_HOLDTIME) return ModelDestination.DESTINATION_EG2_HOLD; + + if(dest == DLSModulator.CONN_DST_FILTER_CUTOFF) return ModelDestination.DESTINATION_FILTER_FREQ; + if(dest == DLSModulator.CONN_DST_FILTER_Q) return ModelDestination.DESTINATION_FILTER_Q; + + return null; + } + + private ModelIdentifier convertToModelSrc(int src) + { + if(src == DLSModulator.CONN_SRC_NONE) return null; + + if(src == DLSModulator.CONN_SRC_LFO) return ModelSource.SOURCE_LFO1; + if(src == DLSModulator.CONN_SRC_KEYONVELOCITY) return ModelSource.SOURCE_NOTEON_VELOCITY; + if(src == DLSModulator.CONN_SRC_KEYNUMBER) return ModelSource.SOURCE_NOTEON_KEYNUMBER; + if(src == DLSModulator.CONN_SRC_EG1) return ModelSource.SOURCE_EG1; + if(src == DLSModulator.CONN_SRC_EG2) return ModelSource.SOURCE_EG2; + if(src == DLSModulator.CONN_SRC_PITCHWHEEL) return ModelSource.SOURCE_MIDI_PITCH; + if(src == DLSModulator.CONN_SRC_CC1) return new ModelIdentifier("midi_cc","1",0); + if(src == DLSModulator.CONN_SRC_CC7) return new ModelIdentifier("midi_cc","7",0); + if(src == DLSModulator.CONN_SRC_CC10) return new ModelIdentifier("midi_cc","10",0); + if(src == DLSModulator.CONN_SRC_CC11) return new ModelIdentifier("midi_cc","11",0); + if(src == DLSModulator.CONN_SRC_RPN0) return new ModelIdentifier("midi_rpn","0",0); + if(src == DLSModulator.CONN_SRC_RPN1) return new ModelIdentifier("midi_rpn","1",0); + + if(src == DLSModulator.CONN_SRC_POLYPRESSURE) return ModelSource.SOURCE_MIDI_POLY_PRESSURE; + if(src == DLSModulator.CONN_SRC_CHANNELPRESSURE) return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; + if(src == DLSModulator.CONN_SRC_VIBRATO) return ModelSource.SOURCE_LFO2; + if(src == DLSModulator.CONN_SRC_MONOPRESSURE) return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; + + if(src == DLSModulator.CONN_SRC_CC91) return new ModelIdentifier("midi_cc","91",0); + if(src == DLSModulator.CONN_SRC_CC93) return new ModelIdentifier("midi_cc","93",0); + + return null; + } + + private ModelConnectionBlock convertToModel(DLSModulator mod) + { + ModelIdentifier source = convertToModelSrc(mod.getSource()); + ModelIdentifier control = convertToModelSrc(mod.getControl()); + ModelIdentifier destination_id = convertToModelDest(mod.getDestination()); + + int scale = mod.getScale(); + double f_scale; + if(scale == Integer.MIN_VALUE) + f_scale = Double.NEGATIVE_INFINITY; + else + f_scale = scale / 65536.0; + + if(destination_id != null) + { + ModelSource src = null; + ModelSource ctrl = null; + ModelConnectionBlock block = new ModelConnectionBlock(); + if(control != null) + { + ModelSource s = new ModelSource(); + if(control == ModelSource.SOURCE_MIDI_PITCH) + ((ModelStandardTransform)s.getTransform()).setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + else if(control == ModelSource.SOURCE_LFO1 || control == ModelSource.SOURCE_LFO2) + ((ModelStandardTransform)s.getTransform()).setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + s.setIdentifier(control); + block.addSource(s); + ctrl = s; + } + if(source != null) + { + ModelSource s = new ModelSource(); + if(source == ModelSource.SOURCE_MIDI_PITCH) + ((ModelStandardTransform)s.getTransform()).setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + else if(source == ModelSource.SOURCE_LFO1 || source == ModelSource.SOURCE_LFO2) + ((ModelStandardTransform)s.getTransform()).setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + s.setIdentifier(source); + block.addSource(s); + src = s; + } + ModelDestination destination = new ModelDestination(); + destination.setIdentifier(destination_id); + block.setDestination(destination); + + if(mod.getVersion() == 1) + { + //if(mod.getTransform() == DLSModulator.CONN_TRN_CONCAVE) + // ((ModelStandardTransform)destination.getTransform()).setTransform(ModelStandardTransform.TRANSFORM_CONCAVE); + if(mod.getTransform() == DLSModulator.CONN_TRN_CONCAVE) + { + if(src != null) + { + ((ModelStandardTransform)src.getTransform()).setTransform(ModelStandardTransform.TRANSFORM_CONCAVE); + ((ModelStandardTransform)src.getTransform()).setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + } + if(ctrl != null) + { + ((ModelStandardTransform)ctrl.getTransform()).setTransform(ModelStandardTransform.TRANSFORM_CONCAVE); + ((ModelStandardTransform)ctrl.getTransform()).setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + } + } + + } + else if(mod.getVersion() == 2) + { + int transform = mod.getTransform(); + int src_transform_invert = (transform >> 15) & 1; + int src_transform_bipolar = (transform >> 14) & 1; + int src_transform = (transform >> 10) & 8; + int ctr_transform_invert = (transform >> 9) & 1; + int ctr_transform_bipolar = (transform >> 8) & 1; + int ctr_transform = (transform >> 4) & 8; + + + if(src != null) + { + int trans = ModelStandardTransform.TRANSFORM_LINEAR; + if(src_transform == DLSModulator.CONN_TRN_SWITCH) trans = ModelStandardTransform.TRANSFORM_SWITCH; + if(src_transform == DLSModulator.CONN_TRN_CONCAVE) trans = ModelStandardTransform.TRANSFORM_CONCAVE; + if(src_transform == DLSModulator.CONN_TRN_CONVEX) trans = ModelStandardTransform.TRANSFORM_CONVEX; + ((ModelStandardTransform)src.getTransform()).setTransform(trans); + ((ModelStandardTransform)src.getTransform()).setPolarity(src_transform_bipolar==1); + ((ModelStandardTransform)src.getTransform()).setDirection(src_transform_invert==1); + + } + + if(ctrl != null) + { + int trans = ModelStandardTransform.TRANSFORM_LINEAR; + if(ctr_transform == DLSModulator.CONN_TRN_SWITCH) trans = ModelStandardTransform.TRANSFORM_SWITCH; + if(ctr_transform == DLSModulator.CONN_TRN_CONCAVE) trans = ModelStandardTransform.TRANSFORM_CONCAVE; + if(ctr_transform == DLSModulator.CONN_TRN_CONVEX) trans = ModelStandardTransform.TRANSFORM_CONVEX; + ((ModelStandardTransform)ctrl.getTransform()).setTransform(trans); + ((ModelStandardTransform)ctrl.getTransform()).setPolarity(ctr_transform_bipolar==1); + ((ModelStandardTransform)ctrl.getTransform()).setDirection(ctr_transform_invert==1); + } + + /* + No output transforms are defined the DLS Level 2 + + int out_transform = transform % 8; + + int trans = ModelStandardTransform.TRANSFORM_LINEAR; + if(out_transform == DLSModulator.CONN_TRN_SWITCH) trans = ModelStandardTransform.TRANSFORM_SWITCH; + if(out_transform == DLSModulator.CONN_TRN_CONCAVE) trans = ModelStandardTransform.TRANSFORM_CONCAVE; + if(out_transform == DLSModulator.CONN_TRN_CONVEX) trans = ModelStandardTransform.TRANSFORM_CONVEX; + if(ctrl != null) ((ModelStandardTransform)destination.getTransform()).setTransform(trans); + */ + + + } + + block.setScale(f_scale); + + return block; + } + + return null; + } + + public ModelPerformer[] getPerformers() + { + List performers = new ArrayList(); + + Map modmap = new HashMap (); + for(DLSModulator mod : getModulators()) + modmap.put(mod.getSource()+"x"+mod.getControl()+"="+mod.getDestination(), mod); + + Map insmodmap = new HashMap (); + + for(DLSRegion zone : regions) + { + ModelPerformer performer = new ModelPerformer(); + performer.setName(zone.getSample().getName()); + performer.setSelfNonExclusive((zone.getFusoptions() & DLSRegion.OPTION_SELFNONEXCLUSIVE) != 0); + performer.setExclusiveClass(zone.getExclusiveClass()); + performer.setKeyFrom(zone.getKeyfrom()); + performer.setKeyTo(zone.getKeyto()); + performer.setVelFrom(zone.getVelfrom()); + performer.setVelTo(zone.getVelto()); + + insmodmap.clear(); + insmodmap.putAll(modmap); + for(DLSModulator mod : zone.getModulators()) + insmodmap.put(mod.getSource()+"x"+mod.getControl()+"="+mod.getDestination(), mod); + + List blocks = performer.getConnectionBlocks(); + for(DLSModulator mod : insmodmap.values()) + { + ModelConnectionBlock p = convertToModel(mod); + if(p != null) blocks.add(p); + } + + + DLSSample sample = zone.getSample(); + DLSSampleOptions sampleopt = zone.getSampleoptions(); + if(sampleopt == null) sampleopt = sample.getSampleoptions(); + + ModelByteBuffer buff = sample.getDataBuffer(); + + float pitchcorrection = (-sampleopt.unitynote*100) + sampleopt.finetune; + + ModelByteBufferWavetable osc = new ModelByteBufferWavetable(buff, sample.getFormat(),pitchcorrection); + osc.setAttenuation(osc.getAttenuation() / 65536f); + if(sampleopt.getLoops().size() != 0) + { + DLSSampleLoop loop = sampleopt.getLoops().get(0); + osc.setLoopStart((int)loop.getStart()); + osc.setLoopLength((int)loop.getLength()); + if(loop.getType() == DLSSampleLoop.LOOP_TYPE_FORWARD) + osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); + if(loop.getType() == DLSSampleLoop.LOOP_TYPE_RELEASE) + osc.setLoopType(ModelWavetable.LOOP_TYPE_RELEASE); + else + osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); + } + + performer.getConnectionBlocks().add(new ModelConnectionBlock(SoftFilter.FILTERTYPE_LP12,new ModelDestination(new ModelIdentifier("filter", "type", 1)))); + + performer.getOscillators().add(osc); + + performers.add(performer); + + } + + return performers.toArray(new ModelPerformer[performers.size()]); + } + + public byte[] getGuid() { + return guid; + } + + public void setGuid(byte[] guid) { + this.guid = guid; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSModulator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSModulator.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,284 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * This class is used to store modulator/artiuclation data. + * A modulator connects one synthesizer source to + * a destination. For example a note on velocity + * can be mapped to the gain of the synthesized voice. + * It is stored as a "art1" or "art2" chunk inside DLS files. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class DLSModulator { + + // DLS1 Destinations + public static final int CONN_DST_NONE = 0x000; // 0 + public static final int CONN_DST_GAIN = 0x001; // cB + public static final int CONN_DST_PITCH = 0x003; // 3 cent + public static final int CONN_DST_PAN = 0x004; // 4 0.1% + + public static final int CONN_DST_LFO_FREQUENCY = 0x104; // 260 cent (default 5 Hz) + public static final int CONN_DST_LFO_STARTDELAY = 0x105; // 261 timecent + + public static final int CONN_DST_EG1_ATTACKTIME = 0x206; // 518 timecent + public static final int CONN_DST_EG1_DECAYTIME = 0x207; // 519 timecent + public static final int CONN_DST_EG1_RELEASETIME = 0x209; // 521 timecent + public static final int CONN_DST_EG1_SUSTAINLEVEL = 0x20A; // 522 0.1% + + public static final int CONN_DST_EG2_ATTACKTIME = 0x30A; // 778 timecent + public static final int CONN_DST_EG2_DECAYTIME = 0x30B; // 779 timecent + public static final int CONN_DST_EG2_RELEASETIME = 0x30D; // 781 timecent + public static final int CONN_DST_EG2_SUSTAINLEVEL = 0x30E; // 782 0.1% + + // DLS2 Destinations + public static final int CONN_DST_KEYNUMBER = 0x005; + + public static final int CONN_DST_LEFT = 0x010; // 0.1% + public static final int CONN_DST_RIGHT = 0x011; // 0.1% + public static final int CONN_DST_CENTER = 0x012; // 0.1% + public static final int CONN_DST_LEFTREAR = 0x013; // 0.1% + public static final int CONN_DST_RIGHTREAR = 0x014; // 0.1% + public static final int CONN_DST_LFE_CHANNEL = 0x015; // 0.1% + public static final int CONN_DST_CHORUS = 0x080; // 0.1% + public static final int CONN_DST_REVERB = 0x081; // 0.1% + + public static final int CONN_DST_VIB_FREQUENCY = 0x114; // cent + public static final int CONN_DST_VIB_STARTDELAY = 0x115; // dB + + public static final int CONN_DST_EG1_DELAYTIME = 0x20B; // timecent + public static final int CONN_DST_EG1_HOLDTIME = 0x20C; // timecent + public static final int CONN_DST_EG1_SHUTDOWNTIME = 0x20D; // timecent + + public static final int CONN_DST_EG2_DELAYTIME = 0x30F; // timecent + public static final int CONN_DST_EG2_HOLDTIME = 0x310; // timecent + + public static final int CONN_DST_FILTER_CUTOFF = 0x500; // cent + public static final int CONN_DST_FILTER_Q = 0x501; // dB + + // DLS1 Sources + public static final int CONN_SRC_NONE = 0x000; // 1 + public static final int CONN_SRC_LFO = 0x001; // linear (sine wave) + public static final int CONN_SRC_KEYONVELOCITY = 0x002; // ?? db or velocity ?? + public static final int CONN_SRC_KEYNUMBER = 0x003; // ?? cent or keynumber ?? + public static final int CONN_SRC_EG1 = 0x004; // linear direct from eg + public static final int CONN_SRC_EG2 = 0x005; // linear direct from eg + public static final int CONN_SRC_PITCHWHEEL = 0x006; // linear -1..1 + + public static final int CONN_SRC_CC1 = 0x081; // linear 0..1 + public static final int CONN_SRC_CC7 = 0x087; // linear 0..1 + public static final int CONN_SRC_CC10 = 0x08A; // linear 0..1 + public static final int CONN_SRC_CC11 = 0x08B; // linear 0..1 + + public static final int CONN_SRC_RPN0 = 0x100; // ?? // Pitch Bend Range + public static final int CONN_SRC_RPN1 = 0x101; // ?? // Fine Tune + public static final int CONN_SRC_RPN2 = 0x102; // ?? // Course Tune + + // DLS2 Sources + public static final int CONN_SRC_POLYPRESSURE = 0x007; // linear 0..1 + public static final int CONN_SRC_CHANNELPRESSURE = 0x008; // linear 0..1 + public static final int CONN_SRC_VIBRATO = 0x009; // linear 0..1 + public static final int CONN_SRC_MONOPRESSURE = 0x00A; // linear 0..1 + + public static final int CONN_SRC_CC91 = 0x0DB; // linear 0..1 + public static final int CONN_SRC_CC93 = 0x0DD; // linear 0..1 + + + // DLS1 Transforms + public static final int CONN_TRN_NONE = 0x000; + public static final int CONN_TRN_CONCAVE = 0x001; + + // DLS2 Transforms + public static final int CONN_TRN_CONVEX = 0x002; + public static final int CONN_TRN_SWITCH = 0x003; + + + public static final int DST_FORMAT_CB = 1; + public static final int DST_FORMAT_CENT = 1; + public static final int DST_FORMAT_TIMECENT = 2; + public static final int DST_FORMAT_PERCENT = 3; + + protected int source; + protected int control; + protected int destination; + protected int transform; + protected int scale; + protected int version = 1; + + public int getControl() { + return control; + } + public void setControl(int control) { + this.control = control; + } + public static int getDestinationFormat(int destination) { + + if(destination == CONN_DST_GAIN) return DST_FORMAT_CB; + if(destination == CONN_DST_PITCH) return DST_FORMAT_CENT; + if(destination == CONN_DST_PAN) return DST_FORMAT_PERCENT; + + if(destination == CONN_DST_LFO_FREQUENCY) return DST_FORMAT_CENT; + if(destination == CONN_DST_LFO_STARTDELAY) return DST_FORMAT_TIMECENT; + + if(destination == CONN_DST_EG1_ATTACKTIME) return DST_FORMAT_TIMECENT; + if(destination == CONN_DST_EG1_DECAYTIME) return DST_FORMAT_TIMECENT; + if(destination == CONN_DST_EG1_RELEASETIME) return DST_FORMAT_TIMECENT; + if(destination == CONN_DST_EG1_SUSTAINLEVEL) return DST_FORMAT_PERCENT; + + if(destination == CONN_DST_EG2_ATTACKTIME) return DST_FORMAT_TIMECENT; + if(destination == CONN_DST_EG2_DECAYTIME) return DST_FORMAT_TIMECENT; + if(destination == CONN_DST_EG2_RELEASETIME) return DST_FORMAT_TIMECENT; + if(destination == CONN_DST_EG2_SUSTAINLEVEL) return DST_FORMAT_PERCENT; + + if(destination == CONN_DST_KEYNUMBER) return DST_FORMAT_CENT; // NOT SURE WITHOUT DLS 2 SPEC + if(destination == CONN_DST_LEFT) return DST_FORMAT_CB; + if(destination == CONN_DST_RIGHT) return DST_FORMAT_CB; + if(destination == CONN_DST_CENTER) return DST_FORMAT_CB; + if(destination == CONN_DST_LEFTREAR) return DST_FORMAT_CB; + if(destination == CONN_DST_RIGHTREAR) return DST_FORMAT_CB; + if(destination == CONN_DST_LFE_CHANNEL) return DST_FORMAT_CB; + if(destination == CONN_DST_CHORUS) return DST_FORMAT_PERCENT; + if(destination == CONN_DST_REVERB) return DST_FORMAT_PERCENT; + + if(destination == CONN_DST_VIB_FREQUENCY) return DST_FORMAT_CENT; + if(destination == CONN_DST_VIB_STARTDELAY) return DST_FORMAT_TIMECENT; + + if(destination == CONN_DST_EG1_DELAYTIME) return DST_FORMAT_TIMECENT; + if(destination == CONN_DST_EG1_HOLDTIME) return DST_FORMAT_TIMECENT; + if(destination == CONN_DST_EG1_SHUTDOWNTIME) return DST_FORMAT_TIMECENT; + + if(destination == CONN_DST_EG2_DELAYTIME) return DST_FORMAT_TIMECENT; + if(destination == CONN_DST_EG2_HOLDTIME) return DST_FORMAT_TIMECENT; + + if(destination == CONN_DST_FILTER_CUTOFF) return DST_FORMAT_CENT; + if(destination == CONN_DST_FILTER_Q) return DST_FORMAT_CB; + + return -1; + } + + public static String getDestinationName(int destination) { + + if(destination == CONN_DST_GAIN) return "gain"; + if(destination == CONN_DST_PITCH) return "pitch"; + if(destination == CONN_DST_PAN) return "pan"; + + if(destination == CONN_DST_LFO_FREQUENCY) return "lfo1.freq"; + if(destination == CONN_DST_LFO_STARTDELAY) return "lfo1.delay"; + + if(destination == CONN_DST_EG1_ATTACKTIME) return "eg1.attack"; + if(destination == CONN_DST_EG1_DECAYTIME) return "eg1.decay"; + if(destination == CONN_DST_EG1_RELEASETIME) return "eg1.release"; + if(destination == CONN_DST_EG1_SUSTAINLEVEL) return "eg1.sustain"; + + if(destination == CONN_DST_EG2_ATTACKTIME) return "eg2.attack"; + if(destination == CONN_DST_EG2_DECAYTIME) return "eg2.decay"; + if(destination == CONN_DST_EG2_RELEASETIME) return "eg2.release"; + if(destination == CONN_DST_EG2_SUSTAINLEVEL) return "eg2.sustain"; + + if(destination == CONN_DST_KEYNUMBER) return "keynumber"; + if(destination == CONN_DST_LEFT) return "left"; + if(destination == CONN_DST_RIGHT) return "right"; + if(destination == CONN_DST_CENTER) return "center"; + if(destination == CONN_DST_LEFTREAR) return "leftrear"; + if(destination == CONN_DST_RIGHTREAR) return "rightrear"; + if(destination == CONN_DST_LFE_CHANNEL) return "lfe_channel"; + if(destination == CONN_DST_CHORUS) return "chorus"; + if(destination == CONN_DST_REVERB) return "reverb"; + + if(destination == CONN_DST_VIB_FREQUENCY) return "vib.freq"; + if(destination == CONN_DST_VIB_STARTDELAY) return "vib.delay"; + + if(destination == CONN_DST_EG1_DELAYTIME) return "eg1.delay"; + if(destination == CONN_DST_EG1_HOLDTIME) return "eg1.hold"; + if(destination == CONN_DST_EG1_SHUTDOWNTIME) return "eg1.shutdown"; + + if(destination == CONN_DST_EG2_DELAYTIME) return "eg2.delay"; + if(destination == CONN_DST_EG2_HOLDTIME) return "eg.2hold"; + + if(destination == CONN_DST_FILTER_CUTOFF) return "filter.cutoff"; // NOT SURE WITHOUT DLS 2 SPEC + if(destination == CONN_DST_FILTER_Q) return "filter.q"; // NOT SURE WITHOUT DLS 2 SPEC + + return null; + } + + public static String getSourceName(int source) { + + if(source == CONN_SRC_NONE) return "none"; + if(source == CONN_SRC_LFO) return "lfo"; + if(source == CONN_SRC_KEYONVELOCITY) return "keyonvelocity"; + if(source == CONN_SRC_KEYNUMBER) return "keynumber"; + if(source == CONN_SRC_EG1) return "eg1"; + if(source == CONN_SRC_EG2) return "eg2"; + if(source == CONN_SRC_PITCHWHEEL) return "pitchweel"; + if(source == CONN_SRC_CC1) return "cc1"; + if(source == CONN_SRC_CC7) return "cc7"; + if(source == CONN_SRC_CC10) return "c10"; + if(source == CONN_SRC_CC11) return "cc11"; + + if(source == CONN_SRC_POLYPRESSURE) return "polypressure"; + if(source == CONN_SRC_CHANNELPRESSURE) return "channelpressure"; + if(source == CONN_SRC_VIBRATO) return "vibrato"; + if(source == CONN_SRC_MONOPRESSURE) return "monopressure"; + if(source == CONN_SRC_CC91) return "cc91"; + if(source == CONN_SRC_CC93) return "cc93"; + return null; + } + + + public int getDestination() { + return destination; + } + public void setDestination(int destination) { + this.destination = destination; + } + public int getScale() { + return scale; + } + public void setScale(int scale) { + this.scale = scale; + } + public int getSource() { + return source; + } + public void setSource(int source) { + this.source = source; + } + public int getVersion() { + return version; + } + public void setVersion(int version) { + this.version = version; + } + public int getTransform() { + return transform; + } + public void setTransform(int transform) { + this.transform = transform; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSRegion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSRegion.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,162 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * This class is used to store region parts for instrument. + * A region has a velocity and key range which it response to. + * And it has a list of modulators/articulators which + * is used how to synthesize a single voice. + * It is stored inside a "rgn " List Chunk inside DLS files. + * + * @version %I%, %E% + * @author Karl Helgason + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used for storing DLS regions. + * It is stored inside a "rgn " List Chunk inside DLS files. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class DLSRegion { + + public final static int OPTION_SELFNONEXCLUSIVE = 0x0001; + + protected List modulators = new ArrayList(); + + protected int keyfrom; + protected int keyto; + protected int velfrom; + protected int velto; + protected int options; + protected int exclusiveClass; + + protected int fusoptions; + protected int phasegroup; + protected long channel; + protected DLSSample sample = null; + protected DLSSampleOptions sampleoptions; + + public List getModulators() { + return modulators; + } + + public long getChannel() { + return channel; + } + + public void setChannel(long channel) { + this.channel = channel; + } + + public int getExclusiveClass() { + return exclusiveClass; + } + + public void setExclusiveClass(int exclusiveClass) { + this.exclusiveClass = exclusiveClass; + } + + public int getFusoptions() { + return fusoptions; + } + + public void setFusoptions(int fusoptions) { + this.fusoptions = fusoptions; + } + + public int getKeyfrom() { + return keyfrom; + } + + public void setKeyfrom(int keyfrom) { + this.keyfrom = keyfrom; + } + + public int getKeyto() { + return keyto; + } + + public void setKeyto(int keyto) { + this.keyto = keyto; + } + + public int getOptions() { + return options; + } + + public void setOptions(int options) { + this.options = options; + } + + public int getPhasegroup() { + return phasegroup; + } + + public void setPhasegroup(int phasegroup) { + this.phasegroup = phasegroup; + } + + public DLSSample getSample() { + return sample; + } + + public void setSample(DLSSample sample) { + this.sample = sample; + } + + public int getVelfrom() { + return velfrom; + } + + public void setVelfrom(int velfrom) { + this.velfrom = velfrom; + } + + public int getVelto() { + return velto; + } + + public void setVelto(int velto) { + this.velto = velto; + } + + public void setModulators(List modulators) { + this.modulators = modulators; + } + + public DLSSampleOptions getSampleoptions() { + return sampleoptions; + } + + public void setSampleoptions(DLSSampleOptions sampleOptions) { + this.sampleoptions = sampleOptions; + } +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSample.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSample.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,131 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.InputStream; + +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; + +/** + * This class is used to store the sample data itself. + * A sample is encoded as PCM audio stream + * and in DLS Level 1 files it is always a mono 8/16 bit stream. + * They are stored just like RIFF WAVE files are stored. + * It is stored inside a "wave" List Chunk inside DLS files. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class DLSSample extends SoundbankResource { + + protected byte[] guid = null; + + protected DLSInfo info = new DLSInfo(); + + protected DLSSampleOptions sampleoptions; + protected ModelByteBuffer data; + protected AudioFormat format; + + public DLSSample(Soundbank soundBank) { + super(soundBank, null, AudioInputStream.class); + } + + public DLSSample() { + super(null, null, AudioInputStream.class); + } + + public DLSInfo getInfo() { + return info; + } + + public Object getData() { + + AudioFormat format = getFormat(); + + InputStream is = data.getInputStream(); + if(is == null) return null; + return new AudioInputStream(is, format, data.capacity()); + } + + public ModelByteBuffer getDataBuffer() + { + return data; + } + + public AudioFormat getFormat() + { + return format; + } + + public void setFormat(AudioFormat format) { + this.format = format; + } + + public void setData(ModelByteBuffer data) { + this.data = data; + } + + public void setData(byte[] data) { + this.data = new ModelByteBuffer(data); + } + + public void setData(byte[] data, int offset, int length) { + this.data = new ModelByteBuffer(data, offset, length); + } + + public String getName() { + return info.name; + } + + public void setName(String name) { + info.name = name; + } + + public DLSSampleOptions getSampleoptions() { + return sampleoptions; + } + + public void setSampleoptions(DLSSampleOptions sampleOptions) { + this.sampleoptions = sampleOptions; + } + + public String toString() + { + return "Sample: " + info.name; + } + + public byte[] getGuid() { + return guid; + } + + public void setGuid(byte[] guid) { + this.guid = guid; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSampleLoop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSampleLoop.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * This class is used to store loop points inside DLSSampleOptions class. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class DLSSampleLoop { + + public final static int LOOP_TYPE_FORWARD = 0; + public final static int LOOP_TYPE_RELEASE = 1; + + protected long type; + protected long start; + protected long length; + + public long getLength() { + return length; + } + public void setLength(long length) { + this.length = length; + } + public long getStart() { + return start; + } + public void setStart(long start) { + this.start = start; + } + public long getType() { + return type; + } + public void setType(long type) { + this.type = type; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSampleOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSampleOptions.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * This class is used to store information + * how samples are rendered inside software synthesizer. + * It includes information on MIDI root note, loop points + * attenuation and tuning. + * It is stored inside a "wsmp" Chunk inside DLS files. + * + * @version %I%, %E% + * @author Karl Helgason + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class stores options how to + * playback sampled data like pitch/tuning, attenuation and loops. + * It is stored as a "wsmp" chunk inside DLS files. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class DLSSampleOptions { + + protected int unitynote; + protected short finetune; + protected int attenuation; + protected long options; + protected List loops = new ArrayList(); + + public int getAttenuation() { + return attenuation; + } + public void setAttenuation(int attenuation) { + this.attenuation = attenuation; + } + public short getFinetune() { + return finetune; + } + public void setFinetune(short finetune) { + this.finetune = finetune; + } + public List getLoops() { + return loops; + } + public long getOptions() { + return options; + } + public void setOptions(long options) { + this.options = options; + } + public int getUnitynote() { + return unitynote; + } + public void setUnitynote(int unitynote) { + this.unitynote = unitynote; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,1333 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * This class reads DLS (Downloadable Sounds) from files/url/streams. + * It can both read Level 1 and Level 2 DLS files. + * + * @version %I%, %E% + * @author Karl Helgason + */ +package com.sun.media.sound; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import javax.sound.midi.Instrument; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFormat.Encoding; + +/** + * A DLS Level 1 and Level 2 soundbank reader. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class DLSSoundbank implements Soundbank { + + static private class DLSID + { + long i1; + int s1; + int s2; + int x1; + int x2; + int x3; + int x4; + int x5; + int x6; + int x7; + int x8; + + private DLSID() + { + } + public DLSID(long i1, int s1, int s2, int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8) + { + this.i1 = i1; + this.s1 = s1; + this.s2 = s2; + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + this.x4 = x4; + this.x5 = x5; + this.x6 = x6; + this.x7 = x7; + this.x8 = x8; + } + + public static DLSID read(RIFFReader riff) throws IOException + { + DLSID d = new DLSID(); + d.i1 = riff.readUnsignedInt(); + d.s1 = riff.readUnsignedShort(); + d.s2 = riff.readUnsignedShort(); + d.x1 = riff.readByte(); + d.x2 = riff.readByte(); + d.x3 = riff.readByte(); + d.x4 = riff.readByte(); + d.x5 = riff.readByte(); + d.x6 = riff.readByte(); + d.x7 = riff.readByte(); + d.x8 = riff.readByte(); + return d; + } + + public boolean equals(Object obj) { + if(!(obj instanceof DLSID)) return false; + DLSID t = (DLSID)obj; + if(i1 != t.i1) return false; + if(s1 != t.s1) return false; + if(s2 != t.s2) return false; + if(x1 != t.x1) return false; + if(x2 != t.x2) return false; + if(x3 != t.x3) return false; + if(x4 != t.x4) return false; + if(x5 != t.x5) return false; + if(x6 != t.x6) return false; + if(x7 != t.x7) return false; + if(x8 != t.x8) return false; + return true; + } + + + } + + private static final int DLS_CDL_AND = 0x0001; /* X = X & Y */ + private static final int DLS_CDL_OR = 0x0002; /* X = X | Y */ + private static final int DLS_CDL_XOR = 0x0003; /* X = X ^ Y */ + private static final int DLS_CDL_ADD = 0x0004; /* X = X + Y */ + private static final int DLS_CDL_SUBTRACT = 0x0005; /* X = X - Y */ + private static final int DLS_CDL_MULTIPLY = 0x0006; /* X = X * Y */ + private static final int DLS_CDL_DIVIDE = 0x0007; /* X = X / Y */ + private static final int DLS_CDL_LOGICAL_AND = 0x0008; /* X = X && Y */ + private static final int DLS_CDL_LOGICAL_OR = 0x0009; /* X = X || Y */ + private static final int DLS_CDL_LT = 0x000A; /* X = (X < Y) */ + private static final int DLS_CDL_LE = 0x000B; /* X = (X <= Y) */ + private static final int DLS_CDL_GT = 0x000C; /* X = (X > Y) */ + private static final int DLS_CDL_GE = 0x000D; /* X = (X >= Y) */ + private static final int DLS_CDL_EQ = 0x000E; /* X = (X == Y) */ + private static final int DLS_CDL_NOT = 0x000F; /* X = !X */ + private static final int DLS_CDL_CONST = 0x0010; /* 32-bit constant */ + private static final int DLS_CDL_QUERY = 0x0011; /* 32-bit value returned from query */ + private static final int DLS_CDL_QUERYSUPPORTED = 0x0012; /* 32-bit value returned from query */ + + private static final DLSID DLSID_GMInHardware = new DLSID(0x178f2f24, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_GSInHardware = new DLSID(0x178f2f25, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_XGInHardware = new DLSID(0x178f2f26, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_SupportsDLS1 = new DLSID(0x178f2f27, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_SupportsDLS2 = new DLSID(0xf14599e5, 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6); + private static final DLSID DLSID_SampleMemorySize = new DLSID(0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_ManufacturersID = new DLSID(0xb03e1181, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); + private static final DLSID DLSID_ProductID = new DLSID(0xb03e1182, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); + private static final DLSID DLSID_SamplePlaybackRate = new DLSID(0x2a91f713, 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); + + private long major = -1; + private long minor = -1; + + private DLSInfo info = new DLSInfo(); + + private List instruments = new ArrayList(); + private List samples = new ArrayList(); + + private boolean largeFormat = false; + private File sampleFile; + + public DLSSoundbank() + { + } + + public DLSSoundbank(URL url) throws IOException { + + InputStream is = url.openStream(); + try + { + readSoundbank(is); + } + finally + { + is.close(); + } + } + + public DLSSoundbank(File file) throws IOException { + largeFormat = true; + sampleFile = file; + InputStream is = new FileInputStream(file); + try + { + readSoundbank(is); + } + finally + { + is.close(); + } + } + + public DLSSoundbank(InputStream inputstream) throws IOException { + readSoundbank(inputstream); + } + + private void readSoundbank(InputStream inputstream) throws IOException { + + RIFFReader riff = new RIFFReader(inputstream); + if (!riff.getFormat().equals("RIFF")) + throw new RIFFInvalidFormatException("Input stream is not a valid RIFF stream!"); + if (!riff.getType().equals("DLS ")) + throw new RIFFInvalidFormatException("Input stream is not a valid DLS soundbank!"); + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if (chunk.getType().equals("INFO")) + readInfoChunk(chunk); + if (chunk.getType().equals("lins")) + readLinsChunk(chunk); + if (chunk.getType().equals("wvpl")) + readWvplChunk(chunk); + } + else + { + if (chunk.getFormat().equals("cdl ")) + { + if(!readCdlChunk(chunk)) + throw new RIFFInvalidFormatException("DLS file isn't supported!"); + } + if (chunk.getFormat().equals("colh")) { + // - skipped because we will load the entire bank into memory + // long instrumentcount = chunk.readUnsignedInt(); + // System.out.println("instrumentcount = "+ instrumentcount); + } + if (chunk.getFormat().equals("ptbl")) { + // Pool Table Chunk + // - skipped because we will load the entire bank into memory + } + if (chunk.getFormat().equals("vers")) { + major = chunk.readUnsignedInt(); + minor = chunk.readUnsignedInt(); + } + } + } + + for(Map.Entry entry : temp_rgnassign.entrySet()) + { + entry.getKey().sample = samples.get((int)entry.getValue().longValue()); + } + + temp_rgnassign = null; + } + + + + private boolean cdlIsQuerySupported(DLSID uuid) + { + if(uuid.equals(DLSID_GMInHardware)) return true; + if(uuid.equals(DLSID_GSInHardware)) return true; + if(uuid.equals(DLSID_XGInHardware)) return true; + if(uuid.equals(DLSID_SupportsDLS1)) return true; + if(uuid.equals(DLSID_SupportsDLS2)) return true; + if(uuid.equals(DLSID_SampleMemorySize)) return true; + if(uuid.equals(DLSID_ManufacturersID)) return true; + if(uuid.equals(DLSID_ProductID)) return true; + if(uuid.equals(DLSID_SamplePlaybackRate)) return true; + return false; + } + private long cdlQuery(DLSID uuid) + { + if(uuid.equals(DLSID_GMInHardware)) return 1; + if(uuid.equals(DLSID_GSInHardware)) return 0; + if(uuid.equals(DLSID_XGInHardware)) return 0; + if(uuid.equals(DLSID_SupportsDLS1)) return 1; + if(uuid.equals(DLSID_SupportsDLS2)) return 1; + if(uuid.equals(DLSID_SampleMemorySize)) return Runtime.getRuntime().totalMemory(); + if(uuid.equals(DLSID_ManufacturersID)) return 0; + if(uuid.equals(DLSID_ProductID)) return 0; + if(uuid.equals(DLSID_SamplePlaybackRate)) return 44100; + return 0; + } + + + // Reading cdl-ck Chunk + // "cdl " chunk can only appear inside : DLS,lart,lar2,rgn,rgn2 + private boolean readCdlChunk(RIFFReader riff) throws IOException { + + DLSID uuid; + long x; + long y; + Stack stack = new Stack(); + + while(riff.available() != 0) + { + int opcode = riff.readUnsignedShort(); + switch (opcode) { + case DLS_CDL_AND: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( ((x!=0) & (y!=0)) ?1:0)); + break; + case DLS_CDL_OR: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( ((x!=0) | (y!=0)) ?1:0)); + break; + case DLS_CDL_XOR: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( ((x!=0) ^ (y!=0)) ?1:0)); + break; + case DLS_CDL_ADD: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( x+y )); + break; + case DLS_CDL_SUBTRACT: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( x-y )); + break; + case DLS_CDL_MULTIPLY: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( x*y )); + break; + case DLS_CDL_DIVIDE: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( x/y )); + break; + case DLS_CDL_LOGICAL_AND: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( ((x!=0) & (y!=0)) ?1:0)); + break; + case DLS_CDL_LOGICAL_OR: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( ((x!=0) | (y!=0)) ?1:0)); + break; + case DLS_CDL_LT: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( (x < y) ?1:0)); + break; + case DLS_CDL_LE: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( (x <= y) ?1:0)); + break; + case DLS_CDL_GT: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( (x > y) ?1:0)); + break; + case DLS_CDL_GE: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( (x >= y) ?1:0)); + break; + case DLS_CDL_EQ: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long( (x == y) ?1:0)); + break; + case DLS_CDL_NOT: + x = stack.pop(); + y = stack.pop(); + stack.push(new Long((x==0)?1:0)); + break; + case DLS_CDL_CONST: + stack.push(new Long(riff.readUnsignedInt())); + break; + case DLS_CDL_QUERY: + uuid = DLSID.read(riff); + stack.push(cdlQuery(uuid)); + break; + case DLS_CDL_QUERYSUPPORTED: + uuid = DLSID.read(riff); + stack.push(new Long(cdlIsQuerySupported(uuid)?1:0)); + break; + default: + break; + } + } + if(stack.isEmpty()) return false; + return stack.pop() == 1; + + } + + private void readInfoChunk(RIFFReader riff) throws IOException { + info.name = null; + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if(format.equals("INAM")) + info.name = chunk.readString(chunk.available()); + else if(format.equals("ICRD")) + info.creationDate = chunk.readString(chunk.available()); + else if(format.equals("IENG")) + info.engineers = chunk.readString(chunk.available()); + else if(format.equals("IPRD")) + info.product = chunk.readString(chunk.available()); + else if(format.equals("ICOP")) + info.copyright = chunk.readString(chunk.available()); + else if(format.equals("ICMT")) + info.comments = chunk.readString(chunk.available()); + else if(format.equals("ISFT")) + info.tools = chunk.readString(chunk.available()); + else if(format.equals("IARL")) + info.archival_location = chunk.readString(chunk.available()); + else if(format.equals("IART")) + info.artist = chunk.readString(chunk.available()); + else if(format.equals("ICMS")) + info.commissioned = chunk.readString(chunk.available()); + else if(format.equals("IGNR")) + info.genre = chunk.readString(chunk.available()); + else if(format.equals("IKEY")) + info.keywords = chunk.readString(chunk.available()); + else if(format.equals("IMED")) + info.medium = chunk.readString(chunk.available()); + else if(format.equals("ISBJ")) + info.subject = chunk.readString(chunk.available()); + else if(format.equals("ISRC")) + info.source = chunk.readString(chunk.available()); + else if(format.equals("ISRF")) + info.source_form = chunk.readString(chunk.available()); + else if(format.equals("ITCH")) + info.technician = chunk.readString(chunk.available()); + } + } + + private void readLinsChunk(RIFFReader riff) throws IOException { + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if(chunk.getType().equals("ins ")) + { + readInsChunk(chunk); + } + + } + } + } + + private void readInsChunk(RIFFReader riff) throws IOException { + DLSInstrument instrument = new DLSInstrument(this); + + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if(format.equals("LIST")) + { + if(chunk.getType().equals("INFO")) + { + readInsInfoChunk(instrument, chunk); + } + if(chunk.getType().equals("lrgn")) + { + while(chunk.hasNextChunk()) + { + RIFFReader subchunk = chunk.nextChunk(); + if(subchunk.getFormat().equals("LIST")) + { + if(subchunk.getType().equals("rgn ")) + { + DLSRegion split = new DLSRegion(); + if(readRgnChunk(split, subchunk)) + instrument.getRegions().add(split); + + } + if(subchunk.getType().equals("rgn2")) // support for DLS level 2 regions + { + DLSRegion split = new DLSRegion(); + if(readRgnChunk(split, subchunk)) + instrument.getRegions().add(split); + + } + } + } + } + if(chunk.getType().equals("lart")) + { + List modlist = new ArrayList(); + while(chunk.hasNextChunk()) + { + RIFFReader subchunk = chunk.nextChunk(); + if (chunk.getFormat().equals("cdl ")) + { + if(!readCdlChunk(chunk)) + { + modlist.clear(); + break; + } + } + if(subchunk.getFormat().equals("art1")) + readArt1Chunk(modlist, subchunk); + } + instrument.getModulators().addAll(modlist); + } + if(chunk.getType().equals("lar2")) // support for DLS level 2 ART + { + List modlist = new ArrayList(); + while(chunk.hasNextChunk()) + { + RIFFReader subchunk = chunk.nextChunk(); + if (chunk.getFormat().equals("cdl ")) + { + if(!readCdlChunk(chunk)) + { + modlist.clear(); + break; + } + } + if(subchunk.getFormat().equals("art2")) + readArt2Chunk(modlist, subchunk); + } + instrument.getModulators().addAll(modlist); + } + } + else + { + if(format.equals("dlid")) + { + instrument.guid = new byte[16]; + chunk.read(instrument.guid); + } + if(format.equals("insh")) + { + chunk.readUnsignedInt(); // Read Region Count - ignored + + int bank = chunk.read(); // LSB + bank += (chunk.read() & 127) << 7; // MSB + chunk.read(); // Read Reserved byte + int drumins = chunk.read(); // Drum Instrument + + int id = chunk.read() & 127; // Read only first 7 bits + chunk.read(); // Read Reserved byte + chunk.read(); // Read Reserved byte + chunk.read(); // Read Reserved byte + + instrument.bank = bank; + instrument.preset = (int)id; + instrument.druminstrument = (drumins & 128) > 0; + //System.out.println("bank="+bank+" drumkit="+drumkit+" id="+id); + } + + } + } + instruments.add(instrument); + } + + private void readArt1Chunk(List modulators, RIFFReader riff) throws IOException { + + long size = riff.readUnsignedInt(); + long count = riff.readUnsignedInt(); + + if(size - 8 != 0) riff.skip(size - 8); + + for (int i = 0; i < count; i++) { + + DLSModulator modulator = new DLSModulator(); + modulator.version = 1; + modulator.source = riff.readUnsignedShort(); + modulator.control = riff.readUnsignedShort(); + modulator.destination = riff.readUnsignedShort(); + modulator.transform = riff.readUnsignedShort(); + modulator.scale = riff.readInt(); + modulators.add(modulator); + } + } + + private void readArt2Chunk(List modulators, RIFFReader riff) throws IOException { + + long size = riff.readUnsignedInt(); + long count = riff.readUnsignedInt(); + + if(size - 8 != 0) riff.skip(size - 8); + + for (int i = 0; i < count; i++) { + + DLSModulator modulator = new DLSModulator(); + modulator.version = 2; + modulator.source = riff.readUnsignedShort(); + modulator.control = riff.readUnsignedShort(); + modulator.destination = riff.readUnsignedShort(); + modulator.transform = riff.readUnsignedShort(); + modulator.scale = riff.readInt(); + modulators.add(modulator); + } + } + private Map temp_rgnassign = new HashMap(); + private boolean readRgnChunk(DLSRegion split, RIFFReader riff) throws IOException { + + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if(format.equals("LIST")) + { + if(chunk.getType().equals("lart")) + { + List modlist = new ArrayList(); + while(chunk.hasNextChunk()) + { + RIFFReader subchunk = chunk.nextChunk(); + if (chunk.getFormat().equals("cdl ")) + { + if(!readCdlChunk(chunk)) + { + modlist.clear(); + break; + } + } + if(subchunk.getFormat().equals("art1")) + readArt1Chunk(modlist, subchunk); + } + split.getModulators().addAll(modlist); + } + if(chunk.getType().equals("lar2")) // support for DLS level 2 ART + { + List modlist = new ArrayList(); + while(chunk.hasNextChunk()) + { + RIFFReader subchunk = chunk.nextChunk(); + if (chunk.getFormat().equals("cdl ")) + { + if(!readCdlChunk(chunk)) + { + modlist.clear(); + break; + } + } + if(subchunk.getFormat().equals("art2")) + readArt2Chunk(modlist, subchunk); + } + split.getModulators().addAll(modlist); + } + } + else + { + + if (format.equals("cdl ")) + { + if(!readCdlChunk(chunk)) + return false; + } + if(format.equals("rgnh")) + { + split.keyfrom = chunk.readUnsignedShort(); + split.keyto = chunk.readUnsignedShort(); + split.velfrom = chunk.readUnsignedShort(); + split.velto = chunk.readUnsignedShort(); + split.options = chunk.readUnsignedShort(); + split.exclusiveClass = chunk.readUnsignedShort(); + } + if(format.equals("wlnk")) + { + split.fusoptions = chunk.readUnsignedShort(); + split.phasegroup = chunk.readUnsignedShort(); + split.channel = chunk.readUnsignedInt(); + long sampleid = chunk.readUnsignedInt(); + temp_rgnassign.put(split, sampleid); + } + if(format.equals("wsmp")) + { + split.sampleoptions = new DLSSampleOptions(); + readWsmpChunk(split.sampleoptions, chunk); + } + } + } + return true; + } + + private void readWsmpChunk(DLSSampleOptions sampleOptions, RIFFReader riff) throws IOException { + + long size = riff.readUnsignedInt(); + sampleOptions.unitynote = riff.readUnsignedShort(); + sampleOptions.finetune = riff.readShort(); + sampleOptions.attenuation = riff.readInt(); + sampleOptions.options = riff.readUnsignedInt(); + long loops = riff.readInt(); + + if(size > 20) + { + riff.skip(size - 20); + } + + for (int i = 0; i < loops; i++) { + DLSSampleLoop loop = new DLSSampleLoop(); + long size2 = riff.readUnsignedInt(); + loop.type = riff.readUnsignedInt(); + loop.start = riff.readUnsignedInt(); + loop.length = riff.readUnsignedInt(); + sampleOptions.loops.add(loop); + if(size2 > 16) + { + riff.skip(size2 - 16); + } + } + } + + private void readInsInfoChunk(DLSInstrument dlsinstrument, RIFFReader riff) throws IOException { + dlsinstrument.info.name = null; + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if(format.equals("INAM")) + dlsinstrument.info.name = chunk.readString(chunk.available()); + else if(format.equals("ICRD")) + dlsinstrument.info.creationDate = chunk.readString(chunk.available()); + else if(format.equals("IENG")) + dlsinstrument.info.engineers = chunk.readString(chunk.available()); + else if(format.equals("IPRD")) + dlsinstrument.info.product = chunk.readString(chunk.available()); + else if(format.equals("ICOP")) + dlsinstrument.info.copyright = chunk.readString(chunk.available()); + else if(format.equals("ICMT")) + dlsinstrument.info.comments = chunk.readString(chunk.available()); + else if(format.equals("ISFT")) + dlsinstrument.info.tools = chunk.readString(chunk.available()); + else if(format.equals("IARL")) + dlsinstrument.info.archival_location = chunk.readString(chunk.available()); + else if(format.equals("IART")) + dlsinstrument.info.artist = chunk.readString(chunk.available()); + else if(format.equals("ICMS")) + dlsinstrument.info.commissioned = chunk.readString(chunk.available()); + else if(format.equals("IGNR")) + dlsinstrument.info.genre = chunk.readString(chunk.available()); + else if(format.equals("IKEY")) + dlsinstrument.info.keywords = chunk.readString(chunk.available()); + else if(format.equals("IMED")) + dlsinstrument.info.medium = chunk.readString(chunk.available()); + else if(format.equals("ISBJ")) + dlsinstrument.info.subject = chunk.readString(chunk.available()); + else if(format.equals("ISRC")) + dlsinstrument.info.source = chunk.readString(chunk.available()); + else if(format.equals("ISRF")) + dlsinstrument.info.source_form = chunk.readString(chunk.available()); + else if(format.equals("ITCH")) + dlsinstrument.info.technician = chunk.readString(chunk.available()); + } + } + + private void readWvplChunk(RIFFReader riff) throws IOException { + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if(chunk.getType().equals("wave")) + { + readWaveChunk(chunk); + } + } + } + } + + private void readWaveChunk(RIFFReader riff) throws IOException { + + DLSSample sample = new DLSSample(this); + + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if(format.equals("LIST")) + { + if(chunk.getType().equals("INFO")) + { + readWaveInfoChunk(sample, chunk); + } + } + else + { + if(format.equals("dlid")) + { + sample.guid = new byte[16]; + chunk.read(sample.guid); + } + + if(format.equals("fmt ")) + { + + int sampleformat = chunk.readUnsignedShort(); + if(sampleformat != 1 && sampleformat != 3) + throw new RIFFInvalidDataException("Only PCM samples are supported!"); + int channels = chunk.readUnsignedShort(); + long samplerate = chunk.readUnsignedInt(); + /* long framerate = */ chunk.readUnsignedInt(); // bytes per sec + int framesize = chunk.readUnsignedShort(); // block align, framesize + int bits = chunk.readUnsignedShort(); + AudioFormat audioformat = null; + if(sampleformat == 1) + if(bits == 8) + audioformat = new AudioFormat( + Encoding.PCM_UNSIGNED, samplerate, bits, + channels, framesize, samplerate, false); + + else + audioformat = new AudioFormat( + Encoding.PCM_SIGNED, samplerate, bits, + channels, framesize, samplerate, false); + if(sampleformat == 3) + audioformat = new AudioFormat + (AudioFloatConverter.PCM_FLOAT, samplerate, bits, + channels, framesize, samplerate, false); + + sample.format = audioformat; + } + + if(format.equals("data")) + { + if(largeFormat) + { + sample.setData(new ModelByteBuffer(sampleFile, chunk.getFilePointer(), chunk.available())); + } + else + { + + byte[] buffer = new byte[chunk.available()]; + // chunk.read(buffer); + sample.setData(buffer); + + int read = 0; + int avail = chunk.available(); + while(read != avail) + { + if(avail - read > 65536) + { + chunk.read(buffer, read, 65536); + read += 65536; + } + else + { + chunk.read(buffer, read, avail - read); + read = avail; + } + + } + } + } + + if(format.equals("wsmp")) + { + sample.sampleoptions = new DLSSampleOptions(); + readWsmpChunk(sample.sampleoptions, chunk); + } + } + } + + samples.add(sample); + + } + + private void readWaveInfoChunk(DLSSample dlssample, RIFFReader riff) throws IOException { + dlssample.info.name = null; + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if(format.equals("INAM")) + dlssample.info.name = chunk.readString(chunk.available()); + else if(format.equals("ICRD")) + dlssample.info.creationDate = chunk.readString(chunk.available()); + else if(format.equals("IENG")) + dlssample.info.engineers = chunk.readString(chunk.available()); + else if(format.equals("IPRD")) + dlssample.info.product = chunk.readString(chunk.available()); + else if(format.equals("ICOP")) + dlssample.info.copyright = chunk.readString(chunk.available()); + else if(format.equals("ICMT")) + dlssample.info.comments = chunk.readString(chunk.available()); + else if(format.equals("ISFT")) + dlssample.info.tools = chunk.readString(chunk.available()); + else if(format.equals("IARL")) + dlssample.info.archival_location = chunk.readString(chunk.available()); + else if(format.equals("IART")) + dlssample.info.artist = chunk.readString(chunk.available()); + else if(format.equals("ICMS")) + dlssample.info.commissioned = chunk.readString(chunk.available()); + else if(format.equals("IGNR")) + dlssample.info.genre = chunk.readString(chunk.available()); + else if(format.equals("IKEY")) + dlssample.info.keywords = chunk.readString(chunk.available()); + else if(format.equals("IMED")) + dlssample.info.medium = chunk.readString(chunk.available()); + else if(format.equals("ISBJ")) + dlssample.info.subject = chunk.readString(chunk.available()); + else if(format.equals("ISRC")) + dlssample.info.source = chunk.readString(chunk.available()); + else if(format.equals("ISRF")) + dlssample.info.source_form = chunk.readString(chunk.available()); + else if(format.equals("ITCH")) + dlssample.info.technician = chunk.readString(chunk.available()); + } + } + + public void save(String name) throws IOException + { + writeSoundbank(new RIFFWriter(name, "DLS ")); + } + + public void save(File file) throws IOException + { + writeSoundbank(new RIFFWriter(file, "DLS ")); + } + + public void save(OutputStream out) throws IOException + { + writeSoundbank(new RIFFWriter(out, "DLS ")); + } + + private void writeSoundbank(RIFFWriter writer) throws IOException + { + RIFFWriter colh_chunk = writer.writeChunk("colh"); + colh_chunk.writeUnsignedInt(instruments.size()); + + if(major != -1 && minor != -1) + { + RIFFWriter vers_chunk = writer.writeChunk("vers"); + vers_chunk.writeUnsignedInt(major); + vers_chunk.writeUnsignedInt(minor); + } + + writeInstruments(writer.writeList("lins")); + + RIFFWriter ptbl = writer.writeChunk("ptbl"); + ptbl.writeUnsignedInt(8); + ptbl.writeUnsignedInt(samples.size()); + long ptbl_offset = writer.getFilePointer(); + for (int i = 0; i < samples.size(); i++) + ptbl.writeUnsignedInt(0); + + RIFFWriter wvpl = writer.writeList("wvpl"); + long off = wvpl.getFilePointer(); + List offsettable = new ArrayList(); + for (DLSSample sample : samples) + { + offsettable.add(new Long(wvpl.getFilePointer() - off)); + writeSample(wvpl.writeList("wave"), sample); + } + + // small cheat, we are going to rewrite data back in wvpl + long bak = writer.getFilePointer(); + writer.seek(ptbl_offset); + writer.setWriteOverride(true); + for(Long offset : offsettable) + writer.writeUnsignedInt(offset.longValue()); + writer.setWriteOverride(false); + writer.seek(bak); + + writeInfo(writer.writeList("INFO"), info); + + writer.close(); + } + + private void writeSample(RIFFWriter writer, DLSSample sample) throws IOException + { + + AudioFormat audioformat = sample.getFormat(); + + Encoding encoding = audioformat.getEncoding(); + float sampleRate = audioformat.getSampleRate(); + int sampleSizeInBits = audioformat.getSampleSizeInBits(); + int channels = audioformat.getChannels(); + int frameSize = audioformat.getFrameSize(); + float frameRate = audioformat.getFrameRate(); + boolean bigEndian = audioformat.isBigEndian(); + + boolean convert_needed = false; + + if(audioformat.getSampleSizeInBits() == 8) + { + if(!encoding.equals(Encoding.PCM_UNSIGNED)) + { + encoding = Encoding.PCM_UNSIGNED; + convert_needed = true; + } + } + else + { + if(!encoding.equals(Encoding.PCM_SIGNED)) + { + encoding = Encoding.PCM_SIGNED; + convert_needed = true; + } + if(bigEndian) + { + bigEndian = false; + convert_needed = true; + } + } + + if(convert_needed) + { + audioformat = new AudioFormat(encoding, sampleRate, + sampleSizeInBits, channels, frameSize, frameRate, bigEndian); + } + + // fmt + RIFFWriter fmt_chunk = writer.writeChunk("fmt "); + int sampleformat = 0; + if(audioformat.getEncoding().equals(Encoding.PCM_UNSIGNED)) sampleformat = 1; + if(audioformat.getEncoding().equals(Encoding.PCM_SIGNED)) sampleformat = 1; + if(audioformat.getEncoding().equals(AudioFloatConverter.PCM_FLOAT)) sampleformat = 3; + fmt_chunk.writeUnsignedShort(sampleformat); + fmt_chunk.writeUnsignedShort(audioformat.getChannels()); + fmt_chunk.writeUnsignedInt((long)audioformat.getSampleRate()); + long srate = (long)audioformat.getSampleRate(); + srate *= audioformat.getChannels(); + srate *= audioformat.getSampleSizeInBits() / 8; + //fmt_chunk.writeUnsignedInt((long)audioformat.getFrameRate()); + fmt_chunk.writeUnsignedInt(srate); + fmt_chunk.writeUnsignedShort(audioformat.getFrameSize()); + fmt_chunk.writeUnsignedShort(audioformat.getSampleSizeInBits()); + fmt_chunk.write(0); + fmt_chunk.write(0); + + writeSampleOptions(writer.writeChunk("wsmp"), sample.sampleoptions); + + if(convert_needed) + { + RIFFWriter data_chunk = writer.writeChunk("data"); + AudioInputStream stream = AudioSystem.getAudioInputStream(audioformat, (AudioInputStream)sample.getData()); + byte[] buff = new byte[1024]; + int ret; + while( (ret = stream.read(buff)) != -1) + { + data_chunk.write(buff, 0, ret); + } + } + else + { + + RIFFWriter data_chunk = writer.writeChunk("data"); + ModelByteBuffer databuff = sample.getDataBuffer(); + databuff.writeTo(data_chunk); + /* + data_chunk.write(databuff.array(), + databuff.arrayOffset(), + databuff.capacity()); + */ + + } + + writeInfo(writer.writeList("INFO"), sample.info); + } + + private void writeInstruments(RIFFWriter writer) throws IOException + { + for(DLSInstrument instrument : instruments) + { + writeInstrument(writer.writeList("ins "), instrument); + } + } + + private void writeInstrument(RIFFWriter writer, DLSInstrument instrument) throws IOException + { + + int art1_count = 0; + int art2_count = 0; + for(DLSModulator modulator : instrument.getModulators()) + { + if(modulator.version == 1) art1_count++; + if(modulator.version == 2) art2_count++; + } + for(DLSRegion region : instrument.regions) + for(DLSModulator modulator : region.getModulators()) + { + if(modulator.version == 1) art1_count++; + if(modulator.version == 2) art2_count++; + } + + int version = 1; + if(art2_count > 0) version = 2; + + RIFFWriter insh_chunk = writer.writeChunk("insh"); + insh_chunk.writeUnsignedInt(instrument.getRegions().size()); + insh_chunk.writeUnsignedInt(instrument.bank + + (instrument.druminstrument?2147483648L:0)); + insh_chunk.writeUnsignedInt(instrument.preset); + + RIFFWriter lrgn = writer.writeList("lrgn"); + for(DLSRegion region : instrument.regions) + writeRegion(lrgn, region, version); + + writeArticulators(writer, instrument.getModulators()); + + writeInfo(writer.writeList("INFO"), instrument.info); + + } + + private void writeArticulators(RIFFWriter writer, List modulators) throws IOException + { + int art1_count = 0; + int art2_count = 0; + for(DLSModulator modulator : modulators) + { + if(modulator.version == 1) art1_count++; + if(modulator.version == 2) art2_count++; + } + if(art1_count > 0) + { + RIFFWriter lar1 = writer.writeList("lart"); + RIFFWriter art1 = lar1.writeChunk("art1"); + art1.writeUnsignedInt(8); + art1.writeUnsignedInt(art1_count); + for(DLSModulator modulator : modulators) + if(modulator.version == 1) + { + + art1.writeUnsignedShort(modulator.source); + art1.writeUnsignedShort(modulator.control); + art1.writeUnsignedShort(modulator.destination); + art1.writeUnsignedShort(modulator.transform); + art1.writeInt(modulator.scale); + } + } + if(art2_count > 0) + { + RIFFWriter lar2 = writer.writeList("lar2"); + RIFFWriter art2 = lar2.writeChunk("art2"); + art2.writeUnsignedInt(8); + art2.writeUnsignedInt(art2_count); + for(DLSModulator modulator : modulators) + if(modulator.version == 2) + { + + art2.writeUnsignedShort(modulator.source); + art2.writeUnsignedShort(modulator.control); + art2.writeUnsignedShort(modulator.destination); + art2.writeUnsignedShort(modulator.transform); + art2.writeInt(modulator.scale); + } + } + } + + private void writeRegion(RIFFWriter writer, DLSRegion region, int version) throws IOException + { + + RIFFWriter rgns = null; + if(version == 1) + rgns = writer.writeList("rgn "); + if(version == 2) + rgns = writer.writeList("rgn2"); + if(rgns == null) + return; + + RIFFWriter rgnh = rgns.writeChunk("rgnh"); + rgnh.writeUnsignedShort(region.keyfrom); + rgnh.writeUnsignedShort(region.keyto); + rgnh.writeUnsignedShort(region.velfrom); + rgnh.writeUnsignedShort(region.velto); + rgnh.writeUnsignedShort(region.options); + rgnh.writeUnsignedShort(region.exclusiveClass); + + if(region.sampleoptions != null) + writeSampleOptions(rgns.writeChunk("wsmp"), region.sampleoptions); + + if(region.sample != null) + if(samples.indexOf(region.sample) != -1) + { + RIFFWriter wlnk = rgns.writeChunk("wlnk"); + wlnk.writeUnsignedShort(region.fusoptions); + wlnk.writeUnsignedShort(region.phasegroup); + wlnk.writeUnsignedInt(region.channel); + wlnk.writeUnsignedInt(samples.indexOf(region.sample)); + } + writeArticulators(rgns, region.getModulators()); + rgns.close(); + } + + private void writeSampleOptions(RIFFWriter wsmp, DLSSampleOptions sampleoptions) throws IOException + { + wsmp.writeUnsignedInt(20); + wsmp.writeUnsignedShort(sampleoptions.unitynote); + wsmp.writeShort(sampleoptions.finetune); + wsmp.writeInt(sampleoptions.attenuation); + wsmp.writeUnsignedInt(sampleoptions.options); + wsmp.writeInt(sampleoptions.loops.size()); + + for(DLSSampleLoop loop : sampleoptions.loops) + { + wsmp.writeUnsignedInt(16); + wsmp.writeUnsignedInt(loop.type); + wsmp.writeUnsignedInt(loop.start); + wsmp.writeUnsignedInt(loop.length); + } + } + + private void writeInfoStringChunk(RIFFWriter writer, String name, String value) throws IOException + { + if(value == null) return; + RIFFWriter chunk = writer.writeChunk(name); + chunk.writeString(value); + int len = value.getBytes("ascii").length; + chunk.write(0); + len++; + if(len % 2 != 0) chunk.write(0); + } + + private void writeInfo(RIFFWriter writer, DLSInfo info) throws IOException + { + writeInfoStringChunk(writer, "INAM", info.name); + writeInfoStringChunk(writer, "ICRD", info.creationDate); + writeInfoStringChunk(writer, "IENG", info.engineers); + writeInfoStringChunk(writer, "IPRD", info.product); + writeInfoStringChunk(writer, "ICOP", info.copyright); + writeInfoStringChunk(writer, "ICMT", info.comments); + writeInfoStringChunk(writer, "ISFT", info.tools); + writeInfoStringChunk(writer, "IARL", info.archival_location); + writeInfoStringChunk(writer, "IART", info.artist); + writeInfoStringChunk(writer, "ICMS", info.commissioned); + writeInfoStringChunk(writer, "IGNR", info.genre); + writeInfoStringChunk(writer, "IKEY", info.keywords); + writeInfoStringChunk(writer, "IMED", info.medium); + writeInfoStringChunk(writer, "ISBJ", info.subject); + writeInfoStringChunk(writer, "ISRC", info.source); + writeInfoStringChunk(writer, "ISRF", info.source_form); + writeInfoStringChunk(writer, "ITCH", info.technician); + } + + public DLSInfo getInfo() { + return info; + } + + public String getName() { + return info.name; + } + + public String getVersion() { + return major + "." + minor; + } + + public String getVendor() { + return info.engineers; + } + + public String getDescription() { + return info.comments; + } + + public void setName(String s) { + info.name = s; + } + + public void setVendor(String s) { + info.engineers = s; + } + + public void setDescription(String s) { + info.comments = s; + } + + public SoundbankResource[] getResources() { + SoundbankResource[] resources = new SoundbankResource[samples.size()]; + int j = 0; + for (int i = 0; i < samples.size(); i++) + resources[j++] = samples.get(i); + return resources; + } + + public DLSInstrument[] getInstruments() { + DLSInstrument[] inslist_array = instruments.toArray(new DLSInstrument[instruments.size()]); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + + public DLSSample[] getSamples() { + return samples.toArray(new DLSSample[samples.size()]); + } + + public Instrument getInstrument(Patch patch) { + int program = patch.getProgram(); + int bank = patch.getBank(); + boolean percussion = false; + if (patch instanceof ModelPatch) + percussion = ((ModelPatch) patch).isPercussion(); + for (Instrument instrument : instruments) { + Patch patch2 = instrument.getPatch(); + int program2 = patch2.getProgram(); + int bank2 = patch2.getBank(); + if (program == program2 && bank == bank2) { + boolean percussion2 = false; + if (patch2 instanceof ModelPatch) + percussion2 = ((ModelPatch) patch2).isPercussion(); + if (percussion == percussion2) + return instrument; + } + } + return null; + } + + public void addResource(SoundbankResource resource) + { + if(resource instanceof DLSInstrument) instruments.add((DLSInstrument)resource); + if(resource instanceof DLSSample) samples.add((DLSSample)resource); + } + + public void removeResource(SoundbankResource resource) + { + if(resource instanceof DLSInstrument) instruments.remove((DLSInstrument)resource); + if(resource instanceof DLSSample) samples.remove((DLSSample)resource); + } + + public void addInstrument(DLSInstrument resource) + { + instruments.add(resource); + } + + public void removeInstrument(DLSInstrument resource) + { + instruments.remove(resource); + } + + public long getMajor() { + return major; + } + + public void setMajor(long major) { + this.major = major; + } + + public long getMinor() { + return minor; + } + + public void setMinor(long minor) { + this.minor = minor; + } + + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbankReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbankReader.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Soundbank; +import javax.sound.midi.spi.SoundbankReader; + +/** + * This class is used to connect the DLSSoundBank class + * to the SoundbankReader SPI interface. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class DLSSoundbankReader extends SoundbankReader { + + public Soundbank getSoundbank(URL url) throws InvalidMidiDataException, IOException { + try + { + return new DLSSoundbank(url); + } + catch(RIFFInvalidFormatException e) + { + return null; + } + } + + public Soundbank getSoundbank(InputStream stream) throws InvalidMidiDataException, IOException { + try + { + stream.mark(512); + return new DLSSoundbank(stream); + } + catch(RIFFInvalidFormatException e) + { + stream.reset(); + return null; + } + } + + public Soundbank getSoundbank(File file) throws InvalidMidiDataException, IOException { + if(!file.getPath().toLowerCase().endsWith(".dls")) return null; + try + { + return new DLSSoundbank(file); + } + catch(RIFFInvalidFormatException e) + { + return null; + } + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/EmergencySoundbank.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/EmergencySoundbank.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,2795 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.Random; + +import javax.sound.midi.Patch; +import javax.sound.sampled.AudioFormat; + +import com.sun.media.sound.ModelPatch; +import com.sun.media.sound.SF2GlobalRegion; +import com.sun.media.sound.SF2Instrument; +import com.sun.media.sound.SF2InstrumentRegion; +import com.sun.media.sound.SF2Layer; +import com.sun.media.sound.SF2LayerRegion; +import com.sun.media.sound.SF2Region; +import com.sun.media.sound.SF2Sample; +import com.sun.media.sound.SF2Soundbank; + +/** + * Emergency Soundbank generator. + * Used when no other default soundbank can be found. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class EmergencySoundbank { + + public static String[] general_midi_instruments = { + "Acoustic Grand Piano", + "Bright Acoustic Piano", + "Electric Grand Piano", + "Honky-tonk Piano", + "Electric Piano 1", + "Electric Piano 2", + "Harpsichord", + "Clavi", + "Celesta", + "Glockenspiel", + "Music Box", + "Vibraphone", + "Marimba", + "Xylophone", + "Tubular Bells", + "Dulcimer", + "Drawbar Organ", + "Percussive Organ", + "Rock Organ", + "Church Organ", + "Reed Organ", + "Accordion", + "Harmonica", + "Tango Accordion", + "Acoustic Guitar (nylon)", + "Acoustic Guitar (steel)", + "Electric Guitar (jazz)", + "Electric Guitar (clean)", + "Electric Guitar (muted)", + "Overdriven Guitar", + "Distortion Guitar", + "Guitar harmonics", + "Acoustic Bass", + "Electric Bass (finger)", + "Electric Bass (pick)", + "Fretless Bass", + "Slap Bass 1", + "Slap Bass 2", + "Synth Bass 1", + "Synth Bass 2", + "Violin", + "Viola", + "Cello", + "Contrabass", + "Tremolo Strings", + "Pizzicato Strings", + "Orchestral Harp", + "Timpani", + "String Ensemble 1", + "String Ensemble 2", + "SynthStrings 1", + "SynthStrings 2", + "Choir Aahs", + "Voice Oohs", + "Synth Voice", + "Orchestra Hit", + "Trumpet", + "Trombone", + "Tuba", + "Muted Trumpet", + "French Horn", + "Brass Section", + "SynthBrass 1", + "SynthBrass 2", + "Soprano Sax", + "Alto Sax", + "Tenor Sax", + "Baritone Sax", + "Oboe", + "English Horn", + "Bassoon", + "Clarinet", + "Piccolo", + "Flute", + "Recorder", + "Pan Flute", + "Blown Bottle", + "Shakuhachi", + "Whistle", + "Ocarina", + "Lead 1 (square)", + "Lead 2 (sawtooth)", + "Lead 3 (calliope)", + "Lead 4 (chiff)", + "Lead 5 (charang)", + "Lead 6 (voice)", + "Lead 7 (fifths)", + "Lead 8 (bass + lead)", + "Pad 1 (new age)", + "Pad 2 (warm)", + "Pad 3 (polysynth)", + "Pad 4 (choir)", + "Pad 5 (bowed)", + "Pad 6 (metallic)", + "Pad 7 (halo)", + "Pad 8 (sweep)", + "FX 1 (rain)", + "FX 2 (soundtrack)", + "FX 3 (crystal)", + "FX 4 (atmosphere)", + "FX 5 (brightness)", + "FX 6 (goblins)", + "FX 7 (echoes)", + "FX 8 (sci-fi)", + "Sitar", + "Banjo", + "Shamisen", + "Koto", + "Kalimba", + "Bag pipe", + "Fiddle", + "Shanai", + "Tinkle Bell", + "Agogo", + "Steel Drums", + "Woodblock", + "Taiko Drum", + "Melodic Tom", + "Synth Drum", + "Reverse Cymbal", + "Guitar Fret Noise", + "Breath Noise", + "Seashore", + "Bird Tweet", + "Telephone Ring", + "Helicopter", + "Applause", + "Gunshot"}; + + public static SF2Soundbank createSoundbank() throws Exception + { + SF2Soundbank sf2 = new SF2Soundbank(); + sf2.setName("Emergency GM sound set"); + sf2.setVendor("Generated"); + sf2.setDescription("Emergency generated soundbank"); + + /* + * percussion instruments + */ + + SF2Layer bass_drum = new_bass_drum(sf2); + SF2Layer snare_drum = new_snare_drum(sf2); + SF2Layer tom = new_tom(sf2); + SF2Layer open_hihat = new_open_hihat(sf2); + SF2Layer closed_hihat = new_closed_hihat(sf2); + SF2Layer crash_cymbal = new_crash_cymbal(sf2); + SF2Layer side_stick = new_side_stick(sf2); + + SF2Layer[] drums = new SF2Layer[128]; + drums[35] = bass_drum; + drums[36] = bass_drum; + drums[38] = snare_drum; + drums[40] = snare_drum; + drums[41] = tom; + drums[43] = tom; + drums[45] = tom; + drums[47] = tom; + drums[48] = tom; + drums[50] = tom; + drums[42] = closed_hihat; + drums[44] = closed_hihat; + drums[46] = open_hihat; + drums[49] = crash_cymbal; + drums[51] = crash_cymbal; + drums[52] = crash_cymbal; + drums[55] = crash_cymbal; + drums[57] = crash_cymbal; + drums[59] = crash_cymbal; + + // Use side_stick for missing drums: + drums[37] = side_stick; + drums[39] = side_stick; + drums[53] = side_stick; + drums[54] = side_stick; + drums[56] = side_stick; + drums[58] = side_stick; + drums[69] = side_stick; + drums[70] = side_stick; + drums[75] = side_stick; + drums[60] = side_stick; + drums[61] = side_stick; + drums[62] = side_stick; + drums[63] = side_stick; + drums[64] = side_stick; + drums[65] = side_stick; + drums[66] = side_stick; + drums[67] = side_stick; + drums[68] = side_stick; + drums[71] = side_stick; + drums[72] = side_stick; + drums[73] = side_stick; + drums[74] = side_stick; + drums[76] = side_stick; + drums[77] = side_stick; + drums[78] = side_stick; + drums[79] = side_stick; + drums[80] = side_stick; + drums[81] = side_stick; + + + SF2Instrument drum_instrument = new SF2Instrument(sf2); + drum_instrument.setName("Standard Kit"); + drum_instrument.setPatch(new ModelPatch(0,0,true)); + sf2.addInstrument(drum_instrument); + for (int i = 0; i < drums.length; i++) { + if(drums[i] != null) + { + SF2InstrumentRegion region = new SF2InstrumentRegion(); + region.setLayer(drums[i]); + region.putBytes(SF2InstrumentRegion.GENERATOR_KEYRANGE, new byte[] {(byte)i, (byte)i}); + drum_instrument.getRegions().add(region); + } + } + + + /* + * melodic instruments + */ + + SF2Layer gpiano = new_gpiano(sf2); + SF2Layer gpiano2 = new_gpiano2(sf2); + SF2Layer gpiano_hammer = new_piano_hammer(sf2); + SF2Layer piano1 = new_piano1(sf2); + SF2Layer epiano1 = new_epiano1(sf2); + SF2Layer epiano2 = new_epiano2(sf2); + + SF2Layer guitar = new_guitar1(sf2); + SF2Layer guitar_pick = new_guitar_pick(sf2); + SF2Layer guitar_dist = new_guitar_dist(sf2); + SF2Layer bass1 = new_bass1(sf2); + SF2Layer bass2 = new_bass2(sf2); + SF2Layer synthbass = new_synthbass(sf2); + SF2Layer string2 = new_string2(sf2); + SF2Layer orchhit = new_orchhit(sf2); + SF2Layer choir = new_choir(sf2); + SF2Layer solostring = new_solostring(sf2); + SF2Layer organ = new_organ(sf2); + SF2Layer ch_organ = new_ch_organ(sf2); + SF2Layer bell = new_bell(sf2); + SF2Layer flute = new_flute(sf2); + + SF2Layer timpani = new_timpani(sf2); + SF2Layer melodic_toms = new_melodic_toms(sf2); + SF2Layer trumpet = new_trumpet(sf2); + SF2Layer trombone = new_trombone(sf2); + SF2Layer brass_section = new_brass_section(sf2); + SF2Layer horn = new_horn(sf2); + SF2Layer sax = new_sax(sf2); + SF2Layer oboe = new_oboe(sf2); + SF2Layer bassoon = new_bassoon(sf2); + SF2Layer clarinet = new_clarinet(sf2); + SF2Layer reverse_cymbal = new_reverse_cymbal(sf2); + + SF2Layer defaultsound = piano1; + + newInstrument(sf2, "Piano", new Patch(0, 0), gpiano, gpiano_hammer); + newInstrument(sf2, "Piano", new Patch(0, 1), gpiano2, gpiano_hammer); + newInstrument(sf2, "Piano", new Patch(0, 2), piano1); + { + SF2Instrument ins = newInstrument(sf2, "Honky-tonk Piano", new Patch(0, 3), piano1, piano1); + SF2InstrumentRegion region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 80); + region.putInteger(SF2Region.GENERATOR_FINETUNE, 30); + region = ins.getRegions().get(1); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 30); + } + newInstrument(sf2, "Rhodes", new Patch(0, 4), epiano2); + newInstrument(sf2, "Rhodes", new Patch(0, 5), epiano2); + newInstrument(sf2, "Clavinet", new Patch(0, 6), epiano1); + newInstrument(sf2, "Clavinet", new Patch(0, 7), epiano1); + newInstrument(sf2, "Rhodes", new Patch(0, 8), epiano2); + newInstrument(sf2, "Bell", new Patch(0, 9), bell); + newInstrument(sf2, "Bell", new Patch(0, 10), bell); + newInstrument(sf2, "Vibraphone", new Patch(0, 11), bell); + newInstrument(sf2, "Marimba", new Patch(0, 12), bell); + newInstrument(sf2, "Marimba", new Patch(0, 13), bell); + newInstrument(sf2, "Bell", new Patch(0, 14), bell); + newInstrument(sf2, "Rock Organ", new Patch(0, 15), organ); + newInstrument(sf2, "Rock Organ", new Patch(0, 16), organ); + newInstrument(sf2, "Perc Organ", new Patch(0, 17), organ); + newInstrument(sf2, "Rock Organ", new Patch(0, 18), organ); + newInstrument(sf2, "Church Organ", new Patch(0, 19), ch_organ); + newInstrument(sf2, "Accordion", new Patch(0, 20), organ); + newInstrument(sf2, "Accordion", new Patch(0, 21), organ); + newInstrument(sf2, "Accordion", new Patch(0, 22), organ); + newInstrument(sf2, "Accordion", new Patch(0, 23), organ); + newInstrument(sf2, "Guitar", new Patch(0, 24), guitar, guitar_pick); + newInstrument(sf2, "Guitar", new Patch(0, 25), guitar, guitar_pick); + newInstrument(sf2, "Guitar", new Patch(0, 26), guitar, guitar_pick); + newInstrument(sf2, "Guitar", new Patch(0, 27), guitar, guitar_pick); + newInstrument(sf2, "Guitar", new Patch(0, 28), guitar, guitar_pick); + newInstrument(sf2, "Distorted Guitar", new Patch(0, 29), guitar_dist); + newInstrument(sf2, "Distorted Guitar", new Patch(0, 30), guitar_dist); + newInstrument(sf2, "Guitar", new Patch(0, 31), guitar, guitar_pick); + newInstrument(sf2, "Finger Bass", new Patch(0, 32), bass1); + newInstrument(sf2, "Finger Bass", new Patch(0, 33), bass1); + newInstrument(sf2, "Finger Bass", new Patch(0, 34), bass1); + newInstrument(sf2, "Frettless Bass", new Patch(0, 35), bass2); + newInstrument(sf2, "Frettless Bass", new Patch(0, 36), bass2); + newInstrument(sf2, "Frettless Bass", new Patch(0, 37), bass2); + newInstrument(sf2, "Synth Bass1", new Patch(0, 38), synthbass); + newInstrument(sf2, "Synth Bass2", new Patch(0, 39), synthbass); + newInstrument(sf2, "Solo String", new Patch(0, 40), string2, solostring); + newInstrument(sf2, "Solo String", new Patch(0, 41), string2, solostring); + newInstrument(sf2, "Solo String", new Patch(0, 42), string2, solostring); + newInstrument(sf2, "Solo String", new Patch(0, 43), string2, solostring); + newInstrument(sf2, "Solo String", new Patch(0, 44), string2, solostring); + newInstrument(sf2, "Def", new Patch(0, 45), defaultsound); + newInstrument(sf2, "Harp", new Patch(0, 46), bell); + newInstrument(sf2, "Timpani", new Patch(0, 47), timpani); + newInstrument(sf2, "Strings", new Patch(0, 48), string2); + SF2Instrument slow_strings = newInstrument(sf2, "Slow Strings", new Patch(0, 49), string2); + SF2InstrumentRegion region = slow_strings.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, 2500); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 2000); + newInstrument(sf2, "Synth Strings", new Patch(0, 50), string2); + newInstrument(sf2, "Synth Strings", new Patch(0, 51), string2); + + + newInstrument(sf2, "Choir", new Patch(0, 52), choir); + newInstrument(sf2, "Choir", new Patch(0, 53), choir); + newInstrument(sf2, "Choir", new Patch(0, 54), choir); + { + SF2Instrument ins = newInstrument(sf2, "Orch Hit", new Patch(0, 55), orchhit,orchhit,timpani); + region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_COARSETUNE, -12); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + } + newInstrument(sf2, "Trumpet", new Patch(0, 56), trumpet); + newInstrument(sf2, "Trombone", new Patch(0, 57), trombone); + newInstrument(sf2, "Trombone", new Patch(0, 58), trombone); + newInstrument(sf2, "Trumpet", new Patch(0, 59), trumpet); + newInstrument(sf2, "Horn", new Patch(0, 60), horn); + newInstrument(sf2, "Brass Section", new Patch(0, 61), brass_section); + newInstrument(sf2, "Brass Section", new Patch(0, 62), brass_section); + newInstrument(sf2, "Brass Section", new Patch(0, 63), brass_section); + newInstrument(sf2, "Sax", new Patch(0, 64), sax); + newInstrument(sf2, "Sax", new Patch(0, 65), sax); + newInstrument(sf2, "Sax", new Patch(0, 66), sax); + newInstrument(sf2, "Sax", new Patch(0, 67), sax); + newInstrument(sf2, "Oboe", new Patch(0, 68), oboe); + newInstrument(sf2, "Horn", new Patch(0, 69), horn); + newInstrument(sf2, "Bassoon", new Patch(0, 70), bassoon); + newInstrument(sf2, "Clarinet", new Patch(0, 71), clarinet); + newInstrument(sf2, "Flute", new Patch(0, 72), flute); + newInstrument(sf2, "Flute", new Patch(0, 73), flute); + newInstrument(sf2, "Flute", new Patch(0, 74), flute); + newInstrument(sf2, "Flute", new Patch(0, 75), flute); + newInstrument(sf2, "Flute", new Patch(0, 76), flute); + newInstrument(sf2, "Flute", new Patch(0, 77), flute); + newInstrument(sf2, "Flute", new Patch(0, 78), flute); + newInstrument(sf2, "Flute", new Patch(0, 79), flute); + newInstrument(sf2, "Organ", new Patch(0, 80), organ); + newInstrument(sf2, "Organ", new Patch(0, 81), organ); + newInstrument(sf2, "Flute", new Patch(0, 82), flute); + newInstrument(sf2, "Organ", new Patch(0, 83), organ); + newInstrument(sf2, "Organ", new Patch(0, 84), organ); + newInstrument(sf2, "Choir", new Patch(0, 85), choir); + newInstrument(sf2, "Organ", new Patch(0, 86), organ); + newInstrument(sf2, "Organ", new Patch(0, 87), organ); + newInstrument(sf2, "Synth Strings", new Patch(0, 88), string2); + newInstrument(sf2, "Organ", new Patch(0, 89), organ); + newInstrument(sf2, "Def", new Patch(0, 90), defaultsound); + newInstrument(sf2, "Choir", new Patch(0, 91), choir); + newInstrument(sf2, "Organ", new Patch(0, 92), organ); + newInstrument(sf2, "Organ", new Patch(0, 93), organ); + newInstrument(sf2, "Organ", new Patch(0, 94), organ); + newInstrument(sf2, "Organ", new Patch(0, 95), organ); + newInstrument(sf2, "Organ", new Patch(0, 96), organ); + newInstrument(sf2, "Organ", new Patch(0, 97), organ); + newInstrument(sf2, "Bell", new Patch(0, 98), bell); + newInstrument(sf2, "Organ", new Patch(0, 99), organ); + newInstrument(sf2, "Organ", new Patch(0, 100), organ); + newInstrument(sf2, "Organ", new Patch(0, 101), organ); + newInstrument(sf2, "Def", new Patch(0, 102), defaultsound); + newInstrument(sf2, "Synth Strings", new Patch(0, 103), string2); + newInstrument(sf2, "Def", new Patch(0, 104), defaultsound); + newInstrument(sf2, "Def", new Patch(0, 105), defaultsound); + newInstrument(sf2, "Def", new Patch(0, 106), defaultsound); + newInstrument(sf2, "Def", new Patch(0, 107), defaultsound); + newInstrument(sf2, "Marimba", new Patch(0, 108), bell); + newInstrument(sf2, "Sax", new Patch(0, 109), sax); + newInstrument(sf2, "Solo String", new Patch(0, 110), string2, solostring); + newInstrument(sf2, "Oboe", new Patch(0, 111), oboe); + newInstrument(sf2, "Bell", new Patch(0, 112), bell); + newInstrument(sf2, "Melodic Toms", new Patch(0, 113), melodic_toms); + newInstrument(sf2, "Marimba", new Patch(0, 114), bell); + newInstrument(sf2, "Melodic Toms", new Patch(0, 115), melodic_toms); + newInstrument(sf2, "Melodic Toms", new Patch(0, 116), melodic_toms); + newInstrument(sf2, "Melodic Toms", new Patch(0, 117), melodic_toms); + newInstrument(sf2, "Reverse Cymbal", new Patch(0, 118), reverse_cymbal); + newInstrument(sf2, "Reverse Cymbal", new Patch(0, 119), reverse_cymbal); + newInstrument(sf2, "Guitar", new Patch(0, 120), guitar); + newInstrument(sf2, "Def", new Patch(0, 121), defaultsound); + { + SF2Instrument ins = newInstrument(sf2, "Seashore/Reverse Cymbal", new Patch(0, 122), reverse_cymbal); + region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 18500); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 4500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, -4500); + } + { + SF2Instrument ins = newInstrument(sf2, "Bird/Flute", new Patch(0, 123), flute); + region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_COARSETUNE, 24); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, -3000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + } + newInstrument(sf2, "Def", new Patch(0, 124), side_stick); + { + SF2Instrument ins = newInstrument(sf2, "Seashore/Reverse Cymbal", new Patch(0, 125), reverse_cymbal); + region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 18500); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 4500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, -4500); + } + newInstrument(sf2, "Applause/crash_cymbal", new Patch(0, 126), crash_cymbal); + newInstrument(sf2, "Gunshot/side_stick", new Patch(0, 127), side_stick); + + for(SF2Instrument instrument : sf2.getInstruments()) + { + Patch patch = instrument.getPatch(); + if(patch instanceof ModelPatch) + if(((ModelPatch)patch).isPercussion()) continue; + instrument.setName(general_midi_instruments[patch.getProgram()]); + } + + return sf2; + + } + + public static SF2Layer new_bell(SF2Soundbank sf2) + { + Random random = new Random(102030201); + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 0.01; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.00001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + for (int i = 0; i < 40; i++) { + double detune = 1 + (random.nextDouble()*2 - 1)*0.01; + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1)*detune, w, a); + a *= a_step; + } + SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base); + SF2Layer layer = newLayer(sf2, "EPiano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 1200); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -9000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + return layer; + } + + public static SF2Layer new_guitar1(SF2Soundbank sf2) + { + + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 0.01; + double end_w = 0.01; + double start_a = 2; + double end_a = 0.01; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + + double[] aa = new double[40]; + for (int i = 0; i < 40; i++) + { + aa[i] = a; + a *= a_step; + } + + aa[0] = 2; + aa[1] = 0.5; + aa[2] = 0.45; + aa[3] = 0.2; + aa[4] = 1; + aa[5] = 0.5; + aa[6] = 2; + aa[7] = 1; + aa[8] = 0.5; + aa[9] = 1; + aa[9] = 0.5; + aa[10] = 0.2; + aa[11] = 1; + aa[12] = 0.7; + aa[13] = 0.5; + aa[14] = 1; + + for (int i = 0; i < 40; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, aa[i]); + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Guitar", data, base); + SF2Layer layer = newLayer(sf2, "Guitar", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 2400); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -100); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -6000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -20); + return layer; + } + + + public static SF2Layer new_guitar_dist(SF2Soundbank sf2) + { + + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 0.01; + double end_w = 0.01; + double start_a = 2; + double end_a = 0.01; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + + double[] aa = new double[40]; + for (int i = 0; i < 40; i++) + { + aa[i] = a; + a *= a_step; + } + + aa[0] = 5; + aa[1] = 2; + aa[2] = 0.45; + aa[3] = 0.2; + aa[4] = 1; + aa[5] = 0.5; + aa[6] = 2; + aa[7] = 1; + aa[8] = 0.5; + aa[9] = 1; + aa[9] = 0.5; + aa[10] = 0.2; + aa[11] = 1; + aa[12] = 0.7; + aa[13] = 0.5; + aa[14] = 1; + + for (int i = 0; i < 40; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, aa[i]); + } + + + + SF2Sample sample = newSimpleFFTSample_dist(sf2, "Distorted Guitar", data, base, 10000.0); + + + + SF2Layer layer = newLayer(sf2, "Distorted Guitar", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + //region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 2400); + //region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 200); + + //region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -100); + //region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + //region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -1000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 8000); + //region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -20); + return layer; + } + + + public static SF2Layer new_guitar_pick(SF2Soundbank sf2) + { + + double datab[]; + + // Make treble part + { + int m = 2; + int fftlen = 4096*m; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5)); + fft(data); + // Remove all negative frequency + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 2048*m; i++) + data[i] *= Math.exp(-Math.abs((i-23)/((double)m))*1.2) + +Math.exp(-Math.abs((i-40)/((double)m))*0.9); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.8); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9994; + } + datab = data; + + fadeUp(data, 80); + } + + SF2Sample sample = newSimpleDrumSample(sf2, "Guitar Noise", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Guitar Noise"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + //region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); +// region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); +/* + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 0); + region.putInteger(SF2Region.GENERATOR_SUSTAINMODENV, 1000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -11000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 12000); + */ + + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + + public static SF2Layer new_gpiano(SF2Soundbank sf2) + { + //Random random = new Random(302030201); + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/15.0); + + double[] aa = new double[30]; + for (int i = 0; i < 30; i++) + { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 2; + //aa[2] *= 0.1; + aa[4] *= 2; + + + aa[12] *= 0.9; + aa[13] *= 0.7; + for (int i = 14; i < 30; i++) + { + aa[i] *= 0.5; + } + + + for (int i = 0; i < 30; i++) { + //double detune = 1 + (random.nextDouble()*2 - 1)*0.0001; + double w = 0.2; + double ai = aa[i]; + if(i > 10) + { + w = 5; + ai *= 10; + } + int adjust = 0; + if(i > 5) + { + adjust = (i - 5)*7; + } + complexGaussianDist(data, base*(i+1)+adjust, w, ai); + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Grand Piano", data, base, 200); + SF2Layer layer = newLayer(sf2, "Grand Piano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -7000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 18000); + return layer; + } + + public static SF2Layer new_gpiano2(SF2Soundbank sf2) + { + //Random random = new Random(302030201); + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/20.0); + + double[] aa = new double[30]; + for (int i = 0; i < 30; i++) + { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 1; + //aa[2] *= 0.1; + aa[4] *= 2; + + + aa[12] *= 0.9; + aa[13] *= 0.7; + for (int i = 14; i < 30; i++) + { + aa[i] *= 0.5; + } + + + for (int i = 0; i < 30; i++) { + //double detune = 1 + (random.nextDouble()*2 - 1)*0.0001; + double w = 0.2; + double ai = aa[i]; + if(i > 10) + { + w = 5; + ai *= 10; + } + int adjust = 0; + if(i > 5) + { + adjust = (i - 5)*7; + } + complexGaussianDist(data, base*(i+1)+adjust, w, ai); + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Grand Piano", data, base, 200); + SF2Layer layer = newLayer(sf2, "Grand Piano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -7000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 18000); + return layer; + } + + + public static SF2Layer new_piano_hammer(SF2Soundbank sf2) + { + + double datab[]; + + // Make treble part + { + int m = 2; + int fftlen = 4096*m; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5)); + fft(data); + // Remove all negative frequency + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 2048*m; i++) + data[i] *= Math.exp(-Math.abs((i-37)/((double)m))*0.05); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.6); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9997; + } + datab = data; + + fadeUp(data, 80); + } + + SF2Sample sample = newSimpleDrumSample(sf2, "Piano Hammer", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Piano Hammer"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + //region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); +/* + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 0); + region.putInteger(SF2Region.GENERATOR_SUSTAINMODENV, 1000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -11000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 12000); + */ + + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + + + public static SF2Layer new_piano1(SF2Soundbank sf2) + { + //Random random = new Random(302030201); + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_a = 0.2; + double end_a = 0.0001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + + double[] aa = new double[30]; + for (int i = 0; i < 30; i++) + { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 5; + aa[2] *= 0.1; + aa[7] *= 5; + + + for (int i = 0; i < 30; i++) { + //double detune = 1 + (random.nextDouble()*2 - 1)*0.0001; + double w = 0.2; + double ai = aa[i]; + if(i > 12) + { + w = 5; + ai *= 10; + } + int adjust = 0; + if(i > 5) + { + adjust = (i - 5)*7; + } + complexGaussianDist(data, base*(i+1)+adjust, w, ai); + } + + complexGaussianDist(data, base*(15.5), 1, 0.1); + complexGaussianDist(data, base*(17.5), 1, 0.01); + + SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base, 200); + SF2Layer layer = newLayer(sf2, "EPiano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -1200); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + return layer; + } + + public static SF2Layer new_epiano1(SF2Soundbank sf2) + { + Random random = new Random(302030201); + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 0.05; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.0001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + for (int i = 0; i < 40; i++) { + double detune = 1 + (random.nextDouble()*2 - 1)*0.0001; + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1)*detune, w, a); + a *= a_step; + } + + + + SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base); + SF2Layer layer = newLayer(sf2, "EPiano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 1200); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -9000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + return layer; + } + + + + public static SF2Layer new_epiano2(SF2Soundbank sf2) + { + Random random = new Random(302030201); + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 0.01; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.00001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + for (int i = 0; i < 40; i++) { + double detune = 1 + (random.nextDouble()*2 - 1)*0.0001; + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1)*detune, w, a); + a *= a_step; + } + + SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base); + SF2Layer layer = newLayer(sf2, "EPiano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 8000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 2400); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -9000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + return layer; + } + + public static SF2Layer new_bass1(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 0.05; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.02; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/25.0); + + double[] aa = new double[25]; + for (int i = 0; i < 25; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 8; + aa[1] *= 4; + aa[3] *= 8; + aa[5] *= 8; + + for (int i = 0; i < 25; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, aa[i]); + } + + + + + SF2Sample sample = newSimpleFFTSample(sf2, "Bass", data, base); + SF2Layer layer = newLayer(sf2, "Bass", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 11000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + return layer; + } + + public static SF2Layer new_synthbass(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 0.05; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.02; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/25.0); + + double[] aa = new double[25]; + for (int i = 0; i < 25; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 16; + aa[1] *= 4; + aa[3] *= 16; + aa[5] *= 8; + + for (int i = 0; i < 25; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, aa[i]); + } + + + + SF2Sample sample = newSimpleFFTSample(sf2, "Bass", data, base); + SF2Layer layer = newLayer(sf2, "Bass", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -3000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERQ, 100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 8000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + return layer; + } + + public static SF2Layer new_bass2(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 0.05; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.002; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/25.0); + + double[] aa = new double[25]; + for (int i = 0; i < 25; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 8; + aa[1] *= 4; + aa[3] *= 8; + aa[5] *= 8; + + for (int i = 0; i < 25; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, aa[i]); + } + + + + SF2Sample sample = newSimpleFFTSample(sf2, "Bass2", data, base); + SF2Layer layer = newLayer(sf2, "Bass2", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -8000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + return layer; + } + + + + public static SF2Layer new_solostring(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 2; + double end_w = 2; + double start_a = 0.2; + double end_a = 0.01; + + double[] aa = new double[18]; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + for (int i = 0; i < aa.length; i++) { + a *= a_step; + aa[i] = a; + } + + aa[0] *= 5; + aa[1] *= 5; + aa[2] *= 5; + aa[3] *= 4; + aa[4] *= 4; + aa[5] *= 3; + aa[6] *= 3; + aa[7] *= 2; + + for (int i = 0; i < aa.length; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, a); + } + SF2Sample sample = newSimpleFFTSample(sf2, "Strings", data, base); + SF2Layer layer = newLayer(sf2, "Strings", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + region.putInteger(SF2Region.GENERATOR_FREQVIBLFO, -1000); + region.putInteger(SF2Region.GENERATOR_VIBLFOTOPITCH, 15); + return layer; + + } + + public static SF2Layer new_orchhit(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 2; + double end_w = 80; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + for (int i = 0; i < 40; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, a); + a *= a_step; + } + complexGaussianDist(data, base*4, 300, 1); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Och Strings", data, base); + SF2Layer layer = newLayer(sf2, "Och Strings", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 200); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 200); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + + public static SF2Layer new_string2(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 2; + double end_w = 80; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + for (int i = 0; i < 40; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, a); + a *= a_step; + } + SF2Sample sample = newSimpleFFTSample(sf2, "Strings", data, base); + SF2Layer layer = newLayer(sf2, "Strings", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + + public static SF2Layer new_choir(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 25; + double start_w = 2; + double end_w = 80; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + double[] aa = new double[40]; + for (int i = 0; i < aa.length; i++) { + a *= a_step; + aa[i] = a; + } + + aa[5] *= 0.1; + aa[6] *= 0.01; + aa[7] *= 0.1; + aa[8] *= 0.1; + + for (int i = 0; i < aa.length; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, aa[i]); + } + SF2Sample sample = newSimpleFFTSample(sf2, "Strings", data, base); + SF2Layer layer = newLayer(sf2, "Strings", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + + public static SF2Layer new_organ(SF2Soundbank sf2) + { + Random random = new Random(102030201); + int x = 1; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + double start_w = 0.01; + double end_w = 0.01; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + + for (int i = 0; i < 12; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, a*(0.5 + 3*(random.nextDouble()))); + a *= a_step; + } + SF2Sample sample = newSimpleFFTSample(sf2, "Organ", data, base); + SF2Layer layer = newLayer(sf2, "Organ", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + + + public static SF2Layer new_ch_organ(SF2Soundbank sf2) + { + int x = 1; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + double start_w = 0.01; + double end_w = 0.01; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/60.0); + + double[] aa = new double[60]; + for (int i = 0; i < aa.length; i++) { + a *= a_step; + aa[i] = a; + } + + aa[0] *= 5; + aa[1] *= 2; + aa[2] = 0; + aa[4] = 0; + aa[5] = 0; + aa[7] *= 7; + aa[9] = 0; + aa[10] = 0; + aa[12] = 0; + aa[15] *= 7; + aa[18] = 0; + aa[20] = 0; + aa[24] = 0; + aa[27] *= 5; + aa[29] = 0; + aa[30] = 0; + aa[33] = 0; + aa[36] *= 4; + aa[37] = 0; + aa[39] = 0; + aa[42] = 0; + aa[43] = 0; + aa[47] = 0; + aa[50] *= 4; + aa[52] = 0; + aa[55] = 0; + aa[57] = 0; + + + aa[10] *= 0.1; + aa[11] *= 0.1; + aa[12] *= 0.1; + aa[13] *= 0.1; + + aa[17] *= 0.1; + aa[18] *= 0.1; + aa[19] *= 0.1; + aa[20] *= 0.1; + + for (int i = 0; i < 60; i++) { + double w = start_w + (end_w - start_w)*(i/40.0); + complexGaussianDist(data, base*(i+1), w, aa[i]); + a *= a_step; + } + SF2Sample sample = newSimpleFFTSample(sf2, "Organ", data, base); + SF2Layer layer = newLayer(sf2, "Organ", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -10000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + return layer; + + } + + public static SF2Layer new_flute(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + + complexGaussianDist(data, base*1, 0.001, 0.5); + complexGaussianDist(data, base*2, 0.001, 0.5); + complexGaussianDist(data, base*3, 0.001, 0.5); + complexGaussianDist(data, base*4, 0.01, 0.5); + + complexGaussianDist(data, base*4, 100, 120); + complexGaussianDist(data, base*6, 100, 40); + complexGaussianDist(data, base*8, 100, 80); + + complexGaussianDist(data, base*5, 0.001, 0.05); + complexGaussianDist(data, base*6, 0.001, 0.06); + complexGaussianDist(data, base*7, 0.001, 0.04); + complexGaussianDist(data, base*8, 0.005, 0.06); + complexGaussianDist(data, base*9, 0.005, 0.06); + complexGaussianDist(data, base*10, 0.01, 0.1); + complexGaussianDist(data, base*11, 0.08, 0.7); + complexGaussianDist(data, base*12, 0.08, 0.6); + complexGaussianDist(data, base*13, 0.08, 0.6); + complexGaussianDist(data, base*14, 0.08, 0.6); + complexGaussianDist(data, base*15, 0.08, 0.5); + complexGaussianDist(data, base*16, 0.08, 0.5); + complexGaussianDist(data, base*17, 0.08, 0.2); + + + complexGaussianDist(data, base*1, 10, 8); + complexGaussianDist(data, base*2, 10, 8); + complexGaussianDist(data, base*3, 10, 8); + complexGaussianDist(data, base*4, 10, 8); + complexGaussianDist(data, base*5, 10, 8); + complexGaussianDist(data, base*6, 20, 9); + complexGaussianDist(data, base*7, 20, 9); + complexGaussianDist(data, base*8, 20, 9); + complexGaussianDist(data, base*9, 20, 8); + complexGaussianDist(data, base*10, 30, 8); + complexGaussianDist(data, base*11, 30, 9); + complexGaussianDist(data, base*12, 30, 9); + complexGaussianDist(data, base*13, 30, 8); + complexGaussianDist(data, base*14, 30, 8); + complexGaussianDist(data, base*15, 30, 7); + complexGaussianDist(data, base*16, 30, 7); + complexGaussianDist(data, base*17, 30, 6); + + SF2Sample sample = newSimpleFFTSample(sf2, "Flute", data, base); + SF2Layer layer = newLayer(sf2, "Flute", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_horn(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.00000000001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + for (int i = 0; i < 40; i++) { + if(i == 0) + complexGaussianDist(data, base*(i+1), 0.1, a*0.2); + else + complexGaussianDist(data, base*(i+1), 0.1, a); + a *= a_step; + } + + complexGaussianDist(data, base*2, 100, 1); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Horn", data, base); + SF2Layer layer = newLayer(sf2, "Horn", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -500); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + return layer; + + } + + public static SF2Layer new_trumpet(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.00001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/80.0); + double[] aa = new double[80]; + for (int i = 0; i < 80; i++) + { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 0.05; + aa[1] *= 0.2; + aa[2] *= 0.5; + aa[3] *= 0.85; + + for (int i = 0; i < 80; i++) { + complexGaussianDist(data, base*(i+1), 0.1, aa[i]); + + } + + complexGaussianDist(data, base*5, 300, 3); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Trumpet", data, base); + SF2Layer layer = newLayer(sf2, "Trumpet", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -10000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -4000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, -2500); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERQ, 10); + return layer; + + } + + public static SF2Layer new_brass_section(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.005; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/30.0); + double[] aa = new double[30]; + for (int i = 0; i < 30; i++) + { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 0.8; + aa[1] *= 0.9; + + double w = 5; + for (int i = 0; i < 30; i++) { + + complexGaussianDist(data, base*(i+1), 0.1*w, aa[i]*w); + w += 6; //*= w_step; + } + + complexGaussianDist(data, base*6, 300, 2); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Brass Section", data, base); + SF2Layer layer = newLayer(sf2, "Brass Section", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -9200); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + return layer; + + } + + + public static SF2Layer new_trombone(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/80.0); + double[] aa = new double[80]; + for (int i = 0; i < 80; i++) + { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 0.3; + aa[1] *= 0.7; + + for (int i = 0; i < 80; i++) { + complexGaussianDist(data, base*(i+1), 0.1, aa[i]); + + } + + complexGaussianDist(data, base*6, 300, 2); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Trombone", data, base); + SF2Layer layer = newLayer(sf2, "Trombone", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -8000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -2000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERQ, 10); + return layer; + + } + + public static SF2Layer new_sax(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.01; + double a = start_a; + double a_step = Math.pow(end_a/start_a, 1.0/40.0); + for (int i = 0; i < 40; i++) { + if(i == 0 || i == 2) + complexGaussianDist(data, base*(i+1), 0.1, a*4); + else + complexGaussianDist(data, base*(i+1), 0.1, a); + a *= a_step; + } + + complexGaussianDist(data, base*4, 200, 1); + + SF2Sample sample = newSimpleFFTSample(sf2, "Sax", data, base); + SF2Layer layer = newLayer(sf2, "Sax", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + return layer; + + } + + public static SF2Layer new_oboe(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + + complexGaussianDist(data, base*5, 100, 80); + + + complexGaussianDist(data, base*1, 0.01, 0.53); + complexGaussianDist(data, base*2, 0.01, 0.51); + complexGaussianDist(data, base*3, 0.01, 0.48); + complexGaussianDist(data, base*4, 0.01, 0.49); + complexGaussianDist(data, base*5, 0.01, 5); + complexGaussianDist(data, base*6, 0.01, 0.51); + complexGaussianDist(data, base*7, 0.01, 0.50); + complexGaussianDist(data, base*8, 0.01, 0.59); + complexGaussianDist(data, base*9, 0.01, 0.61); + complexGaussianDist(data, base*10, 0.01, 0.52); + complexGaussianDist(data, base*11, 0.01, 0.49); + complexGaussianDist(data, base*12, 0.01, 0.51); + complexGaussianDist(data, base*13, 0.01, 0.48); + complexGaussianDist(data, base*14, 0.01, 0.51); + complexGaussianDist(data, base*15, 0.01, 0.46); + complexGaussianDist(data, base*16, 0.01, 0.35); + complexGaussianDist(data, base*17, 0.01, 0.20); + complexGaussianDist(data, base*18, 0.01, 0.10); + complexGaussianDist(data, base*19, 0.01, 0.5); + complexGaussianDist(data, base*20, 0.01, 0.1); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Oboe", data, base); + SF2Layer layer = newLayer(sf2, "Oboe", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_bassoon(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + + complexGaussianDist(data, base*2, 100, 40); + complexGaussianDist(data, base*4, 100, 20); + + complexGaussianDist(data, base*1, 0.01, 0.53); + complexGaussianDist(data, base*2, 0.01, 5); + complexGaussianDist(data, base*3, 0.01, 0.51); + complexGaussianDist(data, base*4, 0.01, 0.48); + complexGaussianDist(data, base*5, 0.01, 1.49); + complexGaussianDist(data, base*6, 0.01, 0.51); + complexGaussianDist(data, base*7, 0.01, 0.50); + complexGaussianDist(data, base*8, 0.01, 0.59); + complexGaussianDist(data, base*9, 0.01, 0.61); + complexGaussianDist(data, base*10, 0.01, 0.52); + complexGaussianDist(data, base*11, 0.01, 0.49); + complexGaussianDist(data, base*12, 0.01, 0.51); + complexGaussianDist(data, base*13, 0.01, 0.48); + complexGaussianDist(data, base*14, 0.01, 0.51); + complexGaussianDist(data, base*15, 0.01, 0.46); + complexGaussianDist(data, base*16, 0.01, 0.35); + complexGaussianDist(data, base*17, 0.01, 0.20); + complexGaussianDist(data, base*18, 0.01, 0.10); + complexGaussianDist(data, base*19, 0.01, 0.5); + complexGaussianDist(data, base*20, 0.01, 0.1); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Flute", data, base); + SF2Layer layer = newLayer(sf2, "Flute", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_clarinet(SF2Soundbank sf2) + { + int x = 8; + int fftsize = 4096*x; + double[] data = new double[fftsize*2]; + double base = x * 15; + + complexGaussianDist(data, base*1, 0.001, 0.5); + complexGaussianDist(data, base*2, 0.001, 0.02); + complexGaussianDist(data, base*3, 0.001, 0.2); + complexGaussianDist(data, base*4, 0.01, 0.1); + + complexGaussianDist(data, base*4, 100, 60); + complexGaussianDist(data, base*6, 100, 20); + complexGaussianDist(data, base*8, 100, 20); + + complexGaussianDist(data, base*5, 0.001, 0.1); + complexGaussianDist(data, base*6, 0.001, 0.09); + complexGaussianDist(data, base*7, 0.001, 0.02); + complexGaussianDist(data, base*8, 0.005, 0.16); + complexGaussianDist(data, base*9, 0.005, 0.96); + complexGaussianDist(data, base*10, 0.01, 0.9); + complexGaussianDist(data, base*11, 0.08, 1.2); + complexGaussianDist(data, base*12, 0.08, 1.8); + complexGaussianDist(data, base*13, 0.08, 1.6); + complexGaussianDist(data, base*14, 0.08, 1.2); + complexGaussianDist(data, base*15, 0.08, 0.9); + complexGaussianDist(data, base*16, 0.08, 0.5); + complexGaussianDist(data, base*17, 0.08, 0.2); + + + complexGaussianDist(data, base*1, 10, 8); + complexGaussianDist(data, base*2, 10, 8); + complexGaussianDist(data, base*3, 10, 8); + complexGaussianDist(data, base*4, 10, 8); + complexGaussianDist(data, base*5, 10, 8); + complexGaussianDist(data, base*6, 20, 9); + complexGaussianDist(data, base*7, 20, 9); + complexGaussianDist(data, base*8, 20, 9); + complexGaussianDist(data, base*9, 20, 8); + complexGaussianDist(data, base*10, 30, 8); + complexGaussianDist(data, base*11, 30, 9); + complexGaussianDist(data, base*12, 30, 9); + complexGaussianDist(data, base*13, 30, 8); + complexGaussianDist(data, base*14, 30, 8); + complexGaussianDist(data, base*15, 30, 7); + complexGaussianDist(data, base*16, 30, 7); + complexGaussianDist(data, base*17, 30, 6); + + SF2Sample sample = newSimpleFFTSample(sf2, "Clarient", data, base); + SF2Layer layer = newLayer(sf2, "Clarient", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_timpani(SF2Soundbank sf2) + { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096*8; + double[] data = new double[2*fftlen]; + double base = 48; + complexGaussianDist(data, base*2, 0.2, 1); + complexGaussianDist(data, base*3, 0.2, 0.7); + complexGaussianDist(data, base*5, 10, 1); + complexGaussianDist(data, base*6, 9, 1); + complexGaussianDist(data, base*8, 15, 1); + complexGaussianDist(data, base*9, 18, 0.8); + complexGaussianDist(data, base*11, 21, 0.5); + complexGaussianDist(data, base*13, 28, 0.3); + complexGaussianDist(data, base*14, 22, 0.1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.5); + data = realPart(data); + + double d_len = data.length; + for (int i = 0; i < data.length; i++) + { + double g = (1.0 - (i/d_len)); + data[i] *= g*g; + } + fadeUp(data, 40); + datab = data; + } + + // Make treble part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5))*0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 1024*4; i < 2048*4; i++) + data[i] = 1.0 - (i-4096)/4096.0; + for (int i = 0; i < 300; i++) + { + double g = (1.0 - (i / 300.0)); + data[i] *= 1.0 + 20*g*g; + } + for (int i = 0; i < 24; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9998; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i]*0.02; + + normalize(datab, 0.9); + + SF2Sample sample = newSimpleDrumSample(sf2, "Timpani", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Timpani"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_melodic_toms(SF2Soundbank sf2) + { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + complexGaussianDist(data, 30, 0.5, 1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.8); + data = realPart(data); + + double d_len = data.length; + for (int i = 0; i < data.length; i++) + data[i] *= (1.0 - (i/d_len)); + datab = data; + } + + // Make treble part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5))*0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 1024*4; i < 2048*4; i++) + data[i] = 1.0 - (i-4096)/4096.0; + for (int i = 0; i < 200; i++) + { + double g = (1.0 - (i / 200.0)); + data[i] *= 1.0 + 20*g*g; + } + for (int i = 0; i < 30; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9996; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i]*0.5; + for (int i = 0; i < 5; i++) + datab[i] *= i/5.0; + + normalize(datab, 0.99); + + SF2Sample sample = newSimpleDrumSample(sf2, "Melodic Toms", datab); + sample.setOriginalPitch(63); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Melodic Toms"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + //region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_reverse_cymbal(SF2Soundbank sf2) + { + double datah[]; + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5)); + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 100; i++) + data[i] = 0; + + for (int i = 0; i < 512*2; i++) + { + double gain = (i / (512.0*2.0)); + data[i] = 1 - gain; + } + datah = data; + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Reverse Cymbal", datah, 100, 20); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Reverse Cymbal"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -200); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_snare_drum(SF2Soundbank sf2) + { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + complexGaussianDist(data, 24, 0.5, 1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.5); + data = realPart(data); + + double d_len = data.length; + for (int i = 0; i < data.length; i++) + data[i] *= (1.0 - (i/d_len)); + datab = data; + } + + // Make treble part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5))*0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 1024*4; i < 2048*4; i++) + data[i] = 1.0 - (i-4096)/4096.0; + for (int i = 0; i < 300; i++) + { + double g = (1.0 - (i / 300.0)); + data[i] *= 1.0 + 20*g*g; + } + for (int i = 0; i < 24; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9998; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i]; + for (int i = 0; i < 5; i++) + datab[i] *= i/5.0; + + SF2Sample sample = newSimpleDrumSample(sf2, "Snare Drum", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Snare Drum"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_bass_drum(SF2Soundbank sf2) + { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + complexGaussianDist(data, 1.8*5+1, 2, 1); + complexGaussianDist(data, 1.8*9+1, 2, 1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double d_len = data.length; + for (int i = 0; i < data.length; i++) + data[i] *= (1.0 - (i/d_len)); + datab = data; + } + + // Make treble part + { + int fftlen = 4096; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5))*0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 1024; i < 2048; i++) + data[i] = 1.0 - (i-1024)/1024.0; + for (int i = 0; i < 512; i++) + data[i] = 10*i/512.0; + for (int i = 0; i < 10; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.999; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i]*0.5; + for (int i = 0; i < 5; i++) + datab[i] *= i/5.0; + + SF2Sample sample = newSimpleDrumSample(sf2, "Bass Drum", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Bass Drum"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_tom(SF2Soundbank sf2) + { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + complexGaussianDist(data, 30, 0.5, 1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.8); + data = realPart(data); + + double d_len = data.length; + for (int i = 0; i < data.length; i++) + data[i] *= (1.0 - (i/d_len)); + datab = data; + } + + // Make treble part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5))*0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 1024*4; i < 2048*4; i++) + data[i] = 1.0 - (i-4096)/4096.0; + for (int i = 0; i < 200; i++) + { + double g = (1.0 - (i / 200.0)); + data[i] *= 1.0 + 20*g*g; + } + for (int i = 0; i < 30; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9996; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i]*0.5; + for (int i = 0; i < 5; i++) + datab[i] *= i/5.0; + + normalize(datab, 0.99); + + SF2Sample sample = newSimpleDrumSample(sf2, "Tom", datab); + sample.setOriginalPitch(50); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Tom"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + //region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_closed_hihat(SF2Soundbank sf2) + { + double datah[]; + + // Make treble part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5))*0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 1024*4; i < 2048*4; i++) + data[i] = 1.0 - (i-4096)/4096.0; + for (int i = 0; i < 2048; i++) + data[i] = 0.2 + 0.8*(i / 2048.0); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9996; + } + datah = data; + } + + for (int i = 0; i < 5; i++) + datah[i] *= i/5.0; + SF2Sample sample = newSimpleDrumSample(sf2, "Closed Hi-Hat", datah); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Closed Hi-Hat"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_EXCLUSIVECLASS, 1); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_open_hihat(SF2Soundbank sf2) + { + double datah[]; + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5)); + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 200; i++) + data[i] = 0; + for (int i = 0; i < 2048*4; i++) + { + double gain = (i / (2048.0*4.0)); + data[i] = gain; + } + datah = data; + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Open Hi-Hat", datah, 1000, 5); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Open Hi-Hat"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 1500); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1500); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_EXCLUSIVECLASS, 1); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_crash_cymbal(SF2Soundbank sf2) + { + double datah[]; + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5)); + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 100; i++) + data[i] = 0; + + for (int i = 0; i < 512*2; i++) + { + double gain = (i / (512.0*2.0)); + data[i] = gain; + } + datah = data; + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Crash Cymbal", datah, 1000, 5); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Crash Cymbal"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 1800); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1800); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_side_stick(SF2Soundbank sf2) + { + double datab[]; + + // Make treble part + { + int fftlen = 4096*4; + double[] data = new double[2*fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i+=2) + data[i] = (2.0*(random.nextDouble()-0.5))*0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen/2; i < data.length; i++) + data[i] = 0; + for (int i = 1024*4; i < 2048*4; i++) + data[i] = 1.0 - (i-4096)/4096.0; + for (int i = 0; i < 200; i++) + { + double g = (1.0 - (i / 200.0)); + data[i] *= 1.0 + 20*g*g; + } + for (int i = 0; i < 30; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9996; + } + datab = data; + } + + for (int i = 0; i < 10; i++) + datab[i] *= i/10.0; + + SF2Sample sample = newSimpleDrumSample(sf2, "Side Stick", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Side Stick"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -50); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + + } + + + public static SF2Sample newSimpleFFTSample(SF2Soundbank sf2, String name, double[] data, double base) + { + return newSimpleFFTSample(sf2, name, data, base, 10); + } + + public static SF2Sample newSimpleFFTSample(SF2Soundbank sf2, String name, double[] data, double base, int fadeuptime) + { + + int fftsize = data.length/2; + AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + double basefreq = (base / fftsize) * format.getSampleRate() * 0.5; + + randomPhase(data); + ifft(data); + data = realPart(data); + normalize(data, 0.9); + float[] fdata = toFloat(data); + fdata = loopExtend(fdata, fdata.length+512); + fadeUp(fdata, fadeuptime); + byte[] bdata = toBytes(fdata, format); + + /* + * Create SoundFont2 sample. + */ + SF2Sample sample = new SF2Sample(sf2); + sample.setName(name); + sample.setData(bdata); + sample.setStartLoop(256); + sample.setEndLoop(fftsize+256); + sample.setSampleRate((long) format.getSampleRate()); + double orgnote = (69 + 12) + (12*Math.log(basefreq/440.0)/Math.log(2)); + sample.setOriginalPitch((int)orgnote); + sample.setPitchCorrection((byte)(-(orgnote - (int)orgnote)*100.0)); + sf2.addResource(sample); + + return sample; + } + + public static SF2Sample newSimpleFFTSample_dist(SF2Soundbank sf2, String name, double[] data, double base, double preamp) + { + + int fftsize = data.length/2; + AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + double basefreq = (base / fftsize) * format.getSampleRate() * 0.5; + + randomPhase(data); + ifft(data); + data = realPart(data); + + for (int i = 0; i < data.length; i++) { + + data[i] = (1-Math.exp(-Math.abs(data[i]*preamp)))*Math.signum(data[i]); + } + + normalize(data, 0.9); + float[] fdata = toFloat(data); + fdata = loopExtend(fdata, fdata.length+512); + fadeUp(fdata, 80); + byte[] bdata = toBytes(fdata, format); + + /* + * Create SoundFont2 sample. + */ + SF2Sample sample = new SF2Sample(sf2); + sample.setName(name); + sample.setData(bdata); + sample.setStartLoop(256); + sample.setEndLoop(fftsize+256); + sample.setSampleRate((long) format.getSampleRate()); + double orgnote = (69 + 12) + (12*Math.log(basefreq/440.0)/Math.log(2)); + sample.setOriginalPitch((int)orgnote); + sample.setPitchCorrection((byte)(-(orgnote - (int)orgnote)*100.0)); + sf2.addResource(sample); + + return sample; + } + + + public static SF2Sample newSimpleDrumSample(SF2Soundbank sf2, String name, double[] data) + { + + int fftsize = data.length; + AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + byte[] bdata = toBytes(toFloat(realPart(data)), format); + + /* + * Create SoundFont2 sample. + */ + SF2Sample sample = new SF2Sample(sf2); + sample.setName(name); + sample.setData(bdata); + sample.setStartLoop(256); + sample.setEndLoop(fftsize+256); + sample.setSampleRate((long) format.getSampleRate()); + sample.setOriginalPitch(60); + sf2.addResource(sample); + + return sample; + } + + public static SF2Layer newLayer(SF2Soundbank sf2, String name, SF2Sample sample) + { + SF2LayerRegion region = new SF2LayerRegion(); + region.setSample(sample); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName(name); + layer.getRegions().add(region); + sf2.addResource(layer); + + return layer; + } + + public static SF2Instrument newInstrument(SF2Soundbank sf2, String name, Patch patch, SF2Layer... layers) + { + + /* + * Create SoundFont2 instrument. + */ + SF2Instrument ins = new SF2Instrument(sf2); + ins.setPatch(patch); + ins.setName(name); + sf2.addInstrument(ins); + + /* + * Create region for instrument. + */ + for (int i = 0; i < layers.length; i++) { + SF2InstrumentRegion insregion = new SF2InstrumentRegion(); + insregion.setLayer(layers[i]); + ins.getRegions().add(insregion); + } + + return ins; + } + + static public void ifft(double[] data) + { + new FFT(data.length/2, 1).transform(data); + } + + static public void fft(double[] data) + { + new FFT(data.length/2, -1).transform(data); + } + + public static void complexGaussianDist(double[] cdata, double m, double s, double v) + { + for (int x = 0; x < cdata.length/4; x++) { + cdata[x*2] += v * (1.0/(s*Math.sqrt(2*Math.PI)) * Math.exp( (-1.0/2.0) * Math.pow( (x - m)/s ,2.0)) ); + } + }; + + static public void randomPhase(double[] data) + { + for (int i = 0; i < data.length; i+=2) { + double phase = Math.random()*2*Math.PI; + double d = data[i]; + data[i] = Math.sin(phase)*d; + data[i+1] = Math.cos(phase)*d; + } + } + + static public void randomPhase(double[] data, Random random) + { + for (int i = 0; i < data.length; i+=2) { + double phase = random.nextDouble()*2*Math.PI; + double d = data[i]; + data[i] = Math.sin(phase)*d; + data[i+1] = Math.cos(phase)*d; + } + } + + static public void normalize(double[] data, double target) + { + double maxvalue = 0; + for (int i = 0; i < data.length; i++) { + if(data[i] > maxvalue) maxvalue = data[i]; + if(-data[i] > maxvalue) maxvalue = -data[i]; + } + if(maxvalue == 0) return; + double gain = target/maxvalue; + for (int i = 0; i < data.length; i++) + data[i] *= gain; + + } + + static public void normalize(float[] data, double target) + { + double maxvalue = 0.5; + for (int i = 0; i < data.length; i++) { + if(data[i*2] > maxvalue) maxvalue = data[i*2]; + if(-data[i*2] > maxvalue) maxvalue = -data[i*2]; + } + double gain = target/maxvalue; + for (int i = 0; i < data.length; i++) + data[i*2] *= gain; + + } + + static public double[] realPart(double[] in) + { + double[] out = new double[in.length/2]; + for (int i = 0; i < out.length; i++) { + out[i] = in[i*2]; + } + return out; + } + + static public double[] imgPart(double[] in) + { + double[] out = new double[in.length/2]; + for (int i = 0; i < out.length; i++) { + out[i] = in[i*2]; + } + return out; + } + + static public float[] toFloat(double[] in) + { + float[] out = new float[in.length]; + for (int i = 0; i < out.length; i++) { + out[i] = (float)in[i]; + } + return out; + } + + static public byte[] toBytes(float[] in, AudioFormat format) + { + byte[] out = new byte[in.length * format.getFrameSize()]; + return AudioFloatConverter.getConverter(format).toByteArray(in, out); + } + + static public void fadeUp(double[] data, int samples) + { + double dsamples = samples; + for (int i = 0; i < samples; i++) + data[i] *= i/dsamples; + } + + static public void fadeUp(float[] data, int samples) + { + double dsamples = samples; + for (int i = 0; i < samples; i++) + data[i] *= i/dsamples; + } + + static public double[] loopExtend(double[] data, int newsize) + { + double[] outdata = new double[newsize]; + int p_len = data.length; + int p_ps = 0; + for (int i = 0; i < outdata.length; i++) { + outdata[i] = data[p_ps]; + p_ps++; + if(p_ps == p_len) p_ps = 0; + } + return outdata; + } + + static public float[] loopExtend(float[] data, int newsize) + { + float[] outdata = new float[newsize]; + int p_len = data.length; + int p_ps = 0; + for (int i = 0; i < outdata.length; i++) { + outdata[i] = data[p_ps]; + p_ps++; + if(p_ps == p_len) p_ps = 0; + } + return outdata; + } + + + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/FFT.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/FFT.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,771 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * Fast Fourier Transformer. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public final class FFT { + + private double[] w; + + private int fftFrameSize; + + private int sign; + + private int[] bitm_array; + + private int fftFrameSize2; + + // Sign = -1 is FFT, 1 is IFFT (inverse FFT) + // Data = Interlaced double array to be transformed. + // The order is: real (sin), complex (cos) + // Framesize must be power of 2 + + public FFT(int fftFrameSize, int sign) { + w = computeTwiddleFactors(fftFrameSize, sign); + + this.fftFrameSize = fftFrameSize; + this.sign = sign; + fftFrameSize2 = fftFrameSize << 1; + + // Pre-process Bit-Reversal + bitm_array = new int[fftFrameSize2]; + for (int i = 2; i < fftFrameSize2; i += 2) { + int j; + int bitm; + for (bitm = 2, j = 0; bitm < fftFrameSize2; bitm <<= 1) { + if ((i & bitm) != 0) + j++; + j <<= 1; + } + bitm_array[i] = j; + } + + } + + public void transform(double[] data) { + bitreversal(data); + calc(fftFrameSize, data, sign, w); + } + + private final static double[] computeTwiddleFactors(int fftFrameSize, + int sign) { + + int imax = (int) (Math.log(fftFrameSize) / Math.log(2.)); + + double[] warray = new double[(fftFrameSize - 1) * 4]; + int w_index = 0; + + for (int i = 0, nstep = 2; i < imax; i++) { + + int jmax = nstep; + nstep <<= 1; + + double wr = 1.0; + double wi = 0.0; + + double arg = Math.PI / (jmax >> 1); + double wfr = Math.cos(arg); + double wfi = sign * Math.sin(arg); + + for (int j = 0; j < jmax; j += 2) { + + warray[w_index++] = wr; + warray[w_index++] = wi; + + double tempr = wr; + wr = tempr * wfr - wi * wfi; + wi = tempr * wfi + wi * wfr; + } + } + + // PRECOMPUTATION of wwr1, wwi1 for factor 4 Decomposition (3 * complex + // operators and 8 +/- complex operators) + { + + w_index = 0; + int w_index2 = warray.length >> 1; + for (int i = 0, nstep = 2; i < (imax - 1); i++) { + + int jmax = nstep; + nstep *= 2; + + int ii = w_index + jmax; + for (int j = 0; j < jmax; j += 2) { + + double wr = warray[w_index++]; + double wi = warray[w_index++]; + double wr1 = warray[ii++]; + double wi1 = warray[ii++]; + warray[w_index2++] = wr * wr1 - wi * wi1; + warray[w_index2++] = wr * wi1 + wi * wr1; + + } + } + + } + + return warray; + + } + + private final static void calc(int fftFrameSize, double[] data, int sign, + double[] w) + + { + + final int fftFrameSize2 = fftFrameSize << 1; + + int nstep = 2; + + if (nstep >= fftFrameSize2) + return; + int i = nstep - 2; + if (sign == -1) + calcF4F(fftFrameSize, data, i, nstep, w); + else + calcF4I(fftFrameSize, data, i, nstep, w); + + } + + private final static void calcF2E(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + int jmax = nstep; + nstep <<= 1; + for (int n = 0; n < jmax; n += 2) { + double wr = w[i++]; + double wi = w[i++]; + int m = n + jmax; + double datam_r = data[m]; + double datam_i = data[m + 1]; + double datan_r = data[n]; + double datan_i = data[n + 1]; + double tempr = datam_r * wr - datam_i * wi; + double tempi = datam_r * wi + datam_i * wr; + data[m] = datan_r - tempr; + data[m + 1] = datan_i - tempi; + data[n] = datan_r + tempr; + data[n + 1] = datan_i + tempi; + } + return; + + } + + // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- + // complex operators + + private final static void calcF4F(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; + // Factor-4 Decomposition + + int w_len = w.length >> 1; + while (nstep < fftFrameSize2) { + + if (nstep << 2 == fftFrameSize2) { + // Goto Factor-4 Final Decomposition + // calcF4E(data, i, nstep, -1, w); + calcF4FE(fftFrameSize, data, i, nstep, w); + return; + } + int jmax = nstep; + int nnstep = nstep << 1; + if (nnstep == fftFrameSize2) { + // Factor-4 Decomposition not possible + calcF2E(fftFrameSize, data, i, nstep, w); + return; + } + nstep <<= 2; + int ii = i + jmax; + int iii = i + w_len; + + { + i += 2; + ii += 2; + iii += 2; + + for (int n = 0; n < fftFrameSize2; n += nstep) { + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r; + double tempi = datam1_i; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r; + double n2w1i = datan2_i; + double m2ww1r = datam2_r; + double m2ww1i = datam2_i; + + tempr = m2ww1r - n2w1r; + tempi = m2ww1i - n2w1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + + } + for (int j = 2; j < jmax; j += 2) { + double wr = w[i++]; + double wi = w[i++]; + double wr1 = w[ii++]; + double wi1 = w[ii++]; + double wwr1 = w[iii++]; + double wwi1 = w[iii++]; + // double wwr1 = wr * wr1 - wi * wi1; // these numbers can be + // precomputed!!! + // double wwi1 = wr * wi1 + wi * wr1; + + for (int n = j; n < fftFrameSize2; n += nstep) { + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r * wr - datam1_i * wi; + double tempi = datam1_r * wi + datam1_i * wr; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r * wr1 - datan2_i * wi1; + double n2w1i = datan2_r * wi1 + datan2_i * wr1; + double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1; + double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1; + + tempr = m2ww1r - n2w1r; + tempi = m2ww1i - n2w1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + } + + i += jmax << 1; + + } + + calcF2E(fftFrameSize, data, i, nstep, w); + + } + + // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- + // complex operators + + private final static void calcF4I(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; + // Factor-4 Decomposition + + int w_len = w.length >> 1; + while (nstep < fftFrameSize2) { + + if (nstep << 2 == fftFrameSize2) { + // Goto Factor-4 Final Decomposition + // calcF4E(data, i, nstep, 1, w); + calcF4IE(fftFrameSize, data, i, nstep, w); + return; + } + int jmax = nstep; + int nnstep = nstep << 1; + if (nnstep == fftFrameSize2) { + // Factor-4 Decomposition not possible + calcF2E(fftFrameSize, data, i, nstep, w); + return; + } + nstep <<= 2; + int ii = i + jmax; + int iii = i + w_len; + { + i += 2; + ii += 2; + iii += 2; + + for (int n = 0; n < fftFrameSize2; n += nstep) { + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r; + double tempi = datam1_i; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r; + double n2w1i = datan2_i; + double m2ww1r = datam2_r; + double m2ww1i = datam2_i; + + tempr = n2w1r - m2ww1r; + tempi = n2w1i - m2ww1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + + } + for (int j = 2; j < jmax; j += 2) { + double wr = w[i++]; + double wi = w[i++]; + double wr1 = w[ii++]; + double wi1 = w[ii++]; + double wwr1 = w[iii++]; + double wwi1 = w[iii++]; + // double wwr1 = wr * wr1 - wi * wi1; // these numbers can be + // precomputed!!! + // double wwi1 = wr * wi1 + wi * wr1; + + for (int n = j; n < fftFrameSize2; n += nstep) { + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r * wr - datam1_i * wi; + double tempi = datam1_r * wi + datam1_i * wr; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r * wr1 - datan2_i * wi1; + double n2w1i = datan2_r * wi1 + datan2_i * wr1; + double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1; + double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1; + + tempr = n2w1r - m2ww1r; + tempi = n2w1i - m2ww1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + } + + i += jmax << 1; + + } + + calcF2E(fftFrameSize, data, i, nstep, w); + + } + + // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- + // complex operators + + private final static void calcF4FE(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; + // Factor-4 Decomposition + + int w_len = w.length >> 1; + while (nstep < fftFrameSize2) { + + int jmax = nstep; + int nnstep = nstep << 1; + if (nnstep == fftFrameSize2) { + // Factor-4 Decomposition not possible + calcF2E(fftFrameSize, data, i, nstep, w); + return; + } + nstep <<= 2; + int ii = i + jmax; + int iii = i + w_len; + for (int n = 0; n < jmax; n += 2) { + double wr = w[i++]; + double wi = w[i++]; + double wr1 = w[ii++]; + double wi1 = w[ii++]; + double wwr1 = w[iii++]; + double wwi1 = w[iii++]; + // double wwr1 = wr * wr1 - wi * wi1; // these numbers can be + // precomputed!!! + // double wwi1 = wr * wi1 + wi * wr1; + + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r * wr - datam1_i * wi; + double tempi = datam1_r * wi + datam1_i * wr; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r * wr1 - datan2_i * wi1; + double n2w1i = datan2_r * wi1 + datan2_i * wr1; + double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1; + double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1; + + tempr = m2ww1r - n2w1r; + tempi = m2ww1i - n2w1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + + i += jmax << 1; + + } + + } + + // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- + // complex operators + + private final static void calcF4IE(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; + // Factor-4 Decomposition + + int w_len = w.length >> 1; + while (nstep < fftFrameSize2) { + + int jmax = nstep; + int nnstep = nstep << 1; + if (nnstep == fftFrameSize2) { + // Factor-4 Decomposition not possible + calcF2E(fftFrameSize, data, i, nstep, w); + return; + } + nstep <<= 2; + int ii = i + jmax; + int iii = i + w_len; + for (int n = 0; n < jmax; n += 2) { + double wr = w[i++]; + double wi = w[i++]; + double wr1 = w[ii++]; + double wi1 = w[ii++]; + double wwr1 = w[iii++]; + double wwi1 = w[iii++]; + // double wwr1 = wr * wr1 - wi * wi1; // these numbers can be + // precomputed!!! + // double wwi1 = wr * wi1 + wi * wr1; + + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r * wr - datam1_i * wi; + double tempi = datam1_r * wi + datam1_i * wr; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r * wr1 - datan2_i * wi1; + double n2w1i = datan2_r * wi1 + datan2_i * wr1; + double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1; + double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1; + + tempr = n2w1r - m2ww1r; + tempi = n2w1i - m2ww1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + + i += jmax << 1; + + } + + } + + private final void bitreversal(double[] data) { + if (fftFrameSize < 4) + return; + + int inverse = fftFrameSize2 - 2; + for (int i = 0; i < fftFrameSize; i += 4) { + int j = bitm_array[i]; + + // Performing Bit-Reversal, even v.s. even, O(2N) + if (i < j) { + + int n = i; + int m = j; + + // COMPLEX: SWAP(data[n], data[m]) + // Real Part + double tempr = data[n]; + data[n] = data[m]; + data[m] = tempr; + // Imagery Part + n++; + m++; + double tempi = data[n]; + data[n] = data[m]; + data[m] = tempi; + + n = inverse - i; + m = inverse - j; + + // COMPLEX: SWAP(data[n], data[m]) + // Real Part + tempr = data[n]; + data[n] = data[m]; + data[m] = tempr; + // Imagery Part + n++; + m++; + tempi = data[n]; + data[n] = data[m]; + data[m] = tempi; + } + + // Performing Bit-Reversal, odd v.s. even, O(N) + + int m = j + fftFrameSize; // bitm_array[i+2]; + // COMPLEX: SWAP(data[n], data[m]) + // Real Part + int n = i + 2; + double tempr = data[n]; + data[n] = data[m]; + data[m] = tempr; + // Imagery Part + n++; + m++; + double tempi = data[n]; + data[n] = data[m]; + data[m] = tempi; + } + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/InvalidDataException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/InvalidDataException.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; + +/** + * This exception is used when a file + * contains illegal or unexpected data. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class InvalidDataException extends IOException { + + private static final long serialVersionUID = 1L; + + public InvalidDataException() { + super("Invalid Data!"); + } + + public InvalidDataException(String s) { + super(s); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/InvalidFormatException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/InvalidFormatException.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * This exception is used when a reader + * is used to read file of a format it doesn't unterstand + * or support. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class InvalidFormatException extends InvalidDataException { + + private static final long serialVersionUID = 1L; + + public InvalidFormatException() { + super("Invalid format!"); + } + + public InvalidFormatException(String s) { + super(s); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/JARSoundbankReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/JARSoundbankReader.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,118 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Soundbank; +import javax.sound.midi.spi.SoundbankReader; + +/** + * JarSoundbankReader is ued to read sounbank object from jar files. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class JARSoundbankReader extends SoundbankReader { + + public boolean isZIP(URL url) + { + boolean ok = false; + try + { + InputStream stream = url.openStream(); + try + { + byte[] buff = new byte[4]; + ok = stream.read(buff) == 4; + if(ok) + { + ok = (buff[0] == 0x50 && + buff[1] == 0x4b && + buff[2] == 0x03 && + buff[3] == 0x04); + } + } + finally + { + stream.close(); + } + } + catch(IOException e) + { + } + return ok; + } + + public Soundbank getSoundbank(URL url) throws InvalidMidiDataException, IOException { + if(!isZIP(url)) return null; + ArrayList soundbanks = new ArrayList(); + URLClassLoader ucl = URLClassLoader.newInstance(new URL[] {url}); + InputStream stream = ucl.getResourceAsStream("META-INF/services/javax.sound.midi.Soundbank"); + if(stream == null) return null; + BufferedReader r = new BufferedReader(new InputStreamReader(stream)); + String line = r.readLine(); + while (line != null) { + if (!line.startsWith("#")) { + try { + Class c = Class.forName(line.trim(), true, ucl); + Object o = c.newInstance(); + if (o instanceof Soundbank) { + soundbanks.add((Soundbank)o); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + line = r.readLine(); + } + stream.close(); + if(soundbanks.size() == 0) return null; + if(soundbanks.size() == 1) return soundbanks.get(0); + SimpleSoundbank sbk = new SimpleSoundbank(); + for (Soundbank soundbank : soundbanks) + sbk.addAllInstruments(soundbank); + return sbk; + } + + public Soundbank getSoundbank(InputStream stream) throws InvalidMidiDataException, IOException { + return null; + } + + public Soundbank getSoundbank(File file) throws InvalidMidiDataException, IOException { + return getSoundbank(file.toURI().toURL()); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/LICENSE Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,347 @@ +The GNU General Public License (GPL) + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you +can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must give the recipients all the rights that you have. You must +make sure that they, too, receive or can get the source code. And you must +show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program proprietary. +To prevent this, we have made it clear that any patent must be licensed for +everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms of +this General Public License. The "Program", below, refers to any such program +or work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included +without limitation in the term "modification".) Each licensee is addressed as +"you". + +Activities other than copying, distribution and modification are not covered by +this License; they are outside its scope. The act of running the Program is +not restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by +running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as +you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this License +and to the absence of any warranty; and give any other recipients of the +Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may +at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus +forming a work based on the Program, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all of +these conditions: + + a) You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or + in part contains or is derived from the Program or any part thereof, to be + licensed as a whole at no charge to all third parties under the terms of + this License. + + c) If the modified program normally reads commands interactively when run, + you must cause it, when started running for such interactive use in the + most ordinary way, to print or display an announcement including an + appropriate copyright notice and a notice that there is no warranty (or + else, saying that you provide a warranty) and that users may redistribute + the program under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the Program is + not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, and +its terms, do not apply to those sections when you distribute them as separate +works. But when you distribute the same sections as part of a whole which is a +work based on the Program, the distribution of the whole must be on the terms +of this License, whose permissions for other licensees extend to the entire +whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on +the Program. + +In addition, mere aggregation of another work not based on the Program with the +Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 and +2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and 2 above + on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to + give any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed only + for noncommercial distribution and only if you received the program in + object code or executable form with such an offer, in accord with + Subsection b above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all +the source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and installation +of the executable. However, as a special exception, the source code +distributed need not include anything that is normally distributed (in either +source or binary form) with the major components (compiler, kernel, and so on) +of the operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the source +code from the same place counts as distribution of the source code, even though +third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, or +rights, from you under this License will not have their licenses terminated so +long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. +However, nothing else grants you permission to modify or distribute the Program +or its derivative works. These actions are prohibited by law if you do not +accept this License. Therefore, by modifying or distributing the Program (or +any work based on the Program), you indicate your acceptance of this License to +do so, and all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor to +copy, distribute or modify the Program subject to these terms and conditions. +You may not impose any further restrictions on the recipients' exercise of the +rights granted herein. You are not responsible for enforcing compliance by +third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), conditions +are imposed on you (whether by court order, agreement or otherwise) that +contradict the conditions of this License, they do not excuse you from the +conditions of this License. If you cannot distribute so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not distribute the Program at all. +For example, if a patent license would not permit royalty-free redistribution +of the Program by all those who receive copies directly or indirectly through +you, then the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and +the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or +other property right claims or to contest validity of any such claims; this +section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many +people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose that +choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. In +such case, this License incorporates the limitation as if written in the body +of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the +General Public License from time to time. Such new versions will be similar in +spirit to the present version, but may differ in detail to address new problems +or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any later +version", you have the option of following the terms and conditions either of +that version or of any later version published by the Free Software Foundation. +If the Program does not specify a version number of this License, you may +choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE +PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + One line to give the program's name and a brief idea of what it does. + + Copyright (C) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program 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 for + more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it +starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes + with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free + software, and you are welcome to redistribute it under certain conditions; + type 'show c' for details. + +The hypothetical commands 'show w' and 'show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than 'show w' and 'show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. Here +is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + 'Gnomovision' (which makes passes at compilers) written by James Hacker. + + signature of Ty Coon, 1 April 1989 + + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General Public +License instead of this License. + + +"CLASSPATH" EXCEPTION TO THE GPL + +Certain source files distributed by Sun Microsystems, Inc. are subject to +the following clarification and special exception to the GPL, but only where +Sun has expressly included in the particular source file's header the words +"Sun designates this particular file as subject to the "Classpath" exception +as provided by Sun in the LICENSE file that accompanied this code." + + Linking this library statically or dynamically with other modules is making + a combined work based on this library. Thus, the terms and conditions of + the GNU General Public License cover the whole combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules, + and to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent module, + the terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. If + you modify this library, you may extend this exception to your version of + the library, but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelAbstractChannelMixer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelAbstractChannelMixer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,130 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * ModelAbstractChannelMixer is ready for use class for implement ModelChannelMixer interface. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public abstract class ModelAbstractChannelMixer implements ModelChannelMixer { + + public abstract boolean process(float[][] buffer, int offset, int len); + + public abstract void stop(); + + public void allNotesOff() { + } + + public void allSoundOff() { + } + + public void controlChange(int controller, int value) { + } + + public int getChannelPressure() { + return 0; + } + + public int getController(int controller) { + return 0; + } + + public boolean getMono() { + return false; + } + + public boolean getMute() { + return false; + } + + public boolean getOmni() { + return false; + } + + public int getPitchBend() { + return 0; + } + + public int getPolyPressure(int noteNumber) { + return 0; + } + + public int getProgram() { + return 0; + } + + public boolean getSolo() { + return false; + } + + public boolean localControl(boolean on) { + return false; + } + + public void noteOff(int noteNumber) { + } + + public void noteOff(int noteNumber, int velocity) { + } + + public void noteOn(int noteNumber, int velocity) { + } + + public void programChange(int program) { + } + + public void programChange(int bank, int program) { + } + + public void resetAllControllers() { + } + + public void setChannelPressure(int pressure) { + } + + public void setMono(boolean on) { + } + + public void setMute(boolean mute) { + } + + public void setOmni(boolean on) { + } + + public void setPitchBend(int bend) { + } + + public void setPolyPressure(int noteNumber, int pressure) { + } + + public void setSolo(boolean soloState) { + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelAbstractOscillator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelAbstractOscillator.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,205 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.midi.VoiceStatus; + +/** + * + * A abstract class used to simplify creating custom ModelOscillator. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public abstract class ModelAbstractOscillator implements ModelOscillator, ModelOscillatorStream, Soundbank { + + protected float pitch = 6000; + protected float samplerate; + protected MidiChannel channel; + protected VoiceStatus voice; + protected int noteNumber; + protected int velocity; + protected boolean on = false; + + public void init() { + } + + public void close() throws IOException { + } + + public void noteOff(int velocity) { + on = false; + } + + public void noteOn(MidiChannel channel, VoiceStatus voice, int noteNumber, int velocity) { + this.channel = channel; + this.voice = voice; + this.noteNumber = noteNumber; + this.velocity = velocity; + on = true; + } + + public int read(float[][] buffer, int offset, int len) throws IOException + { + return -1; + } + + public MidiChannel getChannel() { + return channel; + } + + public VoiceStatus getVoice() { + return voice; + } + + public int getNoteNumber() { + return noteNumber; + } + + public int getVelocity() { + return velocity; + } + + public boolean isOn() { + return on; + } + + public void setPitch(float pitch) { + this.pitch = pitch; + } + + public float getPitch() + { + return pitch; + } + + public void setSampleRate(float samplerate) { + this.samplerate = samplerate; + } + + public float getSampleRate() + { + return samplerate; + } + + public float getAttenuation() { + return 0; + } + + public int getChannels() { + return 1; + } + + public String getName() { + return getClass().getName(); + } + + public Patch getPatch() { + return new Patch(0,0); + } + + public ModelOscillatorStream open(float samplerate) { + ModelAbstractOscillator oscs; + try { + oscs = this.getClass().newInstance(); + } catch (InstantiationException e) { + throw new IllegalArgumentException(e.getMessage()); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e.getMessage()); + } + oscs.setSampleRate(samplerate); + oscs.init(); + return oscs; + } + + public ModelPerformer getPerformer() + { + // Create performer for my custom oscillirator + ModelPerformer performer = new ModelPerformer(); + performer.getOscillators().add(this); + return performer; + + } + + public ModelInstrument getInstrument() + { + // Create Instrument object around my performer + SimpleInstrument ins = new SimpleInstrument(); + ins.setName(getName()); + ins.add(getPerformer()); + ins.setPatch(getPatch()); + return ins; + + } + + public Soundbank getSoundBank() + { + // Create Soundbank object around the instrument + SimpleSoundbank sbk = new SimpleSoundbank(); + sbk.addInstrument(getInstrument()); + return sbk; + } + + public String getDescription() { + return getName(); + } + + public Instrument getInstrument(Patch patch) { + Instrument ins = getInstrument(); + Patch p = ins.getPatch(); + if(p.getBank() != patch.getBank()) return null; + if(p.getProgram() != patch.getProgram()) return null; + if(p instanceof ModelPatch && patch instanceof ModelPatch) + if( ((ModelPatch)p).isPercussion() != ((ModelPatch)patch).isPercussion()) + return null; + return ins; + } + + public Instrument[] getInstruments() { + return new Instrument[] { getInstrument() }; + } + + public SoundbankResource[] getResources() { + return new SoundbankResource[0]; + } + + public String getVendor() { + return null; + } + + public String getVersion() { + return null; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,347 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.util.Collection; + +/** + * + * This class is a pointer to a binary array either in memory or on disk. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelByteBuffer { + + private ModelByteBuffer root = this; + private File file; + private long fileoffset; + private byte[] buffer; + private long offset; + private long len; + + private class RandomFileInputStream extends InputStream + { + private RandomAccessFile raf; + private long left; + private long mark = 0; + private long markleft = 0; + + public RandomFileInputStream() throws IOException + { + raf = new RandomAccessFile(root.file, "r"); + raf.seek(root.fileoffset + arrayOffset()); + left = capacity(); + } + + public int available() throws IOException { + if(left > Integer.MAX_VALUE) return Integer.MAX_VALUE; + return (int)left; + } + + public synchronized void mark(int readlimit) { + try { + mark = raf.getFilePointer(); + markleft = left; + } catch (IOException e) { + e.printStackTrace(); + } + } + + public boolean markSupported() { + return true; + } + + public synchronized void reset() throws IOException { + raf.seek(mark); + left = markleft; + } + + public long skip(long n) throws IOException { + if(n > left) n = left; + n = super.skip(n); + if(n == -1) return -1; + left -= n; + return n; + } + + public int read(byte b[], int off, int len) throws IOException { + if(len > left) len = (int)left; + if(left == 0) + return -1; + len = raf.read(b, off, len); + if(len == -1) + return -1; + left -= len; + return len; + } + + public int read(byte[] b) throws IOException { + if(len > left) len = (int)left; + if(left == 0) + return -1; + int len = raf.read(b); + if(len == -1) + return -1; + left -= len; + return len; } + + public int read() throws IOException { + if(len == 0) + return -1; + int b = raf.read(); + if(b == -1) + return -1; + len--; + return b; + } + + public void close() throws IOException + { + raf.close(); + } + + } + + private ModelByteBuffer(ModelByteBuffer parent, long beginIndex, long endIndex, boolean independent) + { + this.root = parent.root; + this.offset = 0; + this.len = parent.len; + if(beginIndex < 0) beginIndex = 0; + if(beginIndex > len) beginIndex = len; + if(endIndex < 0) endIndex = 0; + if(endIndex > len) endIndex = len; + if(beginIndex > endIndex) beginIndex = endIndex; + offset = beginIndex; + len = endIndex - beginIndex; + if(independent) + { + buffer = root.buffer; + if(root.file != null) + { + file = root.file; + fileoffset = root.fileoffset + arrayOffset(); + offset = 0; + } + else + offset = arrayOffset(); + root = this; + } + } + + public ModelByteBuffer(byte[] buffer) + { + this.buffer = buffer; + this.offset = 0; + this.len = buffer.length; + } + + public ModelByteBuffer(byte[] buffer, int offset, int len) + { + this.buffer = buffer; + this.offset = offset; + this.len = len; + } + + public ModelByteBuffer(File file) + { + this.file = file; + this.fileoffset = 0; + this.len = file.length(); + } + + public ModelByteBuffer(File file, long offset, long len) + { + this.file = file; + this.fileoffset = offset; + this.len = len; + } + + public void writeTo(OutputStream out) throws IOException + { + if(root.file != null && root.buffer == null) + { + InputStream is = getInputStream(); + byte[] buff = new byte[1024]; + int ret; + while((ret = is.read(buff)) != -1) + out.write(buff, 0, ret); + } + else + out.write(array(), (int)arrayOffset(), (int)capacity()); + } + + public InputStream getInputStream() + { + if(root.file != null && root.buffer == null) + try { + return new RandomFileInputStream(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + return new ByteArrayInputStream(array(), (int)arrayOffset(), (int)capacity()); + } + + public ModelByteBuffer subbuffer(long beginIndex) + { + return subbuffer(beginIndex, capacity()); + } + + public ModelByteBuffer subbuffer(long beginIndex, long endIndex) + { + return subbuffer(beginIndex, endIndex, false); + } + + public ModelByteBuffer subbuffer(long beginIndex, long endIndex, boolean independent) + { + return new ModelByteBuffer(this, beginIndex, endIndex, independent); + } + + public byte[] array() + { + return root.buffer; + } + + public long arrayOffset() + { + if(root != this) + return root.arrayOffset() + offset; + return offset; + } + + public long capacity() + { + return len; + } + + public ModelByteBuffer getRoot() + { + return root; + } + + public File getFile() + { + return file; + } + + public long getFilePointer() + { + return fileoffset; + } + + public static void loadAll(Collection col) throws IOException + { + File selfile = null; + RandomAccessFile raf = null; + try + { + for(ModelByteBuffer mbuff : col) + { + mbuff = mbuff.root; + if(mbuff.file == null) continue; + if(mbuff.buffer != null) continue; + if(selfile == null || !selfile.equals(mbuff.file)) + { + if(raf != null) + { + raf.close(); + raf = null; + } + selfile = mbuff.file; + raf = new RandomAccessFile(mbuff.file, "r"); + } + raf.seek(mbuff.fileoffset); + byte[] buffer = new byte[(int)mbuff.capacity()]; + + int read = 0; + int avail = buffer.length; + while(read != avail) + { + if(avail - read > 65536) + { + raf.read(buffer, read, 65536); + read += 65536; + } + else + { + raf.read(buffer, read, avail - read); + read = avail; + } + + } + + mbuff.buffer = buffer; + mbuff.offset = 0; + } + } + finally + { + if(raf != null) + raf.close(); + } + } + + public void load() throws IOException + { + if(root != this) + { + root.load(); + return; + } + if(buffer != null) + return; + if(file == null) + throw new IllegalStateException("No file associated with this ByteBuffer!"); + + InputStream is = getInputStream(); + buffer = new byte[(int)capacity()]; + offset = 0; + is.read(buffer); + is.close(); + + } + + public void unload() + { + if(root != this) + { + root.unload(); + return; + } + if(file == null) + throw new IllegalStateException("No file associated with this ByteBuffer!"); + root.buffer = null; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,296 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFormat.Encoding; + +/** + * + * Wavetable oscillator for pre-loaded data. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelByteBufferWavetable implements ModelWavetable +{ + private class Buffer8PlusInputStream extends InputStream + { + + private boolean bigendian; + private int framesize_pc; + + + int pos = 0; + int pos2 = 0; + + int markpos = 0; + int markpos2 = 0; + + public Buffer8PlusInputStream() + { + framesize_pc = format.getFrameSize() / format.getChannels(); + bigendian = format.isBigEndian(); + } + + public int read(byte[] b, int off, int len) throws IOException { + int avail = available(); + if(avail <= 0) return -1; + if(len > avail) len = avail; + byte[] buff1 = buffer.array(); + byte[] buff2 = buffer8.array(); + pos += buffer.arrayOffset(); + pos2 += buffer8.arrayOffset(); + if(bigendian) + for (int i = 0; i < len; i+=(framesize_pc+1)) { + System.arraycopy(buff1, pos, b, i, framesize_pc); + System.arraycopy(buff2, pos2, b, i + framesize_pc, 1); + pos += framesize_pc; + pos2 += 1; + } + else + for (int i = 0; i < len; i+=(framesize_pc+1)) { + System.arraycopy(buff2, pos2, b, i, 1); + System.arraycopy(buff1, pos, b, i+1, framesize_pc); + pos += framesize_pc; + pos2 += 1; + } + pos -= buffer.arrayOffset(); + pos2 -= buffer8.arrayOffset(); + return len; + } + public long skip(long n) throws IOException { + int avail = available(); + if(avail <= 0) return -1; + if(n > avail) n = avail; + pos += (n / (framesize_pc+1)) * (framesize_pc); + pos2 += n / (framesize_pc+1); + return super.skip(n); + } + + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + public int read() throws IOException { + byte[] b = new byte[1]; + int ret = read(b, 0, 1); + if(ret == -1) return -1; + return 0 & 0xFF; + } + + public boolean markSupported() { + return true; + } + + public int available() throws IOException { + return (int)buffer.capacity() + (int)buffer8.capacity() - pos - pos2; + } + + public synchronized void mark(int readlimit) { + markpos = pos; + markpos2 = pos2; + } + + public synchronized void reset() throws IOException { + pos = markpos; + pos2 = markpos2; + + } + + } + + private float loopStart = -1; + private float loopLength = -1; + private ModelByteBuffer buffer; + private ModelByteBuffer buffer8 = null; + private AudioFormat format = null; + private float pitchcorrection = 0; + private float attenuation = 0; + private int loopType = LOOP_TYPE_OFF; + + public ModelByteBufferWavetable(ModelByteBuffer buffer) + { + this.buffer = buffer; + } + + public ModelByteBufferWavetable(ModelByteBuffer buffer, float pitchcorrection) + { + this.buffer = buffer; + this.pitchcorrection = pitchcorrection; + } + + public ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format) + { + this.format = format; + this.buffer = buffer; + } + + public ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format, float pitchcorrection) + { + this.format = format; + this.buffer = buffer; + this.pitchcorrection = pitchcorrection; + } + + public void set8BitExtensionBuffer(ModelByteBuffer buffer) + { + buffer8 = buffer; + } + + public ModelByteBuffer get8BitExtensionBuffer() + { + return buffer8; + } + + public ModelByteBuffer getBuffer() + { + return buffer; + } + + public AudioFormat getFormat() + { + if(format == null) + { + if(buffer == null) return null; + InputStream is = buffer.getInputStream(); + AudioFormat format = null; + try + { + format = AudioSystem.getAudioFileFormat(is).getFormat(); + } + catch(Exception e) + { + e.printStackTrace(); + } + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return format; + } + return format; + } + + public AudioFloatInputStream openStream() + { + if(buffer == null) return null; + if(format == null) + { + InputStream is = buffer.getInputStream(); + AudioInputStream ais = null; + try + { + ais = AudioSystem.getAudioInputStream(is); + } + catch(Exception e) + { + e.printStackTrace(); + } + return AudioFloatInputStream.getInputStream(ais); + } + if(buffer.array() == null) + return AudioFloatInputStream.getInputStream(new AudioInputStream(buffer.getInputStream(), format, buffer.capacity())); + if(buffer8 != null) + { + if(format.getEncoding().equals(Encoding.PCM_SIGNED) + || format.getEncoding().equals(Encoding.PCM_UNSIGNED)) + { + InputStream is = new Buffer8PlusInputStream(); + AudioFormat format2 = new AudioFormat( + format.getEncoding(), + format.getSampleRate(), + format.getSampleSizeInBits()+8, + format.getChannels(), + format.getFrameSize()+(1*format.getChannels()), + format.getFrameRate(), + format.isBigEndian()); + + AudioInputStream ais = new AudioInputStream(is, format2, buffer.capacity() / format.getFrameSize()); + return AudioFloatInputStream.getInputStream(ais); + } + } + return AudioFloatInputStream.getInputStream(format, buffer.array(), (int)buffer.arrayOffset(), (int)buffer.capacity()); + + } + + public int getChannels() + { + return getFormat().getChannels(); + } + + public ModelOscillatorStream open(float samplerate) { + // ModelWavetableOscillator doesn't support ModelOscillatorStream + return null; + } + + // attenuation is in cB + public float getAttenuation() { + return attenuation; + } + // attenuation is in cB + public void setAttenuation(float attenuation) { + this.attenuation = attenuation; + } + + public float getLoopLength() { + return loopLength; + } + + public void setLoopLength(float loopLength) { + this.loopLength = loopLength; + } + + public float getLoopStart() { + return loopStart; + } + + public void setLoopStart(float loopStart) { + this.loopStart = loopStart; + } + + public void setLoopType(int loopType) { + this.loopType = loopType; + } + + public int getLoopType() { + return loopType; + } + + public float getPitchcorrection() { + return pitchcorrection; + } + + public void setPitchcorrection(float pitchcorrection) { + this.pitchcorrection = pitchcorrection; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelChannelMixer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelChannelMixer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import javax.sound.midi.MidiChannel; + +/** + * + * ModelChannelMixer is used to process channel voice mix output + * before going to master output.
+ * It can be used to:
+ *

    + *
  • Implement non-voice oriented instruments.
  • + *
  • Add insert effect to instruments for example: distortion effect.
  • + * + *

    + * Warning! Classes that implements ModelChannelMixer must be thread-safe. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface ModelChannelMixer extends MidiChannel { + + // Used to process input audio from voices mix. + public boolean process(float[][] buffer, int offset, int len); + + // Is used to trigger that this mixer is not be used + // and it should fade out. + public void stop(); + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelConnectionBlock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelConnectionBlock.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,149 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * Connection blocks are used to connect source variable + * to a destination variable. + * For example Note On velocity can be connected to output gain. + * In DLS this is called articulator and in SoundFonts (SF2) a modulator. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelConnectionBlock { + + // + // source1 * source2 * scale -> destination + // + + private final static ModelSource[] no_sources = new ModelSource[0]; + + private ModelSource[] sources = no_sources; + private double scale = 1; + private ModelDestination destination; + + public ModelConnectionBlock() + { + } + public ModelConnectionBlock(double scale, ModelDestination destination) + { + this.scale = scale; + this.destination = destination; + } + public ModelConnectionBlock(ModelSource source, ModelDestination destination) + { + if(source != null) + { + this.sources = new ModelSource[1]; + this.sources[0] = source; + } + this.destination = destination; + } + public ModelConnectionBlock(ModelSource source, double scale, ModelDestination destination) + { + if(source != null) + { + this.sources = new ModelSource[1]; + this.sources[0] = source; + } + this.scale = scale; + this.destination = destination; + } + public ModelConnectionBlock(ModelSource source, ModelSource control, ModelDestination destination) + { + if(source != null) + { + if(control == null) + { + this.sources = new ModelSource[1]; + this.sources[0] = source; + } + else + { + this.sources = new ModelSource[2]; + this.sources[0] = source; + this.sources[1] = control; + } + } + this.destination = destination; + } + public ModelConnectionBlock(ModelSource source, ModelSource control, double scale, ModelDestination destination) + { + if(source != null) + { + if(control == null) + { + this.sources = new ModelSource[1]; + this.sources[0] = source; + } + else + { + this.sources = new ModelSource[2]; + this.sources[0] = source; + this.sources[1] = control; + } + } + this.scale = scale; + this.destination = destination; + } + + public ModelDestination getDestination() { + return destination; + } + + public void setDestination(ModelDestination destination) { + this.destination = destination; + } + + public double getScale() { + return scale; + } + + public void setScale(double scale) { + this.scale = scale; + } + + public ModelSource[] getSources() { + return sources; + } + + public void setSources(ModelSource[] source) { + this.sources = source; + } + + public void addSource(ModelSource source) { + ModelSource[] oldsources = sources; + sources = new ModelSource[oldsources.length + 1]; + for (int i = 0; i < oldsources.length; i++) { + sources[i] = oldsources[i]; + } + sources[sources.length - 1] = source; + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDestination.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDestination.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,99 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * This class is used to identify destinations in connection blocks, see ModelConnectionBlock. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelDestination { + + public static final ModelIdentifier DESTINATION_NONE = null; + + public static final ModelIdentifier DESTINATION_KEYNUMBER = new ModelIdentifier("noteon","keynumber"); + public static final ModelIdentifier DESTINATION_VELOCITY = new ModelIdentifier("noteon","velocity"); + + public static final ModelIdentifier DESTINATION_PITCH = new ModelIdentifier("osc","pitch"); // cent + + public static final ModelIdentifier DESTINATION_GAIN = new ModelIdentifier("mixer","gain"); // cB + public static final ModelIdentifier DESTINATION_PAN = new ModelIdentifier("mixer","pan"); // 0.1 % + public static final ModelIdentifier DESTINATION_REVERB = new ModelIdentifier("mixer","reverb"); // 0.1 % + public static final ModelIdentifier DESTINATION_CHORUS = new ModelIdentifier("mixer","chorus"); // 0.1 % + + public static final ModelIdentifier DESTINATION_LFO1_DELAY = new ModelIdentifier("lfo","delay",0); // timecent + public static final ModelIdentifier DESTINATION_LFO1_FREQ = new ModelIdentifier("lfo","freq",0); // cent + + public static final ModelIdentifier DESTINATION_LFO2_DELAY = new ModelIdentifier("lfo","delay",1); // timecent + public static final ModelIdentifier DESTINATION_LFO2_FREQ = new ModelIdentifier("lfo","freq",1); // cent + + public static final ModelIdentifier DESTINATION_EG1_DELAY = new ModelIdentifier("eg","delay",0); // timecent + public static final ModelIdentifier DESTINATION_EG1_ATTACK = new ModelIdentifier("eg","attack",0); // timecent + public static final ModelIdentifier DESTINATION_EG1_HOLD = new ModelIdentifier("eg","hold",0); // timecent + public static final ModelIdentifier DESTINATION_EG1_DECAY = new ModelIdentifier("eg","decay",0); // timecent + public static final ModelIdentifier DESTINATION_EG1_SUSTAIN = new ModelIdentifier("eg","sustain",0); // 0.1 % ( I want this to be value not %) + public static final ModelIdentifier DESTINATION_EG1_RELEASE = new ModelIdentifier("eg","release",0); // timecent + public static final ModelIdentifier DESTINATION_EG1_SHUTDOWN = new ModelIdentifier("eg","shutdown",0); // timecent + + public static final ModelIdentifier DESTINATION_EG2_DELAY = new ModelIdentifier("eg","delay",1); // timecent + public static final ModelIdentifier DESTINATION_EG2_ATTACK = new ModelIdentifier("eg","attack",1); // timecent + public static final ModelIdentifier DESTINATION_EG2_HOLD = new ModelIdentifier("eg","hold",1); // 0.1 % + public static final ModelIdentifier DESTINATION_EG2_DECAY = new ModelIdentifier("eg","decay",1); // timecent + public static final ModelIdentifier DESTINATION_EG2_SUSTAIN = new ModelIdentifier("eg","sustain",1); // 0.1 % ( I want this to be value not %) + public static final ModelIdentifier DESTINATION_EG2_RELEASE = new ModelIdentifier("eg","release",1); // timecent + public static final ModelIdentifier DESTINATION_EG2_SHUTDOWN = new ModelIdentifier("eg","shutdown",1); // timecent + + public static final ModelIdentifier DESTINATION_FILTER_FREQ = new ModelIdentifier("filter","freq",0); // cent + public static final ModelIdentifier DESTINATION_FILTER_Q = new ModelIdentifier("filter","q",0); // cB + + private ModelIdentifier destination = DESTINATION_NONE; + private ModelTransform transform = new ModelStandardTransform(); + + public ModelDestination() + { + } + + public ModelDestination(ModelIdentifier id) + { + destination = id; + } + + public ModelIdentifier getIdentifier() { + return destination; + } + public void setIdentifier(ModelIdentifier destination) { + this.destination = destination; + } + public ModelTransform getTransform() { + return transform; + } + public void setTransform(ModelTransform transform) { + this.transform = transform; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDirectedPlayer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDirectedPlayer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * ModelDirectedPlayer is the one who is directed by ModelDirector + * to play ModelPerformer objects. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public interface ModelDirectedPlayer { + + public void play(int performerIndex, ModelConnectionBlock[] connectionBlocks); + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDirector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDirector.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * A director chooses what performers should be + * played for each note on and note off events. + * + * ModelInstrument can implement custom performer + * who chooses what performers to play for example by sustain pedal is off or on. + * + * The default director (ModelStandardDirector) chooses performers + * by there keyfrom,keyto,velfrom,velto properties. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public interface ModelDirector { + public void noteOn(int noteNumber, int velocity); + public void noteOff(int noteNumber, int velocity); + public void close(); +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelIdentifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelIdentifier.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,153 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * This class stores the identity of source and destinations in connection blocks, see ModelConnectionBlock. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelIdentifier { + +/* + * Object Variable + * ------ -------- + * + * // INPUT parameters + * noteon keynumber 7 bit midi value + * velocity 7 bit midi vale + * on 1 or 0 + * + * midi pitch 14 bit midi value + * channel_pressure 7 bit midi value + * poly_pressure 7 bit midi value + * + * midi_cc 0 (midi control #0 7 bit midi value + * 1 (midi control #1 7 bit midi value + * ... + * 127 (midi control #127 7 bit midi value + * + * midi_rpn 0 (midi rpn control #0) 14 bit midi value + * 1 (midi rpn control #1) 14 bit midi value + * .... + * + * // DAHDSR envelope generator + * eg (null) + * delay timecent + * attack timecent + * hold timecent + * decay timecent + * sustain 0.1 % + * release timecent + * + * // Low frequency oscillirator (sine wave) + * lfo (null) + * delay timcent + * freq cent + * + * // Resonance LowPass Filter 6dB slope + * filter (null) (output/input) + * freq cent + * q cB + * + * // The oscillator with preloaded wavetable data + * osc (null) + * pitch cent + * + * // Output mixer pins + * mixer gain cB + * pan 0.1 % + * reverb 0.1 % + * chorus 0.1 % + * + */ + + + private String object = null; + private String variable = null; + private int instance = 0; + + public ModelIdentifier(String object) + { + this.object = object; + } + public ModelIdentifier(String object, int instance) + { + this.object = object; + this.instance = instance; + } + public ModelIdentifier(String object, String variable) + { + this.object = object; + this.variable = variable; + + } + public ModelIdentifier(String object, String variable, int instance) + { + this.object = object; + this.variable = variable; + this.instance = instance; + + } + + public int getInstance() { + return instance; + } + public void setInstance(int instance) { + this.instance = instance; + } + public String getObject() { + return object; + } + public void setObject(String object) { + this.object = object; + } + public String getVariable() { + return variable; + } + public void setVariable(String variable) { + this.variable = variable; + } + + + public boolean equals(Object obj) { + if(!(obj instanceof ModelIdentifier)) return false; + ModelIdentifier mobj = (ModelIdentifier)obj; + if((object == null) != (mobj.object == null)) return false; + if((variable == null) != (mobj.variable == null)) return false; + if(mobj.getInstance() != getInstance()) return false; + if(!(object == null || object.equals(mobj.object))) return false; + if(!(variable == null || variable.equals(mobj.variable))) return false; + return true; + + } + public String toString() + { + if(variable == null) return object+"[" + instance + "]"; else return object + "[" + instance + "]" + "." + variable; + } +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,143 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.AudioFormat; + +/** + * + * The model instrument class. + *

    + * The main methods to override are:
    + * getPerformer, getDirector, getChannelMixer. + *

    + * Performers are used to define what voices which will + * playback when using the instrument. + *
    + * ChannelMixer is used to add channel-wide processing + * on voices output or to define non-voice oriented instruments. + *
    + * Director is used to change how the synthesizer + * chooses what performers to play on midi events. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public abstract class ModelInstrument extends Instrument { + + protected ModelInstrument(Soundbank soundbank, Patch patch, String name, Class dataClass) { + super(soundbank, patch, name, dataClass); + } + + public ModelDirector getDirector(ModelPerformer[] performers, MidiChannel channel, ModelDirectedPlayer player) + { + return new ModelStandardDirector(performers, player); + } + + public ModelPerformer[] getPerformers() + { + return new ModelPerformer[0]; + } + + public ModelChannelMixer getChannelMixer(MidiChannel channel, AudioFormat format) + { + return null; + } + + // Get General MIDI 2 Alias patch for this instrument. + public Patch getPatchAlias() + { + Patch patch = getPatch(); + int program = patch.getProgram(); + int bank = patch.getBank(); + if(bank != 0) return patch; + boolean percussion = false; + if(getPatch() instanceof ModelPatch) + percussion = ((ModelPatch)getPatch()).isPercussion(); + if(percussion) + return new Patch(0x78 << 7, program); + else + return new Patch(0x79 << 7, program); + } + + // Return name of all the keys. + // This information is generated from ModelPerformer.getName() returned from getPerformers(). + public String[] getKeys() + { + String[] keys = new String[127]; + for(ModelPerformer performer : getPerformers()) + { + for(int k = performer.getKeyFrom(); k <= performer.getKeyTo(); k++) + { + if(keys[k] == null) + { + String name = performer.getName(); + if(name == null) name = "untitled"; + keys[k] = name; + } + } + } + return keys; + } + + // Return what channels this instrument will probably response on General MIDI synthesizer. + public boolean[] getChannels() + { + boolean percussion = false; + if(getPatch() instanceof ModelPatch) + percussion = ((ModelPatch)getPatch()).isPercussion(); + + // Check if instrument is percussion. + if(percussion) + { + boolean[] ch = new boolean[16]; + for (int i = 0; i < ch.length; i++) + ch[i] = false; + ch[9] = true; + return ch; + } + + // Check if instrument uses General MIDI 2 default banks. + int bank = getPatch().getBank(); + if (bank >> 7 == 0x78 || bank >> 7 == 0x79) { + boolean[] ch = new boolean[16]; + for (int i = 0; i < ch.length; i++) + ch[i] = true; + return ch; + } + + boolean[] ch = new boolean[16]; + for (int i = 0; i < ch.length; i++) + ch[i] = true; + ch[9] = false; + return ch; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrumentComparator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrumentComparator.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.Comparator; + +import javax.sound.midi.Instrument; +import javax.sound.midi.Patch; + +/** + * + * Instrument comparator class. + * Used to order instrument by program, bank, percussion. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelInstrumentComparator implements Comparator { + + public int compare(Instrument arg0, Instrument arg1) { + Patch p0 = arg0.getPatch(); + Patch p1 = arg1.getPatch(); + int a = p0.getBank() * 128 + p0.getProgram(); + int b = p1.getBank() * 128 + p1.getProgram(); + if (p0 instanceof ModelPatch) + a += ((ModelPatch) p0).isPercussion() ? 2097152 : 0; + if (p1 instanceof ModelPatch) + b += ((ModelPatch) p1).isPercussion() ? 2097152 : 0; + return a - b; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelMappedInstrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelMappedInstrument.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import javax.sound.midi.MidiChannel; +import javax.sound.midi.Patch; +import javax.sound.sampled.AudioFormat; + +/** + * + * This class is used to map instrument to another patch. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelMappedInstrument extends ModelInstrument { + + private ModelInstrument ins; + + public ModelMappedInstrument(ModelInstrument ins, Patch patch) { + super(ins.getSoundbank(), patch, ins.getName(), ins.getDataClass()); + this.ins = ins; + } + + public Object getData() { + return ins.getData(); + } + + public ModelPerformer[] getPerformers() { + return ins.getPerformers(); + } + + public ModelDirector getDirector(ModelPerformer[] performers, MidiChannel channel, ModelDirectedPlayer player) + { + return ins.getDirector(performers, channel, player); + } + + public ModelChannelMixer getChannelMixer(MidiChannel channel, AudioFormat format) + { + return ins.getChannelMixer(channel, format); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelOscillator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelOscillator.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * This interface is used for oscillators. + * See example in ModelDefaultOscillator which is a wavetable oscillator. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface ModelOscillator { + public int getChannels(); + /** + * Attenuation is in cB. + * @return + */ + public float getAttenuation(); + public ModelOscillatorStream open(float samplerate); +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelOscillatorStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelOscillatorStream.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; + +import javax.sound.midi.MidiChannel; +import javax.sound.midi.VoiceStatus; + +/** + * + * This interface is used for audio streams from ModelOscillator. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface ModelOscillatorStream { + public void setPitch(float pitch); // Pitch is in cents! + public void noteOn(MidiChannel channel, VoiceStatus voice, int noteNumber, int velocity); + public void noteOff(int velocity); + public int read(float[][] buffer, int offset, int len) throws IOException ; + public void close() throws IOException ; +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelPatch.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelPatch.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import javax.sound.midi.Patch; + +/** + * + * A extended patch object that has isPercussion function. + * Which is necessary to identify percussion instruments from melodic instruments. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelPatch extends Patch { + + private boolean percussion = false; + + public ModelPatch(int bank, int program) { + super(bank, program); + } + + public ModelPatch(int bank, int program, boolean percussion) { + super(bank, program); + this.percussion = percussion; + } + + public boolean isPercussion() + { + return percussion; + } + + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelPerformer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelPerformer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,130 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * This class is used to define how to synthesize audio in universal maner + * for both SF2 and DLS instruments. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelPerformer { + + private List oscillators = new ArrayList(); + private List connectionBlocks = new ArrayList(); + + private int keyFrom = 0; + private int keyTo = 127; + private int velFrom = 0; + private int velTo = 127; + private int exclusiveClass = 0; + private boolean releaseTrigger = false; + private boolean selfNonExclusive = false; + private Object userObject = null; + + private boolean addDefaultConnections = true; + + private String name = null; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getConnectionBlocks() { + return connectionBlocks; + } + public void setConnectionBlocks(List connectionBlocks) { + this.connectionBlocks = connectionBlocks; + } + public List getOscillators() { + return oscillators; + } + public int getExclusiveClass() { + return exclusiveClass; + } + public void setExclusiveClass(int exclusiveClass) { + this.exclusiveClass = exclusiveClass; + } + public boolean isSelfNonExclusive() { + return selfNonExclusive; + } + public void setSelfNonExclusive(boolean selfNonExclusive) { + this.selfNonExclusive = selfNonExclusive; + } + public int getKeyFrom() { + return keyFrom; + } + public void setKeyFrom(int keyFrom) { + this.keyFrom = keyFrom; + } + public int getKeyTo() { + return keyTo; + } + public void setKeyTo(int keyTo) { + this.keyTo = keyTo; + } + public int getVelFrom() { + return velFrom; + } + public void setVelFrom(int velFrom) { + this.velFrom = velFrom; + } + public int getVelTo() { + return velTo; + } + public void setVelTo(int velTo) { + this.velTo = velTo; + } + public boolean isReleaseTriggered() { + return releaseTrigger; + } + public void setReleaseTriggered(boolean value) { + this.releaseTrigger = value; + } + public Object getUserObject() + { + return userObject; + } + public void setUserObject(Object object) { + userObject = object; + } + public boolean isDefaultConnectionsEnabled() { + return addDefaultConnections; + } + public void setDefaultConnectionsEnabled(boolean addDefaultConnections) { + this.addDefaultConnections = addDefaultConnections; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelSource.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelSource.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,104 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * This class is used to identify sources in connection blocks, see ModelConnectionBlock. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelSource { + + public static final ModelIdentifier SOURCE_NONE = null; + public static final ModelIdentifier SOURCE_NOTEON_KEYNUMBER = new ModelIdentifier("noteon","keynumber"); // midi keynumber + public static final ModelIdentifier SOURCE_NOTEON_VELOCITY = new ModelIdentifier("noteon","velocity"); // midi velocity + public static final ModelIdentifier SOURCE_EG1 = new ModelIdentifier("eg",null,0); + public static final ModelIdentifier SOURCE_EG2 = new ModelIdentifier("eg",null,1); + public static final ModelIdentifier SOURCE_LFO1 = new ModelIdentifier("lfo",null,0); + public static final ModelIdentifier SOURCE_LFO2 = new ModelIdentifier("lfo",null,1); + public static final ModelIdentifier SOURCE_MIDI_PITCH = new ModelIdentifier("midi","pitch",0); // (0..16383) + public static final ModelIdentifier SOURCE_MIDI_CHANNEL_PRESSURE = new ModelIdentifier("midi","channel_pressure",0); // (0..127) +// public static final ModelIdentifier SOURCE_MIDI_MONO_PRESSURE = new ModelIdentifier("midi","mono_pressure",0); // (0..127) + public static final ModelIdentifier SOURCE_MIDI_POLY_PRESSURE = new ModelIdentifier("midi","poly_pressure",0); // (0..127) + + public static final ModelIdentifier SOURCE_MIDI_CC_0 = new ModelIdentifier("midi_cc","0",0); // (0..127) + public static final ModelIdentifier SOURCE_MIDI_RPN_0 = new ModelIdentifier("midi_rpn","0",0); // (0..16383) + + private ModelIdentifier source = SOURCE_NONE; + private ModelTransform transform; + + public ModelSource() + { + this.transform = new ModelStandardTransform(); + } + + public ModelSource(ModelIdentifier id) + { + source = id; + this.transform = new ModelStandardTransform(); + } + + public ModelSource(ModelIdentifier id, boolean direction) + { + source = id; + this.transform = new ModelStandardTransform(direction); + } + + public ModelSource(ModelIdentifier id, boolean direction, boolean polarity) + { + source = id; + this.transform = new ModelStandardTransform(direction, polarity); + } + + public ModelSource(ModelIdentifier id, boolean direction, boolean polarity, int transform) + { + source = id; + this.transform = new ModelStandardTransform(direction, polarity, transform); + } + + public ModelSource(ModelIdentifier id, ModelTransform transform) + { + source = id; + this.transform = transform; + } + + public ModelIdentifier getIdentifier() { + return source; + } + public void setIdentifier(ModelIdentifier source) { + this.source = source; + } + + public ModelTransform getTransform() { + return transform; + } + public void setTransform(ModelTransform transform) { + this.transform = transform; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelStandardDirector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelStandardDirector.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * A standard director who chooses performers + * by there keyfrom,keyto,velfrom,velto properties. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class ModelStandardDirector implements ModelDirector { + + ModelPerformer[] performers; + ModelDirectedPlayer player; + boolean noteOnUsed = false; + boolean noteOffUsed = false; + + public ModelStandardDirector(ModelPerformer[] performers, ModelDirectedPlayer player) + { + this.performers = performers; + this.player = player; + for (int i = 0; i < performers.length; i++) { + ModelPerformer p = performers[i]; + if(p.isReleaseTriggered()) + { + noteOffUsed = true; + } + else + { + noteOnUsed = true; + } + } + } + + public void close() { + } + + public void noteOff(int noteNumber, int velocity) { + if(!noteOffUsed) return; + for (int i = 0; i < performers.length; i++) { + ModelPerformer p = performers[i]; + if (p.getKeyFrom() <= noteNumber && p.getKeyTo() >= noteNumber) + if (p.getVelFrom() <= velocity && p.getVelTo() >= velocity) + if(p.isReleaseTriggered()){ + player.play(i, null); + } + } + } + + public void noteOn(int noteNumber, int velocity) { + if(!noteOnUsed) return; + for (int i = 0; i < performers.length; i++) { + ModelPerformer p = performers[i]; + if (p.getKeyFrom() <= noteNumber && p.getKeyTo() >= noteNumber) + if (p.getVelFrom() <= velocity && p.getVelTo() >= velocity) + if(!p.isReleaseTriggered()){ + player.play(i, null); + } + } + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelStandardTransform.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelStandardTransform.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,134 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * A standard transformer used in connection blocks. + * It expects input values to be between 0 and 1. + * + * The result of the transform is + * between 0 and 1 if polarity = unipolar and + * between -1 and 1 if polarity = bipolar. + * + * These constraints only applies to Concave, Convex and Switch transforms. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class ModelStandardTransform implements ModelTransform { + + public static final boolean DIRECTION_MIN2MAX = false; + public static final boolean DIRECTION_MAX2MIN = true; + public static final boolean POLARITY_UNIPOLAR = false; + public static final boolean POLARITY_BIPOLAR = true; + + public static final int TRANSFORM_LINEAR = 0; + public static final int TRANSFORM_CONCAVE = 1; // output = (20*log10(127^2/value^2)) / 96 + public static final int TRANSFORM_CONVEX = 2; // same as concave except that start and end point are reversed. + public static final int TRANSFORM_SWITCH = 3; // if value > avg(max,min) then max else min + public static final int TRANSFORM_ABSOLUTE = 4; + + private boolean direction = DIRECTION_MIN2MAX; + private boolean polarity = POLARITY_UNIPOLAR; + private int transform = TRANSFORM_LINEAR; + + public ModelStandardTransform() + { + } + + public ModelStandardTransform(boolean direction) + { + this.direction = direction; + } + + public ModelStandardTransform(boolean direction, boolean polarity) + { + this.direction = direction; + this.polarity = polarity; + } + + public ModelStandardTransform(boolean direction, boolean polarity, int transform) + { + this.direction = direction; + this.polarity = polarity; + this.transform = transform; + } + + public double transform(double value) { + double s; + double a; + if(direction == DIRECTION_MAX2MIN) + value = 1.0 - value; + if(polarity == POLARITY_BIPOLAR) + value = value*2.0 - 1.0; + switch (transform) { + case TRANSFORM_CONCAVE: + s = Math.signum(value); + a = Math.abs(value); + a = -((5.0/12.0)/Math.log(10))*Math.log(1.0 - a); + if(a < 0) a = 0; else if(a > 1) a = 1; + return s*a; + case TRANSFORM_CONVEX: + s = Math.signum(value); + a = Math.abs(value); + a = 1.0+((5.0/12.0)/Math.log(10))*Math.log(a); + if(a < 0) a = 0; else if(a > 1) a = 1; + return s*a; + case TRANSFORM_SWITCH: + if(polarity == POLARITY_BIPOLAR) + return (value > 0)?1:-1; + else + return (value > 0.5)?1:0; + case TRANSFORM_ABSOLUTE: + return Math.abs(value); + default: + break; + } + + return value; + } + + public boolean getDirection() { + return direction; + } + public void setDirection(boolean direction) { + this.direction = direction; + } + public boolean getPolarity() { + return polarity; + } + public void setPolarity(boolean polarity) { + this.polarity = polarity; + } + public int getTransform() { + return transform; + } + public void setTransform(int transform) { + this.transform = transform; + } + + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelTransform.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelTransform.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * Model transform interface. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface ModelTransform { + + abstract public double transform(double value); +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelWavetable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelWavetable.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * This is a wavetable oscillator interface. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public interface ModelWavetable extends ModelOscillator +{ + public static final int LOOP_TYPE_OFF = 0; + public static final int LOOP_TYPE_FORWARD = 1; + public static final int LOOP_TYPE_RELEASE = 2; + public static final int LOOP_TYPE_PINGPONG = 4; + public static final int LOOP_TYPE_REVERSE = 8; + + public AudioFloatInputStream openStream(); + public float getLoopLength(); + public float getLoopStart(); + public int getLoopType(); + public float getPitchcorrection(); + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATInstrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATInstrument.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,536 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.midi.Patch; +import javax.sound.sampled.AudioFormat; + +/** + * GUS Instrument. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class PATInstrument extends ModelInstrument { + + private class OffsetInputStream extends InputStream + { + + private InputStream is; + private int filepointer = 0; + + public OffsetInputStream(InputStream is) + { + this.is = is; + } + + public long getFilePointer() throws IOException { + return filepointer; + } + + public void close() throws IOException { + is.close(); + } + + public int read(byte[] b, int off, int len) throws IOException { + int ret = is.read(b, off, len); + if(ret != -1) filepointer+=ret; + return ret; + } + + public long skip(long n) throws IOException { + long ret = is.skip(n); + if(ret != -1) filepointer+=ret; + return ret; + } + + public int read() throws IOException { + int ret = is.read(); + if(ret != -1) filepointer++; + return ret; + } + + } + + protected int preset = 0; + + protected int bank = 0; + + protected boolean percussion = false; + + protected String name = ""; + + protected String description = ""; + + protected String format = "GF1PATCH110"; + + protected String vendor = "ID#000002"; + + protected PATSample[] samples = null; + + protected int volume; + + private boolean largeFormat = false; + private File sampleFile; + private OffsetInputStream ois; + + public PATInstrument() { + super(null, null, null, null); + } + + public PATInstrument(URL url) throws IOException { + super(null, null, null, null); + + InputStream is = url.openStream(); + try { + readPatch(is); + } finally { + is.close(); + } + } + + public PATInstrument(File file) throws IOException { + super(null, null, null, null); + largeFormat = true; + sampleFile = file; + InputStream is = new FileInputStream(file); + ois = new OffsetInputStream(is); + is = ois; + try { + readPatch(is); + } finally { + is.close(); + } + } + + public PATInstrument(InputStream inputstream) throws IOException { + super(null, null, null, null); + readPatch(inputstream); + } + + private String readString(InputStream is, int len) throws IOException { + byte[] buffer = new byte[len]; + is.read(buffer); + for (int i = 0; i < buffer.length; i++) { + if (buffer[i] == (byte) 0) { + return new String(buffer, 0, i, "ASCII"); + } + } + return new String(buffer, "ASCII"); + } + + private void readPatch(InputStream inputstream) throws IOException { + format = readString(inputstream, 12); + vendor = readString(inputstream, 10); + if (!(format.equals("GF1PATCH110") || format.equals("GF1PATCH100"))) + throw new InvalidFormatException(); + if (!(vendor.equals("ID#000002"))) + throw new InvalidFormatException(); + description = readString(inputstream, 60); + + int instrument_count = inputstream.read(); + if (instrument_count > 1) + throw new InvalidDataException("Invalid instrument count."); + @SuppressWarnings("unused") + int voices = inputstream.read(); + int channels = inputstream.read(); + if (channels > 1) + throw new InvalidDataException("Invalid channels count."); + @SuppressWarnings("unused") + int waveforms = inputstream.read() + (inputstream.read() << 8); + volume = inputstream.read() + (inputstream.read() << 8); + @SuppressWarnings("unused") + int datasize = inputstream.read() + (inputstream.read() << 8) + + (inputstream.read() << 16) + (inputstream.read() << 24); + byte[] reserve1 = new byte[36]; + inputstream.read(reserve1); + @SuppressWarnings("unused") + int instrumentid = inputstream.read() + (inputstream.read() << 8); + name = readString(inputstream, 16); + @SuppressWarnings("unused") + int instrumentsize = inputstream.read() + (inputstream.read() << 8) + + (inputstream.read() << 16) + (inputstream.read() << 24); + int layers = inputstream.read(); + if (layers > 1) + throw new InvalidDataException("Invalid layers count."); + byte[] reserve2 = new byte[40]; + inputstream.read(reserve2); + @SuppressWarnings("unused") + int layerdupl = inputstream.read(); + @SuppressWarnings("unused") + int layer = inputstream.read(); + @SuppressWarnings("unused") + int layersize = inputstream.read() + (inputstream.read() << 8) + + (inputstream.read() << 16) + (inputstream.read() << 24); + int samples = inputstream.read(); + byte[] reserve3 = new byte[40]; + inputstream.read(reserve3); + + this.samples = new PATSample[samples]; + for (int i = 0; i < samples; i++) { + this.samples[i] = readSample(inputstream); + } + } + + private PATSample readSample(InputStream inputstream) throws IOException { + PATSample patsample = new PATSample(); + + patsample.wavename = readString(inputstream, 7); + patsample.fractions = inputstream.read(); + int sampledatasize = inputstream.read() + (inputstream.read() << 8) + + (inputstream.read() << 16) + (inputstream.read() << 24); + patsample.loopstart = inputstream.read() + (inputstream.read() << 8) + + (inputstream.read() << 16) + (inputstream.read() << 24); + patsample.loopend = inputstream.read() + (inputstream.read() << 8) + + (inputstream.read() << 16) + (inputstream.read() << 24); + patsample.samplerate = inputstream.read() + (inputstream.read() << 8); + patsample.lowfreq = inputstream.read() + (inputstream.read() << 8) + + (inputstream.read() << 16) + (inputstream.read() << 24); + patsample.hifreq = inputstream.read() + (inputstream.read() << 8) + + (inputstream.read() << 16) + (inputstream.read() << 24); + patsample.rootfreq = inputstream.read() + (inputstream.read() << 8) + + (inputstream.read() << 16) + (inputstream.read() << 24); + patsample.tune = inputstream.read() + (inputstream.read() << 8); + patsample.pan = inputstream.read(); + + patsample.env_attack_rate = inputstream.read(); + patsample.env_decay_rate = inputstream.read(); + patsample.env_sustain_rate = inputstream.read(); + patsample.env_release1_rate = inputstream.read(); + patsample.env_release2_rate = inputstream.read(); + patsample.env_release3_rate = inputstream.read(); + + patsample.env_attack_offset = inputstream.read(); + patsample.env_decay_offset = inputstream.read(); + patsample.env_sustain_offset = inputstream.read(); + patsample.env_release1_offset = inputstream.read(); + patsample.env_release2_offset = inputstream.read(); + patsample.env_release3_offset = inputstream.read(); + + patsample.tremolo_sweep = inputstream.read(); + patsample.tremolo_rate = inputstream.read(); + patsample.tremolo_depth = inputstream.read(); + patsample.vibrato_sweep = inputstream.read(); + patsample.vibrato_rate = inputstream.read(); + patsample.vibrato_depth = inputstream.read(); + patsample.sampling_mode = inputstream.read(); + patsample.scalefreq = inputstream.read() + (inputstream.read() << 8); + patsample.scalefactor = inputstream.read() + (inputstream.read() << 8); + byte[] reserve1 = new byte[36]; + inputstream.read(reserve1); + + if(largeFormat) + { + long offset = ois.getFilePointer(); + inputstream.skip(sampledatasize); + patsample.sampledata = new ModelByteBuffer(sampleFile, offset, sampledatasize); + } + else + { + byte[] buff = new byte[sampledatasize]; + inputstream.read(buff); + patsample.sampledata = new ModelByteBuffer(buff); + } + + return patsample; + + } + + public Object getData() { + return null; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public ModelPatch getPatch() { + return new ModelPatch(bank, preset, percussion); + } + + public void setPatch(Patch patch) { + if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) { + percussion = true; + bank = patch.getBank(); + preset = patch.getProgram(); + } else { + percussion = false; + bank = patch.getBank(); + preset = patch.getProgram(); + } + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public String getVendor() { + return vendor; + } + + public void setVendor(String vendor) { + this.vendor = vendor; + } + + private double convertRate(int rate) { + return (rate & 63) * Math.pow(1.0 / 2.0, 3 * ((rate >> 6) & 3)); + } + + public ModelPerformer[] getPerformers() { + + ModelPerformer[] performers = new ModelPerformer[samples.length]; + for (int i = 0; i < performers.length; i++) { + ModelPerformer performer = new ModelPerformer(); + PATSample patsample = samples[i]; + performer.setName(samples[i].wavename); + + double keyfrom = 69 + 12 + * Math.log((patsample.lowfreq / 1000.0) / 440.0) + / Math.log(2.0); + double keyto = 69 + 12 + * Math.log((patsample.hifreq / 1000.0) / 440.0) + / Math.log(2.0); + + performer.setKeyFrom((int)Math.ceil(keyfrom)); + performer.setKeyTo((int)Math.floor(keyto)); + + ModelByteBuffer buffer = patsample.sampledata; + + boolean is16bit = (patsample.sampling_mode & 1) != 0; + boolean isUnsigned = (patsample.sampling_mode & 2) != 0; + boolean isLooping = (patsample.sampling_mode & 4) != 0; + boolean isPingPongLoop = (patsample.sampling_mode & 8) != 0; + boolean isReverseLoop = (patsample.sampling_mode & 16) != 0; + //boolean isSustain = (patsample.sampling_mode & 32) != 0; + boolean isEnv = (patsample.sampling_mode & 64) != 0; + //boolean isClampedRelease = (patsample.sampling_mode & 128) != 0; + + + AudioFormat audioformat = null; + if (is16bit) + audioformat = new AudioFormat(patsample.samplerate, 16, 1, + !isUnsigned, false); + else + audioformat = new AudioFormat(patsample.samplerate, 8, 1, + !isUnsigned, false); + + float pitchcorrection = -(float) (69 + 12 + * Math.log((patsample.rootfreq / 1000.0) / 440.0) + / Math.log(2.0)); + pitchcorrection *= 100; + + ModelByteBufferWavetable osc = new ModelByteBufferWavetable(buffer, + audioformat, pitchcorrection); + + float loopstart = patsample.loopstart + ((patsample.fractions&0xF)/16f); + float loopend = patsample.loopend + ((patsample.fractions>>4)/16f); + + if (isLooping) { + if (is16bit) { + osc.setLoopStart(loopstart / 2f); + osc.setLoopLength(loopend / 2f + - loopstart / 2f); + } else { + osc.setLoopStart(loopstart); + osc.setLoopLength(loopend - loopstart); + } + osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); + if(isPingPongLoop) + osc.setLoopType(ModelWavetable.LOOP_TYPE_PINGPONG); + if(isReverseLoop) + osc.setLoopType(ModelWavetable.LOOP_TYPE_REVERSE); + } + performer.getOscillators().add(osc); + + double lfo_vib_rate = patsample.vibrato_rate / 42.0; + double lfo_vol_rate = patsample.tremolo_rate / 42.0; + double lfo_vib_depth = 400.0 * patsample.vibrato_depth / 256.0; + + performer.getConnectionBlocks().add( + new ModelConnectionBlock(6900 + 1200.0 + * Math.log(lfo_vol_rate / 440.0) / Math.log(2), + new ModelDestination( + ModelDestination.DESTINATION_LFO1_FREQ))); + if(lfo_vib_depth > 0) + performer.getConnectionBlocks().add( + new ModelConnectionBlock(6900 + 1200.0 + * Math.log(lfo_vib_rate / 440.0) / Math.log(2), + new ModelDestination( + ModelDestination.DESTINATION_LFO2_FREQ))); + + + if (lfo_vib_depth > 0) { + ModelIdentifier src = ModelSource.SOURCE_LFO2; + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR), + lfo_vib_depth, new ModelDestination(dest))); + } + + double lfo_vol_depth = -200 + * Math.log(1.0 - patsample.tremolo_depth / 256.0) + / Math.log(10); + if (lfo_vol_depth > 960) + lfo_vol_depth = 960; + if (lfo_vol_depth > 0) { + ModelIdentifier src = ModelSource.SOURCE_LFO1; + ModelIdentifier dest = ModelDestination.DESTINATION_GAIN; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR), + lfo_vol_depth, new ModelDestination(dest))); + } + + double volume = this.volume / 128.0; + if (isEnv) { + double env_attack_msec = patsample.env_attack_offset + / convertRate(patsample.env_attack_rate); + double env_decay_msec = 0.5*(patsample.env_attack_offset - patsample.env_decay_offset) + / convertRate(patsample.env_decay_rate); + env_decay_msec += 0.5*(patsample.env_decay_offset - patsample.env_sustain_offset) + / convertRate(patsample.env_sustain_rate); + double env_release_msec = 0.5*(patsample.env_attack_offset - 0) + / convertRate(patsample.env_release1_rate); + /* patsample.env_release1_offset + env_release_msec += (patsample.env_release1_offset - patsample.env_release2_offset) + / convertRate(patsample.env_release2_rate); + env_release_msec += (patsample.env_release2_offset - patsample.env_release3_offset) + / convertRate(patsample.env_release3_rate); + */ + double env_volume_level = patsample.env_attack_offset / 256.0; + double env_sustain_level = patsample.env_sustain_offset / 256.0; + if (env_attack_msec < 0) + env_attack_msec = 0; + if (env_decay_msec < 0) + env_decay_msec = 0; + if (env_release_msec < 0) + env_release_msec = 0; + volume *= env_volume_level; + performer + .getConnectionBlocks() + .add( + new ModelConnectionBlock( + env_sustain_level * 1000.0, + new ModelDestination( + ModelDestination.DESTINATION_EG1_SUSTAIN))); + performer.getConnectionBlocks().add( + new ModelConnectionBlock(1200.0 + * Math.log(env_attack_msec / 1000.0) + / Math.log(2), new ModelDestination( + ModelDestination.DESTINATION_EG1_ATTACK))); + performer.getConnectionBlocks().add( + new ModelConnectionBlock(1200.0 + * Math.log(env_decay_msec / 1000.0) + / Math.log(2), new ModelDestination( + ModelDestination.DESTINATION_EG1_DECAY))); + performer.getConnectionBlocks().add( + new ModelConnectionBlock(1200.0 + * Math.log(env_release_msec / 1000.0) + / Math.log(2), new ModelDestination( + ModelDestination.DESTINATION_EG1_RELEASE))); + } else { + if (!isLooping) + performer + .getConnectionBlocks() + .add( + new ModelConnectionBlock( + 12000.0, + new ModelDestination( + ModelDestination.DESTINATION_EG1_RELEASE))); + } + + // Linear gain to dB + double gain = ((20.0) / Math.log(10)) * Math.log(volume); + performer.getConnectionBlocks().add( + new ModelConnectionBlock(gain, new ModelDestination( + ModelDestination.DESTINATION_GAIN))); + + double panning = 500; + if (patsample.pan < 7) + panning = (patsample.pan / 7.0) * 500.0; + if (patsample.pan > 8) + panning += ((patsample.pan - 8) / 7.0) * 500.0; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(panning - 500.0, + new ModelDestination( + ModelDestination.DESTINATION_PAN))); + + // Modulation wheel should use SOURCE_LFO2 (vib) + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource( + ModelSource.SOURCE_LFO2, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(new ModelIdentifier("midi_cc", "1", + 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 50, new ModelDestination( + ModelDestination.DESTINATION_PITCH))); + + performers[i] = performer; + } + + return performers; + } + + public PATSample[] getSamples() { + return samples; + } + + public void setSamples(PATSample[] samples) { + this.samples = samples; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSample.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSample.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,113 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * GUS Sample storage. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class PATSample { + + public String wavename = ""; + + public int fractions; + + // bit 0..3: Loop offset start fractions [0/16 .. 15/16] + // bit 4..7: Loop offset end fractions [0/16 .. 15/16] + + public int loopstart; + + public int loopend; + + public int samplerate; + + public int lowfreq; + + public int hifreq; + + public int rootfreq; + + public int tune; // not used + + public int pan; // 0..15, 7 and 8 are center + + public int env_attack_rate; + + public int env_decay_rate; + + public int env_sustain_rate; + + public int env_release1_rate; + + public int env_release2_rate; // ignored + + public int env_release3_rate; // ignored + + public int env_attack_offset; + + public int env_decay_offset; + + public int env_sustain_offset; + + public int env_release1_offset; + + public int env_release2_offset; // ignored + + public int env_release3_offset; // ignored + + public int tremolo_sweep; // ignored + + public int tremolo_rate; + + public int tremolo_depth; + + public int vibrato_sweep; // ignored + + public int vibrato_rate; + + public int vibrato_depth; + + public int sampling_mode; + + // bit 0: 16-bit (versus 8-bit) + // bit 1: Unsigned (versus signed) + // bit 2: Looped + // bit 3: Pingpong Loop + // bit 4: Reverse + // bit 5: Sustain <- Ignored + // bit 6: Envelope + // bit 7: Clamped release (6th point of envelope) <- Ignored + + public int scalefreq; // ignored + + public int scalefactor; // ignored + + public ModelByteBuffer sampledata; + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSoundbankReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSoundbankReader.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,294 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.spi.SoundbankReader; + +/** + * GUS-compatible GF1 Patch reader. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class PATSoundbankReader extends SoundbankReader { + + public Soundbank getSoundbank(URL url) throws InvalidMidiDataException, + IOException { + try { + PATInstrument ins = new PATInstrument(url); + SimpleSoundbank snk = new SimpleSoundbank(); + snk.addInstrument(ins); + return snk; + } catch (InvalidFormatException e) { + return null; + } + } + + public Soundbank getSoundbank(InputStream stream) + throws InvalidMidiDataException, IOException { + try { + stream.mark(512); + PATInstrument ins = new PATInstrument(stream); + SimpleSoundbank snk = new SimpleSoundbank(); + snk.addInstrument(ins); + return snk; + } catch (InvalidFormatException e) { + stream.reset(); + return null; + } + } + + + public Soundbank getSoundbank(File file) throws InvalidMidiDataException, IOException { + if (file.getPath().toLowerCase().endsWith(".cfg")) + return readConfigFile(file); + if (!file.getPath().toLowerCase().endsWith(".pat")) + return null; + try { + PATInstrument ins = new PATInstrument(file); + SimpleSoundbank snk = new SimpleSoundbank(); + snk.addInstrument(ins); + return snk; + } catch (InvalidFormatException e) { + return null; + } + } + + private ModelPerformer[] processDrumKit(PATInstrument ins) + { + ModelPerformer[] performers = ins.getPerformers(); + + for (ModelPerformer performer : performers) { + double pc = -((ModelWavetable) performer + .getOscillators().get(0)) + .getPitchcorrection() / 100.0; + performer + .getConnectionBlocks() + .add( + new ModelConnectionBlock( + pc / 128.0, + new ModelDestination( + ModelDestination.DESTINATION_KEYNUMBER))); + + if(((ModelWavetable) performer.getOscillators().get(0)).getLoopType() == ModelWavetable.LOOP_TYPE_OFF) + { + performer + .getConnectionBlocks() + .add( + new ModelConnectionBlock( + 12000, + new ModelDestination( + ModelDestination.DESTINATION_EG1_RELEASE))); + + } + } + return performers; + } + + private Soundbank readConfigFile(File file) + throws InvalidMidiDataException, IOException { + File root = file.getParentFile(); + SimpleSoundbank soundbank = new SimpleSoundbank(); + FileInputStream in = new FileInputStream(file); + try { + try { + + int bank = -2; + int drumset = -1; + SimpleInstrument drumsetins = null; + + HashMap> multipatchmaps + = new HashMap>(); + + Reader r = new InputStreamReader(in, "ASCII"); + BufferedReader br = new BufferedReader(r); + String line = null; + while ((line = br.readLine()) != null) { + int li = line.indexOf('#'); + if (li != -1) + line = line.substring(0, li); + line = line.trim(); + if (line.length() == 0) + continue; + StringTokenizer st = new StringTokenizer(line, " "); + if (!st.hasMoreTokens()) + continue; + String token = st.nextToken(); + if (token.equalsIgnoreCase("drumset")) { + if (!st.hasMoreTokens()) + continue; + token = st.nextToken(); + drumset = Integer.parseInt(token); + bank = -1; + drumsetins = new SimpleInstrument(); + drumsetins.setPatch(new ModelPatch(0, drumset, true)); + soundbank.addInstrument(drumsetins); + } else if (token.equalsIgnoreCase("bank")) { + if (!st.hasMoreTokens()) + continue; + token = st.nextToken(); + drumset = -1; + bank = Integer.parseInt(token); + } else + if(bank == -2) + { + int prg_from = 0; + int prg_to = 0; + int li2 = token.indexOf('-'); + if(li2 == -1) + { + prg_from = Integer.parseInt(token)-1; + prg_to = Integer.parseInt(token)-1; + } + else + { + prg_from = Integer.parseInt(token.substring(0, li2))-1; + prg_to = Integer.parseInt(token.substring(li2+1))-1; + } + if(prg_to < 0) continue; + if(prg_to < prg_from) continue; + if(prg_from < 0) prg_from = 0; + + if(!st.hasMoreTokens()) continue; + token = st.nextToken(); + if(token.equals("begin_multipatch") || token.equals("override_patch")) + { + + HashMap multipatchmap = new HashMap(); + if(token.equals("override_patch")) + { + HashMap omap = multipatchmaps.get(prg_from); + if(omap != null) + multipatchmap.putAll(omap); + } + for (int prg = prg_from; prg <= prg_to; prg++) + multipatchmaps.put(prg, multipatchmap); + + + while ((line = br.readLine()) != null) { + if(line.equals("end_multipatch")) break; + + StringTokenizer st2 = new StringTokenizer(line, " "); + if(!st2.hasMoreTokens()) continue; + int key = Integer.parseInt(st2.nextToken().trim()); + if(!st2.hasMoreTokens()) continue; + token = st2.nextToken(); + File patfile = new File(root, token); + if (!patfile.exists()) + patfile = new File(root, token + ".pat"); + + multipatchmap.put(key, processDrumKit(new PATInstrument(patfile))); + } + } + else + { + File patfile = new File(root, token); + if (!patfile.exists()) + patfile = new File(root, token + ".pat"); + + for (int prg = prg_from; prg <= prg_to; prg++) { + PATInstrument ins = new PATInstrument(patfile); + if(prg != 0) + { + if(prg >= 128) + ins.setPatch(new ModelPatch(0, prg-128, true)); + else + ins.setPatch(new Patch(0, prg)); + } + soundbank.addInstrument(ins); + } + + } + } + else + { + int id = Integer.parseInt(token); + if (!st.hasMoreTokens()) + continue; + token = st.nextToken(); + File patfile = new File(root, token); + if (!patfile.exists()) { + patfile = new File(root, token + ".pat"); + } + PATInstrument ins = new PATInstrument(patfile); + + if (bank != -1) { + ins.setPatch(new Patch(bank, id)); + soundbank.addInstrument(ins); + } else if (drumset != -1) { + drumsetins.add(processDrumKit(ins), id, id); + } + } + + } + + for(Map.Entry> entry : + multipatchmaps.entrySet()) + { + + int prg = entry.getKey(); + drumsetins = new SimpleInstrument(); + if(prg >= 128) + drumsetins.setPatch(new ModelPatch(0, prg-128, true)); + else + drumsetins.setPatch(new Patch(0, prg)); + + drumsetins.add(entry.getValue().get(36)); + for(Map.Entry entry2 : entry.getValue().entrySet()) + drumsetins.add(entry2.getValue(), entry2.getKey(), entry2.getKey()); + + soundbank.addInstrument(drumsetins); + + } + + } finally { + in.close(); + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + return soundbank; + } + + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/README.txt Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,403 @@ +Gervill - Software Sound Synthesizer +==================================== + +Introduction: +------------- + + "Gervill" is a software sound synthesizer + which was created for the open source JDK + Audio Synthesis Engine Project. + + +Hightlight of features: +----------------------- + + * Downloadable Sound Level 2.2 + * SoundFonts 2.04 (24 bit) + * Gravis Ultrasound-compatible patches + * Use Audio files (AIFF, AU and WAV) as SoundBanks + * General Midi Level 2 + * MIDI Tuning Standard + * Drumkits can be used on any channel + * Sinc interpolation with anti-aliasing + + +List of Technical Specification used: +------------------------------------- + + The Complete MIDI 1.0 Detailed Specification + (document version 96.1 second edition). + General MIDI 2 (Version 1.1, September 10, 2003). + GM2 MIDI Tuning Amendment (RP-037) + Downloadable Sounds Level 1 (Version 1.1b, September 2004). + Downloadable Sounds Level 2.2 (Version 1.0, April 2006). + MIDI IMPLEMENTATION CHART V2 INSTRUCTIONS + CA-020, MIDI TUNING Extensions + CA# 22, Controller Destination Setting + CA# 23, Key-Based Instrument Controllers + CA# 24, Global Parameter Control + CA# 25, Master Fine/Coarse Tuning + CA# 26, Modulation Depth Range RPN + The MIDI Manufacturers Association Los Angelese, CA. + http://www.midi.org + + SoundFont 2.1 Application Note + (Wednesday, August 12, 1998) + Joint E-mu/Creative Technology Center E-mu Systems, Inc + SoundFont(R) Technical Specification + (Version 2.04, February 3, 2006) + http://www.soundfont.com + + +Features: +--------- + +Audio/Implementation Features: + +* Synhtesizer default parameters. + Interpolation: Linear + Audioformat: 44100 Hz, stereo, + 16 bit, signed, little-endian + Control rate: 147 Hz + Max Polyphony: 64 + Latency: 400 msec + (can be as low as 70 msec on windows plaform) + +* Audio formats supported: + Mono/Stereo. + 8,16,24,32 bit signed/unsigned pcm stream + and 32 bit pcm floating point stream. + Big/little endian. + Any sample rate including 44100 Hz. + + +* Several interpolation algorithms are included: + linear, cubic, lanczos and sinc interpolation. + The sinc interpolation also includes a anti-alias filtering. + +* The synthesizer looks for default soundbank in these locations: + %JAVA_RUNTIME_LOCATION%\lib\audio\*.dls and *.sf2 + %WINDOWS_LOCATION%\system32\drivers\gm.dls + +* Multi-format soundbank support. + SoundFont 2.4, DLS 2.2, Gravis Patch soundbanks + and Simple audio files are also supported + as soundbanks like WAV/AIFF/AU + (and other audio files available thru Java SPI) + +* SoundFont 2.01 NRPN messages are not supported. + +* Editable soundbanks: + SoundFont 2.4 and DLS 2.2 soundbanks + can be edited in memory and saved back to disk. + +* AudioSynthesizer interface is used to + route audio output from the synthesizer. + +* The function getVoiceStatus is fully implemented + and it is the real location where active voice parameters are located. + +* Support midi time stamping in the Receiver interface. + And it is to be used with conjuction with + getMicrosecondPosition() method in the synthesizer class. + +* Two global effect engine are included: Chorus and Reverb + and they are fully configurated with + standard Global Parameter Control Sysex messages. + +* Emergency soundbank is include, + it used when no default soundbank can be found. + + +MIDI Features: + +* The synthesizer is fully General Midi Level 2 compatible. + +* Full support for MIDI tuning standard. + Sysex mesages messages from programs like + Scala (http://www.xs4all.nl/~huygensf/scala/). + This enables all kinds of microtuning. + +* Drumkit and melodic instruments can be on any channel + using the GM2 MSB banks 0x78 (drumkit) and 0x79 (melodic). + +* Support for Midi Controller destination, + user can customize how midi controllers or channel/poly aftertouch + affect internal synthesizer parameters. + +* Other sysex messages support are: + Master Volume, Master Balance, Global Parameter Control + Key-based instrument ctrl, Master Fine/Coarse tune + +* These RPN are supported: + RPN 00 (Pitch Bend Sensitivity) + RPN 01 (Channel Fine Tune) + RPN 02 (Channel Coarse Tune) + RPN 03 (Tuning Program Select) + RPN 04 (Tuning Bank Select) + RPN 05 (Modulation Depth Range) + +* Support for GS/XG NRPN voice editing parameters: + NRPN 1,08 Vibrato Rate + NRPN 1,09 Vibrato Depth + NRPN 1,10 Vibrato Delay + NRPN 1,32 Filter Cutoff + NRPN 1,33 Filter Resonance + NRPN 1,99 Attack Time + NRPN 1,100 Decay Time + NRPN 1,102 Release Time + NRPN 24,rr Pitch per drum sound (rr) + NRPN 26,rr Volume per drum sound (rr) + NRPN 28,rr Pan per drum sound (rr) + NRPN 29,rr Reverb per drum sound (rr) + NRPN 30,rr Chorus per drum sound (rr) + +* Both channel and poly aftertouch are supported. + +* Full support for portamento control both in poly and mono mode. + +* Midi controls supported: + 0 Bank Select MSB + 1 Modulation + 5 Portamento Time + 6 Data Entry MSB + 7 Volume + 8 Balance + 10 Pan + 11 Expression + 32 Ban Select LSB + 38 Data Entry LSB + 64 Sustain + 65 Portamento On/off + 66 Sostenuto + 67 Soft Pedal + 71 Filter Cutoff + 72 Release Time + 73 Attack Time + 74 Filter Resonance + 75 Decay Time + 76 Vibrato Rate + 77 Vibrato Depth + 78 Vibrato Delay + 84 Portamento Control + 91 Reverb send + 93 Chorus send + 96 Data Increment + 97 Data Decrement + 98 NRPN LSB + 99 NRPN MSB + 100 RPN LSB + 101 RPN MSB + 120 All Sound Off + 121 Reset all controllers + 123 All notes Off + 126 Poly Mode Off + 127 Poly Mode On + + +MIDI Implementation Chart v. 2.0 (Page 1 of 3) +---------------------------------------------- + + Transmit/Export Recognize/Import Remarks +1. Basic Information +MIDI channels No 1 - 16 +Note numbers No 1 - 128 +Program change No 1 - 128 +Bank Select response? (Yes/No) No Yes Both MSB and LSB messages. +Modes supported : + Mode 1: Omni-On, Poly (Yes/No) No No + Mode 2: Omni-On, Mono (Yes/No) No No + Mode 3: Omni-Off, Poly (Yes/No) No Yes + Mode 4: Omni-Off, Mono (Yes/No) No Yes +Multi Mode (Yes/No) No Yes +Note-On Velocity (Yes/No) No Yes +Note-Off Velocity (Yes/No) No No +Channel Aftertouch (Yes/No) No Yes +Poly (Key) Aftertouch (Yes/No) No Yes +Pitch Bend (Yes/No) No Yes +Active Sensing (Yes/No) No Yes +System Reset (Yes/No) No Yes +Tune Request (Yes/No) No No +Universal System Exclusive: + Sample Dump Standard (Yes/No) No No + Device Inquiry (Yes/No) No No + File Dump (Yes/No) No No + MIDI Tuning (Yes/No) No Yes + Master Volume (Yes/No) No Yes + Master Balance (Yes/No) No Yes + Notation Information (Yes/No) No No + Turn GM1 System On (Yes/No) No Yes + Turn GM2 System On (Yes/No) No Yes + Turn GM System Off (Yes/No) No Yes + DLS-1 (Yes/No) No Yes + File Reference (Yes/No) No No + Controller Destination (Yes/No) No Yes + Key-based Instrument Ctrl (Yes/No) No Yes + Master Fine/Coarse Tune (Yes/No) No Yes + Other Universal System Exclusive No Yes Global Parameter Control +Manufacturer or Non-Commercial System Exclusive +NRPNs (Yes/No) No Yes GS/XG NRPN voice editing parameters +RPN 00 (Pitch Bend Sensitivity) (Yes/No)No Yes +RPN 01 (Channel Fine Tune) (Yes/No) No Yes +RPN 02 (Channel Coarse Tune) (Yes/No) No Yes +RPN 03 (Tuning Program Select) (Yes/No) No Yes +RPN 04 (Tuning Bank Select) (Yes/No) No Yes +RPN 05 (Modulation Depth Range) (Yes/No)No Yes +2. MIDI Timing and Synchronization +MIDI Clock (Yes/No) No No +Song Position Pointer (Yes/No) No No +Song Select (Yes/No) No No +Start (Yes/No) No No +Continue (Yes/No) No No +Stop (Yes/No) No No +MIDI Time Code (Yes/No) No No +MIDI Machine Control (Yes/No) No No +MIDI Show Control (Yes/No) No No +If yes, MSC Level supported +3. Extensions Compatibility +General MIDI compatible? (Level(s)/No) Level 2 +Is GM default power-up mode? (Level/No) No* * Some non-gm NRPN are enabled. +DLS compatible? (Levels(s)/No) Level 2 (DLS 2.2) Also supports SoundFont 2.4 +(DLS File Type(s)/No) .DLS +Standard MIDI Files (Type(s)/No) No +XMF Files (Type(s)/No) No +SP-MIDI compatible? (Yes/No) No + +MIDI Implementation Chart v. 2.0 (Page 2 of 3) +---------------------------------------------- + +Control# Function# Transmitted (Y/N) Recognized (Y/N) Remarks +0 Bank Select (MSB) N Y +1 Modulation Wheel (MSB) N Y +2 Breath Controller (MSB) N N +3 N N +4 Foot Controller (MSB) N N +5 Portamento Time (MSB) N Y 10^(0.5-5*asin(cc5/64-1)/pi) = cent/msec +6 Data Entry (MSB) N Y +7 Channel Volume (MSB) N Y 40*log10(cc7/128) = dB +8 Balance (MSB) N Y +9 N N +10 Pan (MSB) N Y +11 Expression (MSB) N Y 40*log10(cc11/128) = dB +12 Effect Control 1 (MSB) N N +13 Effect Control 2 (MSB) N N +14 N N +15 N N +16 General Purpose Controller 1 (MSB) N N +17 General Purpose Controller 2 (MSB) N N +18 General Purpose Controller 3 (MSB) N N +19 General Purpose Controller 4 (MSB) N N +20 N N +21 N N +22 N N +23 N N +24 N N +25 N N +26 N N +27 N N +28 N N +29 N N +30 N N +31 N N +32 Bank Select (LSB) N Y +33 Modulation Wheel (LSB) N N +34 Breath Controller (LSB) N N +35 N N +36 Foot Controller (LSB) N N +37 Portamento Time (LSB) N N +38 Data Entry (LSB) N Y +39 Channel Volume (LSB) N N +40 Balance (LSB) N N +41 N N +42 Pan (LSB) N N +43 Expression (LSB) N N +44 Effect Control 1 (LSB) N N +45 Effect Control 2 (LSB) N N +46 N N +47 N N +48 General Purpose Controller 1 (LSB) N N +49 General Purpose Controller 2 (LSB) N N +50 General Purpose Controller 3 (LSB) N N +51 General Purpose Controller 4 (LSB) N N +52 N N +53 N N +54 N N +55 N N +56 N N +57 N N +58 N N +59 N N +60 N N +61 N N +62 N N +63 N N + +MIDI Implementation Chart v. 2.0 (Page 3 of 3) +---------------------------------------------- + +Control# Function# Transmitted (Y/N) Recognized (Y/N) Remarks +64 Sustain Pedal N Y +65 Portamento On/Off N Y +66 Sostenuto N Y +67 Soft Pedal N Y +68 Legato Footswitch N N +69 Hold 2 N N +70 Sound Controller 1 N N +71 Sound Controller 2 (Filter Cutoff) N Y +/- 6400 cents +72 Sound Controller 3 (Release Time) N Y +/- 6 sec +73 Sound Controller 4 (Attack Time) N Y +/- 2 sec +74 Sound Controller 5 (Brightness) N Y +/- 20 db (Filter Resonance) +75 Sound Controller 6 (Decay Time) N Y +/- 6 sec +76 Sound Controller 7 (Vibrato Rate) N Y +/- 2400 cents +77 Sound Controller 8 (Vibrato Depth) N Y +/- 200 cents +78 Sound Controller 9 (Vibrato Delay) N Y +/- 2 sec +79 Sound Controller 10 N N +80 General Purpose Controller 5 N N +81 General Purpose Controller 6 N N +82 General Purpose Controller 7 N N +83 General Purpose Controller 8 N N +84 Portamento Control N Y +85 N N +86 N N +87 N N +88 N N +89 N N +90 N N +91 Effects 1 Depth, Reverb N Y +92 Effects 2 Depth N N +93 Effects 3 Depth, chorus N Y +94 Effects 4 Depth N N +95 Effects 5 Depth N N +96 Data Increment N Y +97 Data Decrement N Y +98 NRPN (LSB) N Y +99 NRPN (MSB) N Y +100 RPN (LSB) N Y +101 RPN (MSB) N Y +102 N N +103 N N +104 N N +105 N N +106 N N +107 N N +108 N N +109 N N +110 N N +111 N N +112 N N +113 N N +114 N N +115 N N +116 N N +117 N N +118 N N +119 N N +120 All Sound Off N Y +121 Reset All Controllers N Y +122 Local Control On/Off N N +123 All Notes Off N Y +124 Omni Mode Off N N +125 Omni Mode On N N +126 Poly Mode Off N Y +127 Poly Mode On N Y + \ No newline at end of file diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidDataException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidDataException.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * This exception is used when a RIFF file contains illegal or unexpected data. + * * + * @version %I%, %E% + * @author Karl Helgason + */ +public class RIFFInvalidDataException extends InvalidDataException { + + private static final long serialVersionUID = 1L; + + public RIFFInvalidDataException() { + super("Invalid Data!"); + } + + public RIFFInvalidDataException(String s) { + super(s); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidFormatException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidFormatException.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * This exception is used when a reader is used to read RIFF file of a format it + * doesn't unterstand or support. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class RIFFInvalidFormatException extends InvalidFormatException { + + private static final long serialVersionUID = 1L; + + public RIFFInvalidFormatException() { + super("Invalid format!"); + } + + public RIFFInvalidFormatException(String s) { + super(s); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFReader.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,308 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; + +/** + * Resource Interchange File Format (RIFF) stream decoder. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class RIFFReader extends InputStream { + + private RIFFReader root; + private long filepointer = 0; + + private String fourcc; + + private String riff_type = null; + + private long ckSize = 0; + + private InputStream stream; + + private long avail; + + private RIFFReader lastiterator = null; + + public RIFFReader(InputStream stream) throws IOException { + + if(stream instanceof RIFFReader) + root = ((RIFFReader)stream).root; + else + root = this; + + this.stream = stream; + avail = stream.available(); + ckSize = stream.available(); + + // Check for RIFF null paddings, + int b; + while (true) { + b = read(); + if (b == -1) { + fourcc = ""; // don't put null value into fourcc, + // because it is expected to + // always contain a string value + riff_type = null; + avail = 0; + return; + } + if (b != 0) + break; + } + + byte[] fourcc = new byte[4]; + fourcc[0] = (byte) b; + read(fourcc, 1, 3); + this.fourcc = new String(fourcc, "ascii"); + ckSize = readUnsignedInt(); + + avail = this.ckSize; + + if (getFormat().equals("RIFF") || getFormat().equals("LIST")) { + byte[] format = new byte[4]; + read(format); + this.riff_type = new String(format, "ascii"); + + } + + } + + public long getFilePointer() throws IOException { + return root.filepointer; + } + + public boolean hasNextChunk() throws IOException { + if (lastiterator != null) + lastiterator.finish(); + return avail != 0; + } + + public RIFFReader nextChunk() throws IOException { + if (lastiterator != null) + lastiterator.finish(); + if (avail == 0) + return null; + lastiterator = new RIFFReader(this); + return lastiterator; + } + + public String getFormat() { + return fourcc; + } + + public String getType() { + return riff_type; + } + + public long getSize() { + return ckSize; + } + + public int read() throws IOException { + if (avail == 0) + return -1; + int b = stream.read(); + if(b == -1) return -1; + avail--; + filepointer++; + return b; + } + + public int read(byte[] b, int offset, int len) throws IOException { + if (avail == 0) + return -1; + if (len > avail) { + int rlen = stream.read(b, offset, (int) avail); + if(rlen != -1) filepointer += rlen; + avail = 0; + return rlen; + } else { + avail -= len; + int ret = stream.read(b, offset, len); + if(ret == -1) return -1; + filepointer += ret; + return ret; + } + } + + public long skip(long n) throws IOException { + if (avail == 0) + return -1; + if (n > avail) { + long len = stream.skip(avail); + if(len != -1) filepointer += len; + avail = 0; + return len; + } else { + avail -= n; + long ret = stream.skip(n); + if(ret == -1) return -1; + filepointer += ret; + return ret; + } + } + + public int available() { + return (int) avail; + } + + public void finish() throws IOException { + if (avail != 0) { + long ret = stream.skip(avail); + if(ret != -1) filepointer += ret; + avail = 0; + } + } + + // Read ASCII chars from stream + public String readString(int len) throws IOException { + byte[] buff = new byte[len]; + read(buff); + for (int i = 0; i < buff.length; i++) { + if (buff[i] == 0) { + return new String(buff, 0, i, "ascii"); + } + } + return new String(buff, "ascii"); + } + + // Read 8 bit signed integer from stream + public byte readByte() throws IOException { + int ch = read(); + if (ch < 0) + throw new EOFException(); + return (byte) ch; + } + + // Read 16 bit signed integer from stream + public short readShort() throws IOException { + int ch1 = read(); + int ch2 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + return (short) (ch1 | (ch2 << 8)); + } + + // Read 32 bit signed integer from stream + public int readInt() throws IOException { + int ch1 = read(); + int ch2 = read(); + int ch3 = read(); + int ch4 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + if (ch3 < 0) + throw new EOFException(); + if (ch4 < 0) + throw new EOFException(); + return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24); + } + + // Read 64 bit signed integer from stream + public long readLong() throws IOException { + long ch1 = read(); + long ch2 = read(); + long ch3 = read(); + long ch4 = read(); + long ch5 = read(); + long ch6 = read(); + long ch7 = read(); + long ch8 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + if (ch3 < 0) + throw new EOFException(); + if (ch4 < 0) + throw new EOFException(); + if (ch5 < 0) + throw new EOFException(); + if (ch6 < 0) + throw new EOFException(); + if (ch7 < 0) + throw new EOFException(); + if (ch8 < 0) + throw new EOFException(); + return ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24) | (ch5 << 32) + | (ch6 << 40) | (ch7 << 48) | (ch8 << 56); + } + + // Read 8 bit unsigned integer from stream + public int readUnsignedByte() throws IOException { + int ch = read(); + if (ch < 0) + throw new EOFException(); + return ch; + } + + // Read 16 bit unsigned integer from stream + public int readUnsignedShort() throws IOException { + int ch1 = read(); + int ch2 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + return ch1 | (ch2 << 8); + } + + // Read 32 bit unsigned integer from stream + public long readUnsignedInt() throws IOException { + long ch1 = read(); + long ch2 = read(); + long ch3 = read(); + long ch4 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + if (ch3 < 0) + throw new EOFException(); + if (ch4 < 0) + throw new EOFException(); + return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24); + } + + public void close() throws IOException + { + finish(); + if(this == root) + stream.close(); + stream = null; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFWriter.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,377 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; + +/** + * Resource Interchange File Format (RIFF) stream encoder. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class RIFFWriter extends OutputStream { + + private interface RandomAccessWriter + { + public void seek(long chunksizepointer) throws IOException; + + public long getPointer() throws IOException; + + public void close() throws IOException; + + public void write(int b)throws IOException; + + public void write(byte[] b, int off, int len)throws IOException; + + public void write(byte[] bytes) throws IOException; + + public long length() throws IOException; + + public void setLength(long i) throws IOException; + } + + private static class RandomAccessFileWriter implements RandomAccessWriter + { + RandomAccessFile raf; + + public RandomAccessFileWriter(File file) throws FileNotFoundException + { + this.raf = new RandomAccessFile(file, "rw"); + } + + public RandomAccessFileWriter(String name) throws FileNotFoundException + { + this.raf = new RandomAccessFile(name, "rw"); + } + + public void seek(long chunksizepointer) throws IOException { + raf.seek(chunksizepointer); + } + + public long getPointer() throws IOException { + return raf.getFilePointer(); + } + + public void close() throws IOException { + raf.close(); + } + + public void write(int b) throws IOException { + raf.write(b); + } + + public void write(byte[] b, int off, int len) throws IOException { + raf.write(b,off,len); + } + + public void write(byte[] bytes) throws IOException { + raf.write(bytes); + } + + public long length() throws IOException + { + return raf.length(); + } + + public void setLength(long i) throws IOException + { + raf.setLength(i); + } + + } + + private static class RandomAccessByteWriter implements RandomAccessWriter + { + + byte[] buff = new byte[32]; + int length = 0; + int pos = 0; + byte[] s; + OutputStream stream; + + public RandomAccessByteWriter(OutputStream stream) + { + this.stream = stream; + } + + public void seek(long chunksizepointer) throws IOException { + pos = (int)chunksizepointer; + } + + public long getPointer() throws IOException { + return pos; + } + + public void close() throws IOException { + stream.write(buff,0,length); + stream.close(); + } + + public void write(int b) throws IOException { + if(s == null) s = new byte[1];; + s[0] = (byte)b; + write(s, 0, 1); + } + + public void write(byte[] b, int off, int len) throws IOException { + int newsize = pos + len; + if(newsize > length) setLength(newsize); + int end = off + len; + for (int i = off; i < end; i++) { + buff[pos++] = b[i]; + } + } + + public void write(byte[] bytes) throws IOException { + write(bytes,0,bytes.length); + } + + public long length() throws IOException { + return length; + } + + public void setLength(long i) throws IOException { + length = (int)i; + if(length > buff.length) + { + int newlen = Math.max(buff.length << 1, length); + byte[] newbuff = new byte[newlen]; + System.arraycopy(buff, 0, newbuff, 0, buff.length); + buff = newbuff; + } + } + + } + + private int chunktype = 0; // 0=RIFF, 1=LIST; 2=CHUNK + + private RandomAccessWriter raf; + + private long chunksizepointer; + + private long startpointer; + + private RIFFWriter childchunk = null; + + private boolean open = true; + + private boolean writeoverride = false; + + public RIFFWriter(String name, String format) throws IOException { + this(new RandomAccessFileWriter(name), format, 0); + } + + public RIFFWriter(File file, String format) throws IOException { + this(new RandomAccessFileWriter(file), format, 0); + } + + public RIFFWriter(OutputStream stream, String format) throws IOException { + this(new RandomAccessByteWriter(stream), format, 0); + } + + private RIFFWriter(RandomAccessWriter raf, String format, int chunktype) + throws IOException { + if (chunktype == 0) + if (raf.length() != 0) + raf.setLength(0); + this.raf = raf; + if (raf.getPointer() % 2 != 0) + raf.write(0); + + if (chunktype == 0) + raf.write("RIFF".getBytes("ascii")); + else if (chunktype == 1) + raf.write("LIST".getBytes("ascii")); + else + raf.write((format + " ").substring(0, 4).getBytes("ascii")); + chunksizepointer = raf.getPointer(); + this.chunktype = 2; + writeUnsignedInt(0); + this.chunktype = chunktype; + startpointer = raf.getPointer(); + if (chunktype != 2) + raf.write((format + " ").substring(0, 4).getBytes("ascii")); + + } + + public void seek(long pos) throws IOException { + raf.seek(pos); + } + + public long getFilePointer() throws IOException { + return raf.getPointer(); + } + + public void setWriteOverride(boolean writeoverride) { + this.writeoverride = writeoverride; + } + + public boolean getWriteOverride() { + return writeoverride; + } + + public void close() throws IOException { + if (!open) + return; + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + + int bakchunktype = chunktype; + long fpointer = raf.getPointer(); + raf.seek(chunksizepointer); + chunktype = 2; + writeUnsignedInt(fpointer - startpointer); + + if (bakchunktype == 0) + raf.close(); + else + raf.seek(fpointer); + open = false; + raf = null; + } + + public void write(int b) throws IOException { + if (!writeoverride) { + if (chunktype != 2) + throw new IllegalArgumentException( + "Only chunks can write bytes!"); + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + } + raf.write(b); + } + + public void write(byte b[], int off, int len) throws IOException { + if (!writeoverride) { + if (chunktype != 2) + throw new IllegalArgumentException( + "Only chunks can write bytes!"); + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + } + raf.write(b, off, len); + } + + public RIFFWriter writeList(String format) throws IOException { + if (chunktype == 2) + throw new IllegalArgumentException( + "Only LIST and RIFF can write lists!"); + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + childchunk = new RIFFWriter(this.raf, format, 1); + return childchunk; + } + + public RIFFWriter writeChunk(String format) throws IOException { + if (chunktype == 2) + throw new IllegalArgumentException( + "Only LIST and RIFF can write chunks!"); + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + childchunk = new RIFFWriter(this.raf, format, 2); + return childchunk; + } + + // Write ASCII chars to stream + public void writeString(String string) throws IOException { + byte[] buff = string.getBytes(); + write(buff); + } + + // Write ASCII chars to stream + public void writeString(String string, int len) throws IOException { + byte[] buff = string.getBytes(); + if (buff.length > len) + write(buff, 0, len); + else { + write(buff); + for (int i = buff.length; i < len; i++) + write(0); + } + } + + // Write 8 bit signed integer to stream + public void writeByte(int b) throws IOException { + write(b); + } + + // Write 16 bit signed integer to stream + public void writeShort(short b) throws IOException { + write((b >>> 0) & 0xFF); + write((b >>> 8) & 0xFF); + } + + // Write 32 bit signed integer to stream + public void writeInt(int b) throws IOException { + write((b >>> 0) & 0xFF); + write((b >>> 8) & 0xFF); + write((b >>> 16) & 0xFF); + write((b >>> 24) & 0xFF); + } + + // Write 64 bit signed integer to stream + public void writeLong(long b) throws IOException { + write((int) (b >>> 0) & 0xFF); + write((int) (b >>> 8) & 0xFF); + write((int) (b >>> 16) & 0xFF); + write((int) (b >>> 24) & 0xFF); + write((int) (b >>> 32) & 0xFF); + write((int) (b >>> 40) & 0xFF); + write((int) (b >>> 48) & 0xFF); + write((int) (b >>> 56) & 0xFF); + } + + // Write 8 bit unsigned integer to stream + public void writeUnsignedByte(int b) throws IOException { + writeByte((byte) b); + } + + // Write 16 bit unsigned integer to stream + public void writeUnsignedShort(int b) throws IOException { + writeShort((short) b); + } + + // Write 32 bit unsigned integer to stream + public void writeUnsignedInt(long b) throws IOException { + writeInt((int) b); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2GlobalRegion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2GlobalRegion.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * Soundfont global region. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2GlobalRegion extends SF2Region { + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Instrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Instrument.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,808 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.Patch; + +/** + * Soundfont instrument. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2Instrument extends ModelInstrument { + + protected String name = ""; + protected int preset = 0; + protected int bank = 0; + protected long library = 0; + protected long genre = 0; + protected long morphology = 0; + + protected SF2GlobalRegion globalregion = null; + + protected List regions = new ArrayList(); + + public SF2Instrument() { + super(null, null, null, null); + } + + public SF2Instrument(SF2Soundbank soundbank) { + super(soundbank, null, null, null); + } + + public String getName() { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public Patch getPatch() { + if(bank == 128) + return new ModelPatch(0, preset, true); + else + return new ModelPatch(bank << 7, preset, false); + } + + public void setPatch(Patch patch) + { + if(patch instanceof ModelPatch && ((ModelPatch)patch).isPercussion()) + { + bank = 128; + preset = patch.getProgram(); + } + else + { + bank = patch.getBank() >> 7; + preset = patch.getProgram(); + } + } + + public Object getData() { + return null; + } + + public long getGenre() { + return genre; + } + + public void setGenre(long genre) { + this.genre = genre; + } + + public long getLibrary() { + return library; + } + + public void setLibrary(long library) { + this.library = library; + } + + public long getMorphology() { + return morphology; + } + + public void setMorphology(long morphology) { + this.morphology = morphology; + } + + public List getRegions() { + return regions; + } + + public SF2GlobalRegion getGlobalRegion() + { + return globalregion; + } + + public void setGlobalZone(SF2GlobalRegion zone) + { + globalregion = zone; + } + + public String toString() + { + if(bank == 128) + return "Drumkit: " + name + " preset #" + preset; + else + return "Instrument: " + name + " bank #" + bank + " preset #" + preset; + } + + public ModelPerformer[] getPerformers() { + int performercount = 0; + for(SF2InstrumentRegion presetzone : regions) + performercount += presetzone.getLayer().getRegions().size(); + ModelPerformer[] performers = new ModelPerformer[performercount]; + int pi = 0; + + SF2GlobalRegion presetglobal = globalregion; + for(SF2InstrumentRegion presetzone : regions) + { + Map pgenerators = new HashMap(); + pgenerators.putAll(presetzone.getGenerators()); + if(presetglobal != null) + pgenerators.putAll(presetglobal.getGenerators()); + + SF2Layer layer = presetzone.getLayer(); + SF2GlobalRegion layerglobal = layer.getGlobalRegion(); + for(SF2LayerRegion layerzone : layer.getRegions()) + { + ModelPerformer performer = new ModelPerformer(); + if(layerzone.getSample() != null) + { + performer.setName(layerzone.getSample().getName()); + } + else + performer.setName(layer.getName()); + + performers[pi++] = performer; + + int keyfrom = 0; + int keyto = 127; + int velfrom = 0; + int velto = 127; + + if(layerzone.contains(SF2Region.GENERATOR_EXCLUSIVECLASS)) + { + performer.setExclusiveClass(layerzone.getInteger(SF2Region.GENERATOR_EXCLUSIVECLASS)); + } + if(layerzone.contains(SF2Region.GENERATOR_KEYRANGE)) + { + byte[] bytes = layerzone.getBytes(SF2Region.GENERATOR_KEYRANGE); + if(bytes[0] >= 0) + if(bytes[0] > keyfrom) keyfrom = bytes[0]; + if(bytes[1] >= 0) + if(bytes[1] < keyto) keyto = bytes[1]; + } + if(layerzone.contains(SF2Region.GENERATOR_VELRANGE)) + { + byte[] bytes = layerzone.getBytes(SF2Region.GENERATOR_VELRANGE); + if(bytes[0] >= 0) + if(bytes[0] > velfrom) velfrom = bytes[0]; + if(bytes[1] >= 0) + if(bytes[1] < velto) velto = bytes[1]; + } + if(presetzone.contains(SF2Region.GENERATOR_KEYRANGE)) + { + byte[] bytes = presetzone.getBytes(SF2Region.GENERATOR_KEYRANGE); + if(bytes[0] > keyfrom) keyfrom = bytes[0]; + if(bytes[1] < keyto) keyto = bytes[1]; + } + if(presetzone.contains(SF2Region.GENERATOR_VELRANGE)) + { + byte[] bytes = presetzone.getBytes(SF2Region.GENERATOR_VELRANGE); + if(bytes[0] > velfrom) velfrom = bytes[0]; + if(bytes[1] < velto) velto = bytes[1]; + } + performer.setKeyFrom(keyfrom); + performer.setKeyTo(keyto); + performer.setVelFrom(velfrom); + performer.setVelTo(velto); + + int startAddrsOffset = layerzone.getShort(SF2Region.GENERATOR_STARTADDRSOFFSET); + int endAddrsOffset = layerzone.getShort(SF2Region.GENERATOR_ENDADDRSOFFSET); + int startloopAddrsOffset = layerzone.getShort(SF2Region.GENERATOR_STARTLOOPADDRSOFFSET); + int endloopAddrsOffset = layerzone.getShort(SF2Region.GENERATOR_ENDLOOPADDRSOFFSET); + + startAddrsOffset += layerzone.getShort(SF2Region.GENERATOR_STARTADDRSCOARSEOFFSET) *32768; + endAddrsOffset += layerzone.getShort(SF2Region.GENERATOR_ENDADDRSCOARSEOFFSET) *32768; + startloopAddrsOffset += layerzone.getShort(SF2Region.GENERATOR_STARTLOOPADDRSCOARSEOFFSET) *32768; + endloopAddrsOffset += layerzone.getShort(SF2Region.GENERATOR_ENDLOOPADDRSCOARSEOFFSET) *32768; + startloopAddrsOffset -= startAddrsOffset; + endloopAddrsOffset -= startAddrsOffset; + + SF2Sample sample = layerzone.getSample(); + int rootkey = sample.originalPitch; + if(layerzone.getShort(SF2Region.GENERATOR_OVERRIDINGROOTKEY) != -1) + rootkey = layerzone.getShort(SF2Region.GENERATOR_OVERRIDINGROOTKEY); + float pitchcorrection = (-rootkey*100) + sample.pitchCorrection; + ModelByteBuffer buff = sample.getDataBuffer(); + ModelByteBuffer buff24 = sample.getData24Buffer(); + + if(startAddrsOffset != 0 || endAddrsOffset != 0) + { + buff = buff.subbuffer(startAddrsOffset*2, buff.capacity() + endAddrsOffset*2); + if(buff24 != null) + buff24 = buff24.subbuffer(startAddrsOffset, buff24.capacity() + endAddrsOffset); + + /* + if(startAddrsOffset < 0) startAddrsOffset = 0; + if(endAddrsOffset > (buff.capacity()/2-startAddrsOffset)) startAddrsOffset = (int)buff.capacity()/2-startAddrsOffset; + byte[] data = buff.array(); + int off = (int)buff.arrayOffset() + startAddrsOffset*2; + int len = (int)buff.capacity() + endAddrsOffset*2; + if(off+len > data.length) len = data.length - off; + buff = new ModelByteBuffer(data, off, len); + if(buff24 != null) + { + data = buff.array(); + off = (int)buff.arrayOffset() + startAddrsOffset; + len = (int)buff.capacity() + endAddrsOffset; + buff24 = new ModelByteBuffer(data, off, len); + } */ + } + + ModelByteBufferWavetable osc = new ModelByteBufferWavetable(buff, sample.getFormat(),pitchcorrection); + if(buff24 != null) osc.set8BitExtensionBuffer(buff24); + + Map generators = new HashMap(); + if(layerglobal != null) + generators.putAll(layerglobal.getGenerators()); + generators.putAll(layerzone.getGenerators()); + for(Map.Entry gen : pgenerators.entrySet()) + { + short val; + if(!generators.containsKey(gen.getKey())) + val = layerzone.getShort(gen.getKey()); + else + val = generators.get(gen.getKey()); + val += gen.getValue(); + generators.put(gen.getKey(), val); + } + + // SampleMode: + // 0 indicates a sound reproduced with no loop + // 1 indicates a sound which loops continuously + // 2 is unused but should be interpreted as indicating no loop + // 3 indicates a sound which loops for the duration of key depression then proceeds to play the remainder of the sample. + int sampleMode = getGeneratorValue(generators, SF2Region.GENERATOR_SAMPLEMODES); + if((sampleMode == 1) || (sampleMode == 3)) + if(sample.startLoop >= 0 && sample.endLoop > 0) + { + osc.setLoopStart((int)(sample.startLoop+startloopAddrsOffset)); + osc.setLoopLength((int)(sample.endLoop - sample.startLoop+endloopAddrsOffset - startloopAddrsOffset)); + if(sampleMode == 1) osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); + if(sampleMode == 3) osc.setLoopType(ModelWavetable.LOOP_TYPE_RELEASE); + } + performer.getOscillators().add(osc); + + + short volDelay = getGeneratorValue(generators, SF2Region.GENERATOR_DELAYVOLENV); + short volAttack = getGeneratorValue(generators, SF2Region.GENERATOR_ATTACKVOLENV); + short volHold = getGeneratorValue(generators, SF2Region.GENERATOR_HOLDVOLENV); + short volDecay = getGeneratorValue(generators, SF2Region.GENERATOR_DECAYVOLENV); + short volSustain = getGeneratorValue(generators, SF2Region.GENERATOR_SUSTAINVOLENV); + short volRelease = getGeneratorValue(generators, SF2Region.GENERATOR_RELEASEVOLENV); + + if(volHold != -12000) + { + short volKeyNumToHold = getGeneratorValue(generators, SF2Region.GENERATOR_KEYNUMTOVOLENVHOLD); + volHold += 60*volKeyNumToHold; + float fvalue = -volKeyNumToHold*128; + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_EG1_HOLD; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest))); + } + if(volDecay != -12000) + { + short volKeyNumToDecay = getGeneratorValue(generators, SF2Region.GENERATOR_KEYNUMTOVOLENVDECAY); + volDecay += 60*volKeyNumToDecay; + float fvalue = -volKeyNumToDecay*128; + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_EG1_DECAY; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest))); + } + + addTimecentValue(performer, ModelDestination.DESTINATION_EG1_DELAY, volDelay); + addTimecentValue(performer, ModelDestination.DESTINATION_EG1_ATTACK, volAttack); + addTimecentValue(performer, ModelDestination.DESTINATION_EG1_HOLD, volHold); + addTimecentValue(performer, ModelDestination.DESTINATION_EG1_DECAY, volDecay); + //float fvolsustain = (960-volSustain)*(1000.0f/960.0f); + + volSustain = (short)(1000 - volSustain); + if(volSustain < 0) volSustain = 0; + if(volSustain > 1000) volSustain = 1000; + + addValue(performer, ModelDestination.DESTINATION_EG1_SUSTAIN, volSustain); + addTimecentValue(performer, ModelDestination.DESTINATION_EG1_RELEASE, volRelease); + + if(getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOFILTERFC) != 0 + || getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOPITCH) != 0) + { + short modDelay = getGeneratorValue(generators, SF2Region.GENERATOR_DELAYMODENV); + short modAttack = getGeneratorValue(generators, SF2Region.GENERATOR_ATTACKMODENV); + short modHold = getGeneratorValue(generators, SF2Region.GENERATOR_HOLDMODENV); + short modDecay = getGeneratorValue(generators, SF2Region.GENERATOR_DECAYMODENV); + short modSustain = getGeneratorValue(generators, SF2Region.GENERATOR_SUSTAINMODENV); + short modRelease = getGeneratorValue(generators, SF2Region.GENERATOR_RELEASEMODENV); + + + if(modHold != -12000) + { + short modKeyNumToHold = getGeneratorValue(generators, SF2Region.GENERATOR_KEYNUMTOMODENVHOLD); + modHold += 60*modKeyNumToHold; + float fvalue = -modKeyNumToHold*128; + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_EG2_HOLD; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest))); + } + if(modDecay != -12000) + { + short modKeyNumToDecay = getGeneratorValue(generators, SF2Region.GENERATOR_KEYNUMTOMODENVDECAY); + modDecay += 60*modKeyNumToDecay; + float fvalue = -modKeyNumToDecay*128; + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_EG2_DECAY; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest))); + } + + addTimecentValue(performer, ModelDestination.DESTINATION_EG2_DELAY, modDelay); + addTimecentValue(performer, ModelDestination.DESTINATION_EG2_ATTACK, modAttack); + addTimecentValue(performer, ModelDestination.DESTINATION_EG2_HOLD, modHold); + addTimecentValue(performer, ModelDestination.DESTINATION_EG2_DECAY, modDecay); + if(modSustain < 0) modSustain = 0; + if(modSustain > 1000) modSustain = 1000; + addValue(performer, ModelDestination.DESTINATION_EG2_SUSTAIN, 1000 - modSustain); + addTimecentValue(performer, ModelDestination.DESTINATION_EG2_RELEASE, modRelease); + + if(getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOFILTERFC) != 0) + { + double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOFILTERFC); + ModelIdentifier src = ModelSource.SOURCE_EG2; + ModelIdentifier dest = ModelDestination.DESTINATION_FILTER_FREQ; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest))); + } + + if(getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOPITCH) != 0) + { + double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOPITCH); + ModelIdentifier src = ModelSource.SOURCE_EG2; + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest))); + } + + } + + if(getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOFILTERFC) != 0 + || getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOPITCH) != 0 + || getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOVOLUME) != 0) + { + short lfo_freq = getGeneratorValue(generators, SF2Region.GENERATOR_FREQMODLFO); + short lfo_delay = getGeneratorValue(generators, SF2Region.GENERATOR_DELAYMODLFO); + addTimecentValue(performer, ModelDestination.DESTINATION_LFO1_DELAY, lfo_delay); + addValue(performer, ModelDestination.DESTINATION_LFO1_FREQ, lfo_freq); + } + + short vib_freq = getGeneratorValue(generators, SF2Region.GENERATOR_FREQVIBLFO); + short vib_delay = getGeneratorValue(generators, SF2Region.GENERATOR_DELAYVIBLFO); + addTimecentValue(performer, ModelDestination.DESTINATION_LFO2_DELAY, vib_delay); + addValue(performer, ModelDestination.DESTINATION_LFO2_FREQ, vib_freq); + + + if(getGeneratorValue(generators, SF2Region.GENERATOR_VIBLFOTOPITCH) != 0) + { + double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_VIBLFOTOPITCH); + ModelIdentifier src = ModelSource.SOURCE_LFO2; + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src,ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR), fvalue, new ModelDestination(dest))); + } + + if(getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOFILTERFC) != 0) + { + double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOFILTERFC); + ModelIdentifier src = ModelSource.SOURCE_LFO1; + ModelIdentifier dest = ModelDestination.DESTINATION_FILTER_FREQ; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src,ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR), fvalue, new ModelDestination(dest))); + } + + if(getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOPITCH) != 0) + { + double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOPITCH); + ModelIdentifier src = ModelSource.SOURCE_LFO1; + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src,ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR), fvalue, new ModelDestination(dest))); + } + + if(getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOVOLUME) != 0) + { + double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOVOLUME); + ModelIdentifier src = ModelSource.SOURCE_LFO1; + ModelIdentifier dest = ModelDestination.DESTINATION_GAIN; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src,ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR), fvalue, new ModelDestination(dest))); + } + + if(layerzone.getShort(SF2Region.GENERATOR_KEYNUM) != -1) + { + double val = layerzone.getShort(SF2Region.GENERATOR_KEYNUM)/128.0; + addValue(performer, ModelDestination.DESTINATION_KEYNUMBER, val); + } + + if(layerzone.getShort(SF2Region.GENERATOR_VELOCITY) != -1) + { + double val = layerzone.getShort(SF2Region.GENERATOR_VELOCITY)/128.0; + addValue(performer, ModelDestination.DESTINATION_VELOCITY, val); + } + + if(getGeneratorValue(generators, SF2Region.GENERATOR_INITIALFILTERFC) < 13500) + { + short filter_freq = getGeneratorValue(generators, SF2Region.GENERATOR_INITIALFILTERFC); + short filter_q = getGeneratorValue(generators, SF2Region.GENERATOR_INITIALFILTERQ); + addValue(performer, ModelDestination.DESTINATION_FILTER_FREQ, filter_freq); + addValue(performer, ModelDestination.DESTINATION_FILTER_Q, filter_q); + } + + int tune = 100 * getGeneratorValue(generators, SF2Region.GENERATOR_COARSETUNE); + tune += getGeneratorValue(generators, SF2Region.GENERATOR_FINETUNE); + if(tune != 0) + { + addValue(performer, ModelDestination.DESTINATION_PITCH, (short)tune); + } + if(getGeneratorValue(generators, SF2Region.GENERATOR_PAN) != 0) + { + short val = getGeneratorValue(generators, SF2Region.GENERATOR_PAN); + addValue(performer, ModelDestination.DESTINATION_PAN, val); + } + if(getGeneratorValue(generators, SF2Region.GENERATOR_INITIALATTENUATION) != 0) + { + short val = getGeneratorValue(generators, SF2Region.GENERATOR_INITIALATTENUATION); + addValue(performer, ModelDestination.DESTINATION_GAIN, -0.376287f*val); + } + if(getGeneratorValue(generators, SF2Region.GENERATOR_CHORUSEFFECTSSEND) != 0) + { + short val = getGeneratorValue(generators, SF2Region.GENERATOR_CHORUSEFFECTSSEND); + addValue(performer, ModelDestination.DESTINATION_CHORUS, val); + } + if(getGeneratorValue(generators, SF2Region.GENERATOR_REVERBEFFECTSSEND) != 0) + { + short val = getGeneratorValue(generators, SF2Region.GENERATOR_REVERBEFFECTSSEND); + addValue(performer, ModelDestination.DESTINATION_REVERB, val); + } + if(getGeneratorValue(generators, SF2Region.GENERATOR_SCALETUNING) != 100) + { + short fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_SCALETUNING); + if(fvalue == 0) + { + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(null, rootkey * 100, new ModelDestination(dest))); + } + else + { + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(null, rootkey * (100 - fvalue), new ModelDestination(dest))); + } + + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), 128*fvalue, new ModelDestination(dest))); + + } + + performer.getConnectionBlocks().add(new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_NOTEON_VELOCITY, + new ModelTransform() + { + public double transform(double value) { + if(value < 0.5) + { + return 1 - value*2; + } + else + return 0; + } + } + ) + ,-2400,new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ))); + + + performer.getConnectionBlocks().add(new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO2, + ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(new ModelIdentifier("midi_cc","1",0), + ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR), + 50,new ModelDestination(ModelDestination.DESTINATION_PITCH))); + + if(layer.getGlobalRegion() != null) + for(SF2Modulator modulator : layer.getGlobalRegion().getModulators()) + convertModulator(performer, modulator); + for(SF2Modulator modulator : layerzone.getModulators()) + convertModulator(performer, modulator); + + if(presetglobal != null) + for(SF2Modulator modulator : presetglobal.getModulators()) + convertModulator(performer, modulator); + for(SF2Modulator modulator : presetzone.getModulators()) + convertModulator(performer, modulator); + + + + + } + } + return performers; + } + + private void convertModulator(ModelPerformer performer, SF2Modulator modulator) + { + ModelSource src1 = convertSource(modulator.getSourceOperator()); + ModelSource src2 = convertSource(modulator.getAmountSourceOperator()); + if(src1 == null && modulator.getSourceOperator() != 0) return; + if(src2 == null && modulator.getAmountSourceOperator() != 0) return; + double amount = modulator.getAmount(); + double[] amountcorrection = new double[1]; + ModelSource[] extrasrc = new ModelSource[1]; + amountcorrection[0] = 1; + ModelDestination dst = convertDestination(modulator.getDestinationOperator(), amountcorrection, extrasrc); + amount *= amountcorrection[0]; + if(dst == null) return; + if(modulator.getTransportOperator() == SF2Modulator.TRANSFORM_ABSOLUTE) + ((ModelStandardTransform)dst.getTransform()).setTransform(ModelStandardTransform.TRANSFORM_ABSOLUTE); + ModelConnectionBlock conn = new ModelConnectionBlock(src1,src2,amount,dst); + if(extrasrc[0] != null) conn.addSource(extrasrc[0]); + performer.getConnectionBlocks().add(conn); + + + } + + private static ModelSource convertSource(int src) + { + if(src == 0) return null; + ModelIdentifier id = null; + int idsrc = src & 0x7F; + if((src & SF2Modulator.SOURCE_MIDI_CONTROL) != 0) + { + id = new ModelIdentifier("midi_cc", Integer.toString(idsrc)); + } + else + { + if(idsrc == SF2Modulator.SOURCE_NOTE_ON_VELOCITY) + id = ModelSource.SOURCE_NOTEON_VELOCITY; + if(idsrc == SF2Modulator.SOURCE_NOTE_ON_KEYNUMBER) + id = ModelSource.SOURCE_NOTEON_KEYNUMBER; + if(idsrc == SF2Modulator.SOURCE_POLY_PRESSURE) + id = ModelSource.SOURCE_MIDI_POLY_PRESSURE; + if(idsrc == SF2Modulator.SOURCE_CHANNEL_PRESSURE) + id = ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; + if(idsrc == SF2Modulator.SOURCE_PITCH_WHEEL) + id = ModelSource.SOURCE_MIDI_PITCH; + if(idsrc == SF2Modulator.SOURCE_PITCH_SENSITIVITY) + id = new ModelIdentifier("midi_rpn", "0"); + + } + if(id == null) return null; + + ModelSource msrc = new ModelSource(id); + ModelStandardTransform transform = (ModelStandardTransform)msrc.getTransform(); + + if((SF2Modulator.SOURCE_DIRECTION_MAX_MIN & src) != 0) + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + else + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + + if((SF2Modulator.SOURCE_POLARITY_BIPOLAR & src) != 0) + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + else + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + + if((SF2Modulator.SOURCE_TYPE_CONCAVE & src) != 0) + transform.setTransform(ModelStandardTransform.TRANSFORM_CONCAVE); + if((SF2Modulator.SOURCE_TYPE_CONVEX & src) != 0) + transform.setTransform(ModelStandardTransform.TRANSFORM_CONVEX); + if((SF2Modulator.SOURCE_TYPE_SWITCH & src) != 0) + transform.setTransform(ModelStandardTransform.TRANSFORM_SWITCH); + + return msrc; + } + + protected static ModelDestination convertDestination(int dst, double[] amountcorrection, ModelSource[] extrasrc) + { + ModelIdentifier id = null; + switch (dst) { + case SF2Region.GENERATOR_INITIALFILTERFC : + id = ModelDestination.DESTINATION_FILTER_FREQ; + break; + case SF2Region.GENERATOR_INITIALFILTERQ : + id = ModelDestination.DESTINATION_FILTER_Q; + break; + case SF2Region.GENERATOR_CHORUSEFFECTSSEND : + id = ModelDestination.DESTINATION_CHORUS; + break; + case SF2Region.GENERATOR_REVERBEFFECTSSEND : + id = ModelDestination.DESTINATION_REVERB; + break; + case SF2Region.GENERATOR_PAN : + id = ModelDestination.DESTINATION_PAN; + break; + case SF2Region.GENERATOR_DELAYMODLFO : + id = ModelDestination.DESTINATION_LFO1_DELAY; + break; + case SF2Region.GENERATOR_FREQMODLFO : + id = ModelDestination.DESTINATION_LFO1_FREQ; + break; + case SF2Region.GENERATOR_DELAYVIBLFO : + id = ModelDestination.DESTINATION_LFO2_DELAY; + break; + case SF2Region.GENERATOR_FREQVIBLFO : + id = ModelDestination.DESTINATION_LFO2_FREQ; + break; + + + + case SF2Region.GENERATOR_DELAYMODENV : + id = ModelDestination.DESTINATION_EG2_DELAY; + break; + case SF2Region.GENERATOR_ATTACKMODENV : + id = ModelDestination.DESTINATION_EG2_ATTACK; + break; + case SF2Region.GENERATOR_HOLDMODENV : + id = ModelDestination.DESTINATION_EG2_HOLD; + break; + case SF2Region.GENERATOR_DECAYMODENV : + id = ModelDestination.DESTINATION_EG2_DECAY; + break; + case SF2Region.GENERATOR_SUSTAINMODENV : + id = ModelDestination.DESTINATION_EG2_SUSTAIN; + amountcorrection[0] = -1; + break; + case SF2Region.GENERATOR_RELEASEMODENV : + id = ModelDestination.DESTINATION_EG2_RELEASE; + break; + case SF2Region.GENERATOR_DELAYVOLENV : + id = ModelDestination.DESTINATION_EG1_DELAY; + break; + case SF2Region.GENERATOR_ATTACKVOLENV : + id = ModelDestination.DESTINATION_EG1_ATTACK; + break; + case SF2Region.GENERATOR_HOLDVOLENV : + id = ModelDestination.DESTINATION_EG1_HOLD; + break; + case SF2Region.GENERATOR_DECAYVOLENV : + id = ModelDestination.DESTINATION_EG1_DECAY; + break; + case SF2Region.GENERATOR_SUSTAINVOLENV : + id = ModelDestination.DESTINATION_EG1_SUSTAIN; + amountcorrection[0] = -1; + break; + case SF2Region.GENERATOR_RELEASEVOLENV : + id = ModelDestination.DESTINATION_EG1_RELEASE; + break; + case SF2Region.GENERATOR_KEYNUM : + id = ModelDestination.DESTINATION_KEYNUMBER; + break; + case SF2Region.GENERATOR_VELOCITY : + id = ModelDestination.DESTINATION_VELOCITY; + break; + + case SF2Region.GENERATOR_COARSETUNE : + amountcorrection[0] = 100; + id = ModelDestination.DESTINATION_PITCH; + break; + + case SF2Region.GENERATOR_FINETUNE : + id = ModelDestination.DESTINATION_PITCH; + break; + + case SF2Region.GENERATOR_INITIALATTENUATION : + id = ModelDestination.DESTINATION_GAIN; + amountcorrection[0] = -0.376287f; + break; + + case SF2Region.GENERATOR_VIBLFOTOPITCH : + id = ModelDestination.DESTINATION_PITCH; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_LFO2, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODLFOTOPITCH : + id = ModelDestination.DESTINATION_PITCH; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODLFOTOFILTERFC : + id = ModelDestination.DESTINATION_FILTER_FREQ; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODLFOTOVOLUME : + id = ModelDestination.DESTINATION_GAIN; + amountcorrection[0] = -0.376287f; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODENVTOPITCH : + id = ModelDestination.DESTINATION_PITCH; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_EG2, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODENVTOFILTERFC : + id = ModelDestination.DESTINATION_FILTER_FREQ; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_EG2, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + + default: + break; + } + if(id != null) return new ModelDestination(id); + return null; + } + + private void addTimecentValue(ModelPerformer performer, ModelIdentifier dest, short value) + { + double fvalue; + if(value == -12000) + fvalue = Double.NEGATIVE_INFINITY; + else + fvalue = value; + performer.getConnectionBlocks().add(new ModelConnectionBlock(fvalue, new ModelDestination(dest))); + } + + private void addValue(ModelPerformer performer, ModelIdentifier dest, short value) + { + double fvalue = value; + performer.getConnectionBlocks().add(new ModelConnectionBlock(fvalue, new ModelDestination(dest))); + } + + private void addValue(ModelPerformer performer, ModelIdentifier dest, double value) + { + double fvalue = value; + performer.getConnectionBlocks().add(new ModelConnectionBlock(fvalue, new ModelDestination(dest))); + } + + private short getGeneratorValue(Map generators, int gen) + { + if(generators.containsKey(gen)) return generators.get(gen); + return SF2Region.getDefaultValue(gen); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2InstrumentRegion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2InstrumentRegion.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * Soundfont instrument region. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2InstrumentRegion extends SF2Region { + + protected SF2Layer layer; + + public SF2Layer getLayer() { + return layer; + } + + public void setLayer(SF2Layer layer) { + this.layer = layer; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Layer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Layer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; + +import javax.sound.midi.SoundbankResource; + +/** + * Soundfont layer. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2Layer extends SoundbankResource { + + protected String name = ""; + protected SF2GlobalRegion globalregion = null; + protected List regions = new ArrayList(); + + public SF2Layer(SF2Soundbank soundBank) { + super(soundBank, null, null); + } + + public SF2Layer() { + super(null, null, null); + } + + public Object getData() { + return null; + } + + public String getName() { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public List getRegions() { + return regions; + } + + public SF2GlobalRegion getGlobalRegion() + { + return globalregion; + } + + public void setGlobalZone(SF2GlobalRegion zone) + { + globalregion = zone; + } + + public String toString() + { + return "Layer: " + name; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2LayerRegion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2LayerRegion.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * Soundfont layer region. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2LayerRegion extends SF2Region { + + protected SF2Sample sample; + + public SF2Sample getSample() { + return sample; + } + + public void setSample(SF2Sample sample) { + this.sample = sample; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Modulator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Modulator.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,96 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * Soundfont modulator container. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2Modulator { + + public final static int SOURCE_NONE = 0; + public final static int SOURCE_NOTE_ON_VELOCITY = 2; + public final static int SOURCE_NOTE_ON_KEYNUMBER = 3; + public final static int SOURCE_POLY_PRESSURE = 10; + public final static int SOURCE_CHANNEL_PRESSURE = 13; + public final static int SOURCE_PITCH_WHEEL = 14; + public final static int SOURCE_PITCH_SENSITIVITY = 16; + public final static int SOURCE_MIDI_CONTROL = 128*1; + + public final static int SOURCE_DIRECTION_MIN_MAX = 256*0; + public final static int SOURCE_DIRECTION_MAX_MIN = 256*1; + + public final static int SOURCE_POLARITY_UNIPOLAR = 512*0; + public final static int SOURCE_POLARITY_BIPOLAR = 512*1; + + public final static int SOURCE_TYPE_LINEAR = 1024*0; + public final static int SOURCE_TYPE_CONCAVE = 1024*1; + public final static int SOURCE_TYPE_CONVEX = 1024*2; + public final static int SOURCE_TYPE_SWITCH = 1024*3; + + public final static int TRANSFORM_LINEAR = 0; + public final static int TRANSFORM_ABSOLUTE = 2; + + protected int sourceOperator; + protected int destinationOperator; + protected short amount; + protected int amountSourceOperator; + protected int transportOperator; + + public short getAmount() { + return amount; + } + public void setAmount(short amount) { + this.amount = amount; + } + public int getAmountSourceOperator() { + return amountSourceOperator; + } + public void setAmountSourceOperator(int amountSourceOperator) { + this.amountSourceOperator = amountSourceOperator; + } + public int getTransportOperator() { + return transportOperator; + } + public void setTransportOperator(int transportOperator) { + this.transportOperator = transportOperator; + } + public int getDestinationOperator() { + return destinationOperator; + } + public void setDestinationOperator(int destinationOperator) { + this.destinationOperator = destinationOperator; + } + public int getSourceOperator() { + return sourceOperator; + } + public void setSourceOperator(int sourceOperator) { + this.sourceOperator = sourceOperator; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Region.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Region.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,179 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Soundfont general region. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2Region { + + public final static int GENERATOR_STARTADDRSOFFSET = 0; + public final static int GENERATOR_ENDADDRSOFFSET = 1; + public final static int GENERATOR_STARTLOOPADDRSOFFSET = 2; + public final static int GENERATOR_ENDLOOPADDRSOFFSET = 3; + public final static int GENERATOR_STARTADDRSCOARSEOFFSET = 4; + public final static int GENERATOR_MODLFOTOPITCH = 5; + public final static int GENERATOR_VIBLFOTOPITCH = 6; + public final static int GENERATOR_MODENVTOPITCH = 7; + public final static int GENERATOR_INITIALFILTERFC = 8; + public final static int GENERATOR_INITIALFILTERQ = 9; + public final static int GENERATOR_MODLFOTOFILTERFC = 10; + public final static int GENERATOR_MODENVTOFILTERFC = 11; + public final static int GENERATOR_ENDADDRSCOARSEOFFSET = 12; + public final static int GENERATOR_MODLFOTOVOLUME = 13; + public final static int GENERATOR_UNUSED1 = 14; + public final static int GENERATOR_CHORUSEFFECTSSEND = 15; + public final static int GENERATOR_REVERBEFFECTSSEND = 16; + public final static int GENERATOR_PAN = 17; + public final static int GENERATOR_UNUSED2 = 18; + public final static int GENERATOR_UNUSED3 = 19; + public final static int GENERATOR_UNUSED4 = 20; + public final static int GENERATOR_DELAYMODLFO = 21; + public final static int GENERATOR_FREQMODLFO = 22; + public final static int GENERATOR_DELAYVIBLFO = 23; + public final static int GENERATOR_FREQVIBLFO = 24; + public final static int GENERATOR_DELAYMODENV = 25; + public final static int GENERATOR_ATTACKMODENV = 26; + public final static int GENERATOR_HOLDMODENV = 27; + public final static int GENERATOR_DECAYMODENV = 28; + public final static int GENERATOR_SUSTAINMODENV = 29; + public final static int GENERATOR_RELEASEMODENV = 30; + public final static int GENERATOR_KEYNUMTOMODENVHOLD = 31; + public final static int GENERATOR_KEYNUMTOMODENVDECAY = 32; + public final static int GENERATOR_DELAYVOLENV = 33; + public final static int GENERATOR_ATTACKVOLENV = 34; + public final static int GENERATOR_HOLDVOLENV = 35; + public final static int GENERATOR_DECAYVOLENV = 36; + public final static int GENERATOR_SUSTAINVOLENV = 37; + public final static int GENERATOR_RELEASEVOLENV = 38; + public final static int GENERATOR_KEYNUMTOVOLENVHOLD = 39; + public final static int GENERATOR_KEYNUMTOVOLENVDECAY = 40; + public final static int GENERATOR_INSTRUMENT = 41; + public final static int GENERATOR_RESERVED1 = 42; + public final static int GENERATOR_KEYRANGE = 43; + public final static int GENERATOR_VELRANGE = 44; + public final static int GENERATOR_STARTLOOPADDRSCOARSEOFFSET = 45; + public final static int GENERATOR_KEYNUM = 46; + public final static int GENERATOR_VELOCITY = 47; + public final static int GENERATOR_INITIALATTENUATION = 48; + public final static int GENERATOR_RESERVED2 = 49; + public final static int GENERATOR_ENDLOOPADDRSCOARSEOFFSET = 50; + public final static int GENERATOR_COARSETUNE = 51; + public final static int GENERATOR_FINETUNE = 52; + public final static int GENERATOR_SAMPLEID = 53; + public final static int GENERATOR_SAMPLEMODES = 54; + public final static int GENERATOR_RESERVED3 = 55; + public final static int GENERATOR_SCALETUNING = 56; + public final static int GENERATOR_EXCLUSIVECLASS = 57; + public final static int GENERATOR_OVERRIDINGROOTKEY = 58; + public final static int GENERATOR_UNUSED5 = 59; + public final static int GENERATOR_ENDOPR = 60; + + protected Map generators = new HashMap(); + protected List modulators = new ArrayList(); + + public Map getGenerators() + { + return generators; + } + + public boolean contains(int generator) + { + return generators.containsKey(generator); + } + + static public short getDefaultValue(int generator) + { + if(generator == 8) return (short)13500; + if(generator == 21) return (short)-12000; + if(generator == 23) return (short)-12000; + if(generator == 25) return (short)-12000; + if(generator == 26) return (short)-12000; + if(generator == 27) return (short)-12000; + if(generator == 28) return (short)-12000; + if(generator == 30) return (short)-12000; + if(generator == 33) return (short)-12000; + if(generator == 34) return (short)-12000; + if(generator == 35) return (short)-12000; + if(generator == 36) return (short)-12000; + if(generator == 38) return (short)-12000; + if(generator == 43) return (short)0x7F00; + if(generator == 44) return (short)0x7F00; + if(generator == 46) return (short)-1; + if(generator == 47) return (short)-1; + if(generator == 56) return (short)100; + if(generator == 58) return (short)-1; + return 0; + } + public short getShort(int generator) + { + if(!contains(generator)) return getDefaultValue(generator); + return generators.get(generator); + } + + public void putShort(int generator, short value) + { + generators.put(generator, value); + } + + public byte[] getBytes(int generator) + { + int val = getInteger(generator); + byte[] bytes = new byte[2]; + bytes[0] = (byte)(0xFF & val); + bytes[1] = (byte)((0xFF00 & val) >> 8); + return bytes; + } + + public void putBytes(int generator, byte[] bytes) + { + generators.put(generator, (short)(bytes[0] + (bytes[1] << 8))); + } + + public int getInteger(int generator) + { + return 0xFFFF & getShort(generator); + } + + public void putInteger(int generator, int value) + { + generators.put(generator, (short)value); + } + + public List getModulators() + { + return modulators; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Sample.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Sample.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,219 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.InputStream; + +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; + +/** + * Soundfont sample storage. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2Sample extends SoundbankResource { + + protected String name = ""; + protected long startLoop = 0; + protected long endLoop = 0; + protected long sampleRate = 44100; + protected int originalPitch = 60; + protected byte pitchCorrection = 0; + protected int sampleLink = 0; + protected int sampleType = 0; + protected ModelByteBuffer data; + protected ModelByteBuffer data24; + + public SF2Sample(Soundbank soundBank) { + super(soundBank, null, AudioInputStream.class); + } + + public SF2Sample() { + super(null, null, AudioInputStream.class); + } + + public Object getData() { + + AudioFormat format = getFormat(); + /* + if(sampleFile != null) + { + FileInputStream fis; + try { + fis = new FileInputStream(sampleFile); + RIFFReader riff = new RIFFReader(fis); + if (!riff.getFormat().equals("RIFF")) + throw new RIFFInvalidDataException("Input stream is not a valid RIFF stream!"); + if (!riff.getType().equals("sfbk")) + throw new RIFFInvalidDataException("Input stream is not a valid SoundFont!"); + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if (chunk.getType().equals("sdta")) + { + while(chunk.hasNextChunk()) + { + RIFFReader chunkchunk = chunk.nextChunk(); + if(chunkchunk.getFormat().equals("smpl")) + { + chunkchunk.skip(sampleOffset); + return new AudioInputStream(chunkchunk, format, sampleLen); + } + } + } + } + } + return null; + } catch (Exception e) { + return new Throwable(e.toString()); + } + } + */ + InputStream is = data.getInputStream(); + if(is == null) return null; + return new AudioInputStream(is, format, data.capacity()); + } + + public ModelByteBuffer getDataBuffer() + { + return data; + } + + public ModelByteBuffer getData24Buffer() + { + return data24; + } + + public AudioFormat getFormat() + { + return new AudioFormat(sampleRate, 16, 1, true, false); + } + + public void setData(ModelByteBuffer data) { + this.data = data; + } + + public void setData(byte[] data) { + this.data = new ModelByteBuffer(data); + } + + public void setData(byte[] data, int offset, int length) { + this.data = new ModelByteBuffer(data, offset, length); + } + + public void setData24(ModelByteBuffer data24) { + this.data24 = data24; + } + + public void setData24(byte[] data24) { + this.data24 = new ModelByteBuffer(data24); + } + + public void setData24(byte[] data24, int offset, int length) { + this.data24 = new ModelByteBuffer(data24, offset, length); + } + /* + public void setData(File file, int offset, int length) { + this.data = null; + this.sampleFile = file; + this.sampleOffset = offset; + this.sampleLen = length; + } + */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getEndLoop() { + return endLoop; + } + + public void setEndLoop(long endLoop) { + this.endLoop = endLoop; + } + + public int getOriginalPitch() { + return originalPitch; + } + + public void setOriginalPitch(int originalPitch) { + this.originalPitch = originalPitch; + } + + public byte getPitchCorrection() { + return pitchCorrection; + } + + public void setPitchCorrection(byte pitchCorrection) { + this.pitchCorrection = pitchCorrection; + } + + public int getSampleLink() { + return sampleLink; + } + + public void setSampleLink(int sampleLink) { + this.sampleLink = sampleLink; + } + + public long getSampleRate() { + return sampleRate; + } + + public void setSampleRate(long sampleRate) { + this.sampleRate = sampleRate; + } + + public int getSampleType() { + return sampleType; + } + + public void setSampleType(int sampleType) { + this.sampleType = sampleType; + } + + public long getStartLoop() { + return startLoop; + } + + public void setStartLoop(long startLoop) { + this.startLoop = startLoop; + } + + public String toString() + { + return "Sample: " + name; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,1000 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.Instrument; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; + + +/** + * + * A SoundFont 2.04 soundbank reader. + * + * Based on SoundFont 2.04 specification from: + *

    + * http://developer.creative.com + *
    + * http://www.soundfont.com/ ; + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2Soundbank implements Soundbank { + + // version of the Sound Font RIFF file + protected int major = 2; + protected int minor = 1; + + // target Sound Engine + protected String targetEngine = "EMU8000"; + + // Sound Font Bank Name + protected String name = "untitled"; + + // Sound ROM Name + protected String romName = null; + + // Sound ROM Version + protected int romVersionMajor = -1; + protected int romVersionMinor = -1; + + // Date of Creation of the Bank + protected String creationDate = null; + + // Sound Designers and Engineers for the Bank + protected String engineers = null; + + // Product for which the Bank was intended + protected String product = null; + + // Copyright message + protected String copyright = null; + + // Comments + protected String comments = null; + + // The SoundFont tools used to create and alter the bank + protected String tools = null; + + // The Sample Data loaded from the SoundFont + private ModelByteBuffer sampleData = null; + private ModelByteBuffer sampleData24 = null; + private File sampleFile = null; + private boolean largeFormat = false; + + private List instruments = new ArrayList(); + private List layers = new ArrayList(); + private List samples = new ArrayList(); + + public SF2Soundbank() + { + } + + public SF2Soundbank(URL url) throws IOException { + + InputStream is = url.openStream(); + try + { + readSoundbank(is); + } + finally + { + is.close(); + } + } + + public SF2Soundbank(File file) throws IOException { + largeFormat = true; + sampleFile = file; + InputStream is = new FileInputStream(file); + try + { + readSoundbank(is); + } + finally + { + is.close(); + } + } + + public SF2Soundbank(InputStream inputstream) throws IOException { + readSoundbank(inputstream); + } + + private void readSoundbank(InputStream inputstream) throws IOException { + RIFFReader riff = new RIFFReader(inputstream); + if (!riff.getFormat().equals("RIFF")) + throw new RIFFInvalidFormatException("Input stream is not a valid RIFF stream!"); + if (!riff.getType().equals("sfbk")) + throw new RIFFInvalidFormatException("Input stream is not a valid SoundFont!"); + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if (chunk.getType().equals("INFO")) + readInfoChunk(chunk); + if (chunk.getType().equals("sdta")) + readSdtaChunk(chunk); + if (chunk.getType().equals("pdta")) + readPdtaChunk(chunk); + } + } + } + + private void readInfoChunk(RIFFReader riff) throws IOException { + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if(format.equals("ifil")) + { + major = chunk.readUnsignedShort(); + minor = chunk.readUnsignedShort(); + } + else if(format.equals("isng")) + this.targetEngine = chunk.readString(chunk.available()); + else if(format.equals("INAM")) + this.name = chunk.readString(chunk.available()); + else if(format.equals("irom")) + this.romName = chunk.readString(chunk.available()); + else if(format.equals("iver")) + { + romVersionMajor = chunk.readUnsignedShort(); + romVersionMinor = chunk.readUnsignedShort(); + } + else if(format.equals("ICRD")) + this.creationDate = chunk.readString(chunk.available()); + else if(format.equals("IENG")) + this.engineers = chunk.readString(chunk.available()); + else if(format.equals("IPRD")) + this.product = chunk.readString(chunk.available()); + else if(format.equals("ICOP")) + this.copyright = chunk.readString(chunk.available()); + else if(format.equals("ICMT")) + this.comments = chunk.readString(chunk.available()); + else if(format.equals("ISFT")) + this.tools = chunk.readString(chunk.available()); + + } + } + + private void readSdtaChunk(RIFFReader riff) throws IOException { + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("smpl")) { + if(!largeFormat) + { + byte[] sampleData = new byte[chunk.available()]; + + int read = 0; + int avail = chunk.available(); + while(read != avail) + { + if(avail - read > 65536) + { + chunk.read(sampleData, read, 65536); + read += 65536; + } + else + { + chunk.read(sampleData, read, avail - read); + read = avail; + } + + } + this.sampleData = new ModelByteBuffer(sampleData); + //chunk.read(sampleData); + } + else + { + this.sampleData = new ModelByteBuffer(sampleFile, chunk.getFilePointer(), chunk.available()); + } + + } + if (chunk.getFormat().equals("sm24")) { + if(!largeFormat) + { + byte[] sampleData24 = new byte[chunk.available()]; + //chunk.read(sampleData24); + + int read = 0; + int avail = chunk.available(); + while(read != avail) + { + if(avail - read > 65536) + { + chunk.read(sampleData24, read, 65536); + read += 65536; + } + else + { + chunk.read(sampleData24, read, avail - read); + read = avail; + } + + } + this.sampleData24 = new ModelByteBuffer(sampleData24); + } + else + this.sampleData24 = new ModelByteBuffer(sampleFile, chunk.getFilePointer(), chunk.available()); + + } + } + } + + private void readPdtaChunk(RIFFReader riff) throws IOException { + + List presets = new ArrayList(); + List presets_bagNdx = new ArrayList(); + List presets_splits_gen = new ArrayList(); + List presets_splits_mod = new ArrayList(); + + List instruments = new ArrayList(); + List instruments_bagNdx = new ArrayList(); + List instruments_splits_gen = new ArrayList(); + List instruments_splits_mod = new ArrayList(); + + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if(format.equals("phdr")) // Preset Header / Instrument + { + if(chunk.available() % 38 != 0) throw new RIFFInvalidDataException(); + int count = chunk.available() / 38; + for (int i = 0; i < count; i++) { + SF2Instrument preset = new SF2Instrument(this); + preset.name = chunk.readString(20); + preset.preset = chunk.readUnsignedShort(); + preset.bank = chunk.readUnsignedShort(); + presets_bagNdx.add(chunk.readUnsignedShort()); + preset.library = chunk.readUnsignedInt(); + preset.genre = chunk.readUnsignedInt(); + preset.morphology = chunk.readUnsignedInt(); + presets.add(preset); + if(i != count - 1) this.instruments.add(preset); + } + } + else if(format.equals("pbag")) // Preset Zones / Instruments splits + { + if(chunk.available() % 4 != 0) throw new RIFFInvalidDataException(); + int count = chunk.available() / 4; + + // Skip first record + { + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + while( presets_splits_gen.size() < gencount) + presets_splits_gen.add(null); + while( presets_splits_mod.size() < modcount) + presets_splits_mod.add(null); + count--; + } + + int offset = presets_bagNdx.get(0); + // Offset should be 0 (but just case) + for (int i = 0; i < offset; i++) { + if(count == 0) throw new RIFFInvalidDataException(); + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + while( presets_splits_gen.size() < gencount) + presets_splits_gen.add(null); + while( presets_splits_mod.size() < modcount) + presets_splits_mod.add(null); + count--; + } + + for (int i = 0; i < presets_bagNdx.size()-1; i++) { + int zone_count = presets_bagNdx.get(i+1) - presets_bagNdx.get(i); + SF2Instrument preset = presets.get(i); + for (int ii = 0; ii < zone_count; ii++) { + if(count == 0) throw new RIFFInvalidDataException(); + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + SF2InstrumentRegion split = new SF2InstrumentRegion(); + preset.regions.add(split); + while( presets_splits_gen.size() < gencount) + presets_splits_gen.add(split); + while( presets_splits_mod.size() < modcount) + presets_splits_mod.add(split); + count--; + } + } + } + else if(format.equals("pmod")) // Preset Modulators / Split Modulators + { + for (int i = 0; i < presets_splits_mod.size(); i++) { + SF2Modulator modulator = new SF2Modulator(); + modulator.sourceOperator = chunk.readUnsignedShort(); + modulator.destinationOperator = chunk.readUnsignedShort(); + modulator.amount = chunk.readShort(); + modulator.amountSourceOperator = chunk.readUnsignedShort(); + modulator.transportOperator= chunk.readUnsignedShort(); + SF2InstrumentRegion split = presets_splits_mod.get(i); + if(split != null) split.modulators.add(modulator); + } + } + else if(format.equals("pgen")) // Preset Generators / Split Generators + { + for (int i = 0; i < presets_splits_gen.size(); i++) { + int operator = chunk.readUnsignedShort(); + short amount = chunk.readShort(); + SF2InstrumentRegion split = presets_splits_gen.get(i); + if(split != null) split.generators.put(operator, amount); + } + } + else if(format.equals("inst")) // Instrument Header / Layers + { + if(chunk.available() % 22 != 0) throw new RIFFInvalidDataException(); + int count = chunk.available() / 22; + for (int i = 0; i < count; i++) { + SF2Layer layer = new SF2Layer(this); + layer.name = chunk.readString(20); + instruments_bagNdx.add(chunk.readUnsignedShort()); + instruments.add(layer); + if(i != count - 1) this.layers.add(layer); + } + } + else if(format.equals("ibag")) // Instrument Zones / Layer splits + { + if(chunk.available() % 4 != 0) throw new RIFFInvalidDataException(); + int count = chunk.available() / 4; + + // Skip first record + { + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + while( instruments_splits_gen.size() < gencount) + instruments_splits_gen.add(null); + while( instruments_splits_mod.size() < modcount) + instruments_splits_mod.add(null); + count--; + } + + int offset = instruments_bagNdx.get(0); + // Offset should be 0 (but just case) + for (int i = 0; i < offset; i++) { + if(count == 0) throw new RIFFInvalidDataException(); + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + while( instruments_splits_gen.size() < gencount) + instruments_splits_gen.add(null); + while( instruments_splits_mod.size() < modcount) + instruments_splits_mod.add(null); + count--; + } + + for (int i = 0; i < instruments_bagNdx.size()-1; i++) { + int zone_count = instruments_bagNdx.get(i+1) - instruments_bagNdx.get(i); + SF2Layer layer = layers.get(i); + for (int ii = 0; ii < zone_count; ii++) { + if(count == 0) throw new RIFFInvalidDataException(); + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + SF2LayerRegion split = new SF2LayerRegion(); + layer.regions.add(split); + while( instruments_splits_gen.size() < gencount) + instruments_splits_gen.add(split); + while( instruments_splits_mod.size() < modcount) + instruments_splits_mod.add(split); + count--; + } + } + + } + else if(format.equals("imod")) // Instrument Modulators / Split Modulators + { + for (int i = 0; i < instruments_splits_mod.size(); i++) { + SF2Modulator modulator = new SF2Modulator(); + modulator.sourceOperator = chunk.readUnsignedShort(); + modulator.destinationOperator = chunk.readUnsignedShort(); + modulator.amount = chunk.readShort(); + modulator.amountSourceOperator = chunk.readUnsignedShort(); + modulator.transportOperator= chunk.readUnsignedShort(); + SF2LayerRegion split = instruments_splits_gen.get(i); + if(split != null) split.modulators.add(modulator); + } + } + else if(format.equals("igen")) // Instrument Generators / Split Generators + { + for (int i = 0; i < instruments_splits_gen.size(); i++) { + int operator = chunk.readUnsignedShort(); + short amount = chunk.readShort(); + SF2LayerRegion split = instruments_splits_gen.get(i); + if(split != null) split.generators.put(operator, amount); + } + } + else if(format.equals("shdr")) // Sample Headers + { + if(chunk.available() % 46 != 0) throw new RIFFInvalidDataException(); + int count = chunk.available() / 46; + for (int i = 0; i < count; i++) { + SF2Sample sample = new SF2Sample(this); + sample.name = chunk.readString(20); + long start = chunk.readUnsignedInt(); + long end = chunk.readUnsignedInt(); + sample.data = sampleData.subbuffer(start*2, end*2, true); + if(sampleData24 != null) + sample.data24 = sampleData24.subbuffer(start, end, true); + /* + sample.data = new ModelByteBuffer(sampleData, (int)(start*2), (int)((end - start)*2)); + if(sampleData24 != null) + sample.data24 = new ModelByteBuffer(sampleData24, (int)start, (int)(end - start)); */ + sample.startLoop = chunk.readUnsignedInt() - start; + sample.endLoop = chunk.readUnsignedInt() - start; + if(sample.startLoop < 0) sample.startLoop = -1; + if(sample.endLoop < 0) sample.endLoop = -1; + sample.sampleRate = chunk.readUnsignedInt(); + sample.originalPitch = chunk.readUnsignedByte(); + sample.pitchCorrection = chunk.readByte(); + sample.sampleLink = chunk.readUnsignedShort(); + sample.sampleType = chunk.readUnsignedShort(); + if(i != count - 1) this.samples.add(sample); + } + } + } + + Iterator liter = this.layers.iterator(); + while (liter.hasNext()) { + SF2Layer layer = liter.next(); + Iterator siter = layer.regions.iterator(); + SF2Region globalsplit = null; + while (siter.hasNext()) { + SF2LayerRegion split = siter.next(); + if(split.generators.get(SF2LayerRegion.GENERATOR_SAMPLEID) != null) + { + int sampleid = split.generators.get(SF2LayerRegion.GENERATOR_SAMPLEID); + split.generators.remove(SF2LayerRegion.GENERATOR_SAMPLEID); + split.sample = samples.get(sampleid); + } + else + { + globalsplit = split; + } + } + if(globalsplit != null) + { + layer.getRegions().remove(globalsplit); + SF2GlobalRegion gsplit = new SF2GlobalRegion(); + gsplit.generators = globalsplit.generators; + gsplit.modulators = globalsplit.modulators; + layer.setGlobalZone(gsplit); + } + } + + + Iterator iiter = this.instruments.iterator(); + while (iiter.hasNext()) { + SF2Instrument instrument = iiter.next(); + Iterator siter = instrument.regions.iterator(); + SF2Region globalsplit = null; + while (siter.hasNext()) { + SF2InstrumentRegion split = siter.next(); + if(split.generators.get(SF2LayerRegion.GENERATOR_INSTRUMENT) != null) + { + int instrumentid = split.generators.get(SF2InstrumentRegion.GENERATOR_INSTRUMENT); + split.generators.remove(SF2LayerRegion.GENERATOR_INSTRUMENT); + split.layer = layers.get(instrumentid); + } + else + { + globalsplit = split; + } + } + + if(globalsplit != null) + { + instrument.getRegions().remove(globalsplit); + SF2GlobalRegion gsplit = new SF2GlobalRegion(); + gsplit.generators = globalsplit.generators; + gsplit.modulators = globalsplit.modulators; + instrument.setGlobalZone(gsplit); + } + } + + } + + public void save(String name) throws IOException + { + writeSoundbank(new RIFFWriter(name, "sfbk")); + } + + public void save(File file) throws IOException + { + writeSoundbank(new RIFFWriter(file, "sfbk")); + } + + public void save(OutputStream out) throws IOException + { + writeSoundbank(new RIFFWriter(out, "sfbk")); + } + + private void writeSoundbank(RIFFWriter writer) throws IOException + { + writeInfo(writer.writeList("INFO")); + writeSdtaChunk(writer.writeList("sdta")); + writePdtaChunk(writer.writeList("pdta")); + writer.close(); + } + + private void writeInfoStringChunk(RIFFWriter writer, String name, String value) throws IOException + { + if(value == null) return; + RIFFWriter chunk = writer.writeChunk(name); + chunk.writeString(value); + int len = value.getBytes("ascii").length; + chunk.write(0); + len++; + if(len % 2 != 0) chunk.write(0); + } + + private void writeInfo(RIFFWriter writer) throws IOException + { + if(this.targetEngine == null) this.targetEngine = "EMU8000"; + if(this.name == null) this.name = ""; + + RIFFWriter ifil_chunk = writer.writeChunk("ifil"); + ifil_chunk.writeUnsignedShort(this.major); + ifil_chunk.writeUnsignedShort(this.minor); + writeInfoStringChunk(writer, "isng", this.targetEngine); + writeInfoStringChunk(writer, "INAM", this.name); + writeInfoStringChunk(writer, "irom", this.romName); + if(romVersionMajor != -1) + { + RIFFWriter iver_chunk = writer.writeChunk("iver"); + iver_chunk.writeUnsignedShort(this.romVersionMajor); + iver_chunk.writeUnsignedShort(this.romVersionMinor); + } + writeInfoStringChunk(writer, "ICRD", this.creationDate); + writeInfoStringChunk(writer, "IENG", this.engineers); + writeInfoStringChunk(writer, "IPRD", this.product); + writeInfoStringChunk(writer, "ICOP", this.copyright); + writeInfoStringChunk(writer, "ICMT", this.comments); + writeInfoStringChunk(writer, "ISFT", this.tools); + + writer.close(); + } + + private void writeSdtaChunk(RIFFWriter writer) throws IOException + { + + byte[] pad = new byte[32]; + + RIFFWriter smpl_chunk = writer.writeChunk("smpl"); + for(SF2Sample sample : samples) + { + ModelByteBuffer data = sample.getDataBuffer(); + data.writeTo(smpl_chunk); + /* + smpl_chunk.write(data.array(), + data.arrayOffset(), + data.capacity()); + */ + smpl_chunk.write(pad); + smpl_chunk.write(pad); + } + if(major < 2) return; + if(major == 2 && minor < 4) return; + + + for(SF2Sample sample : samples) + { + ModelByteBuffer data24 = sample.getData24Buffer(); + if(data24 == null) return; + } + + RIFFWriter sm24_chunk = writer.writeChunk("sm24"); + for(SF2Sample sample : samples) + { + ModelByteBuffer data = sample.getData24Buffer(); + data.writeTo(sm24_chunk); + /* + sm24_chunk.write(data.array(), + data.arrayOffset(), + data.capacity());*/ + smpl_chunk.write(pad); + } + } + + private void writeModulators(RIFFWriter writer, List modulators) throws IOException + { + for(SF2Modulator modulator : modulators) + { + writer.writeUnsignedShort(modulator.sourceOperator); + writer.writeUnsignedShort(modulator.destinationOperator); + writer.writeShort(modulator.amount); + writer.writeUnsignedShort(modulator.amountSourceOperator); + writer.writeUnsignedShort(modulator.transportOperator); + } + } + + private void writeGenerators(RIFFWriter writer, Map generators) throws IOException + { + Short keyrange = (Short)generators.get(SF2Region.GENERATOR_KEYRANGE); + Short velrange = (Short)generators.get(SF2Region.GENERATOR_VELRANGE); + if(keyrange != null) + { + writer.writeUnsignedShort(SF2Region.GENERATOR_KEYRANGE); + writer.writeShort(keyrange); + } + if(velrange != null) + { + writer.writeUnsignedShort(SF2Region.GENERATOR_VELRANGE); + writer.writeShort(velrange); + } + for(Map.Entry generator : generators.entrySet()) + { + if(generator.getKey() == SF2Region.GENERATOR_KEYRANGE) continue; + if(generator.getKey() == SF2Region.GENERATOR_VELRANGE) continue; + writer.writeUnsignedShort(generator.getKey()); + writer.writeShort(generator.getValue()); + } + } + + private void writePdtaChunk(RIFFWriter writer) throws IOException + { + + RIFFWriter phdr_chunk = writer.writeChunk("phdr"); + int phdr_zone_count = 0; + for(SF2Instrument preset : this.instruments) + { + phdr_chunk.writeString(preset.name, 20); + phdr_chunk.writeUnsignedShort(preset.preset); + phdr_chunk.writeUnsignedShort(preset.bank); + phdr_chunk.writeUnsignedShort(phdr_zone_count); + if(preset.getGlobalRegion() != null) + phdr_zone_count += 1; + phdr_zone_count += preset.getRegions().size(); + phdr_chunk.writeUnsignedInt(preset.library); + phdr_chunk.writeUnsignedInt(preset.genre); + phdr_chunk.writeUnsignedInt(preset.morphology); + } + phdr_chunk.writeString("EOP", 20); + phdr_chunk.writeUnsignedShort(0); + phdr_chunk.writeUnsignedShort(0); + phdr_chunk.writeUnsignedShort(phdr_zone_count); + phdr_chunk.writeUnsignedInt(0); + phdr_chunk.writeUnsignedInt(0); + phdr_chunk.writeUnsignedInt(0); + + + RIFFWriter pbag_chunk = writer.writeChunk("pbag"); + int pbag_gencount = 0; + int pbag_modcount = 0; + for(SF2Instrument preset : this.instruments) + { + if(preset.getGlobalRegion() != null) + { + pbag_chunk.writeUnsignedShort(pbag_gencount); + pbag_chunk.writeUnsignedShort(pbag_modcount); + pbag_gencount += preset.getGlobalRegion().getGenerators().size(); + pbag_modcount += preset.getGlobalRegion().getModulators().size(); + } + for(SF2InstrumentRegion region : preset.getRegions()) + { + pbag_chunk.writeUnsignedShort(pbag_gencount); + pbag_chunk.writeUnsignedShort(pbag_modcount); + if(layers.indexOf(region.layer) != -1) + pbag_gencount += 1; // One generator is used to reference to instrument record + pbag_gencount += region.getGenerators().size(); + pbag_modcount += region.getModulators().size(); + + } + } + pbag_chunk.writeUnsignedShort(pbag_gencount); + pbag_chunk.writeUnsignedShort(pbag_modcount); + + RIFFWriter pmod_chunk = writer.writeChunk("pmod"); + for(SF2Instrument preset : this.instruments) + { + if(preset.getGlobalRegion() != null) + writeModulators(pmod_chunk, preset.getGlobalRegion().getModulators()); + for(SF2InstrumentRegion region : preset.getRegions()) + writeModulators(pmod_chunk, region.getModulators()); + } + pmod_chunk.write(new byte[10]); + + RIFFWriter pgen_chunk = writer.writeChunk("pgen"); + for(SF2Instrument preset : this.instruments) + { + if(preset.getGlobalRegion() != null) + writeGenerators(pgen_chunk, preset.getGlobalRegion().getGenerators()); + for(SF2InstrumentRegion region : preset.getRegions()) + { + writeGenerators(pgen_chunk, region.getGenerators()); + int ix = (int)layers.indexOf(region.layer); + if(ix != -1) + { + pgen_chunk.writeUnsignedShort(SF2Region.GENERATOR_INSTRUMENT); + pgen_chunk.writeShort((short)ix); + } + } + } + pgen_chunk.write(new byte[4]); + + RIFFWriter inst_chunk = writer.writeChunk("inst"); + int inst_zone_count = 0; + for(SF2Layer instrument : this.layers) + { + inst_chunk.writeString(instrument.name, 20); + inst_chunk.writeUnsignedShort(inst_zone_count); + if(instrument.getGlobalRegion() != null) + inst_zone_count += 1; + inst_zone_count += instrument.getRegions().size(); + } + inst_chunk.writeString("EOI", 20); + inst_chunk.writeUnsignedShort(inst_zone_count); + + + RIFFWriter ibag_chunk = writer.writeChunk("ibag"); + int ibag_gencount = 0; + int ibag_modcount = 0; + for(SF2Layer instrument : this.layers) + { + if(instrument.getGlobalRegion() != null) + { + ibag_chunk.writeUnsignedShort(ibag_gencount); + ibag_chunk.writeUnsignedShort(ibag_modcount); + ibag_gencount += instrument.getGlobalRegion().getGenerators().size(); + ibag_modcount += instrument.getGlobalRegion().getModulators().size(); + } + for(SF2LayerRegion region : instrument.getRegions()) + { + ibag_chunk.writeUnsignedShort(ibag_gencount); + ibag_chunk.writeUnsignedShort(ibag_modcount); + if(samples.indexOf(region.sample) != -1) + ibag_gencount += 1; // One generator is used to reference to instrument record + ibag_gencount += region.getGenerators().size(); + ibag_modcount += region.getModulators().size(); + + } + } + ibag_chunk.writeUnsignedShort(ibag_gencount); + ibag_chunk.writeUnsignedShort(ibag_modcount); + + + RIFFWriter imod_chunk = writer.writeChunk("imod"); + for(SF2Layer instrument : this.layers) + { + if(instrument.getGlobalRegion() != null) + writeModulators(imod_chunk, instrument.getGlobalRegion().getModulators()); + for(SF2LayerRegion region : instrument.getRegions()) + writeModulators(imod_chunk, region.getModulators()); + } + imod_chunk.write(new byte[10]); + + RIFFWriter igen_chunk = writer.writeChunk("igen"); + for(SF2Layer instrument : this.layers) + { + if(instrument.getGlobalRegion() != null) + writeGenerators(igen_chunk, instrument.getGlobalRegion().getGenerators()); + for(SF2LayerRegion region : instrument.getRegions()) + { + writeGenerators(igen_chunk, region.getGenerators()); + int ix = samples.indexOf(region.sample); + if(ix != -1) + { + igen_chunk.writeUnsignedShort(SF2Region.GENERATOR_SAMPLEID); + igen_chunk.writeShort((short)ix); + } + } + } + igen_chunk.write(new byte[4]); + + + RIFFWriter shdr_chunk = writer.writeChunk("shdr"); + long sample_pos = 0; + for(SF2Sample sample : samples) + { + shdr_chunk.writeString(sample.name, 20); + long start = sample_pos; + sample_pos += sample.data.capacity()/2; + long end = sample_pos; + long startLoop = sample.startLoop + start; + long endLoop = sample.endLoop + start; + if(startLoop < start) startLoop = start; + if(endLoop > end) endLoop = end; + shdr_chunk.writeUnsignedInt(start); + shdr_chunk.writeUnsignedInt(end); + shdr_chunk.writeUnsignedInt(startLoop); + shdr_chunk.writeUnsignedInt(endLoop); + shdr_chunk.writeUnsignedInt(sample.sampleRate); + shdr_chunk.writeUnsignedByte(sample.originalPitch); + shdr_chunk.writeByte(sample.pitchCorrection); + shdr_chunk.writeUnsignedShort(sample.sampleLink); + shdr_chunk.writeUnsignedShort(sample.sampleType); + sample_pos += 32; + } + shdr_chunk.writeString("EOS", 20); + shdr_chunk.write(new byte[26]); + + } + + public String getName() { + return name; + } + + public String getVersion() { + return major + "." + minor; + } + + public String getVendor() { + return engineers; + } + + public String getDescription() { + return comments; + } + + public void setName(String s) { + name = s; + } + + public void setVendor(String s) { + engineers = s; + } + + public void setDescription(String s) { + comments = s; + } + + public SoundbankResource[] getResources() { + SoundbankResource[] resources = new SoundbankResource[layers.size() + samples.size()]; + int j = 0; + for (int i = 0; i < layers.size(); i++) + resources[j++] = layers.get(i); + for (int i = 0; i < samples.size(); i++) + resources[j++] = samples.get(i); + return resources; + } + + public SF2Instrument[] getInstruments() { + SF2Instrument[] inslist_array = instruments.toArray(new SF2Instrument[instruments.size()]); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + + public SF2Layer[] getLayers() { + return layers.toArray(new SF2Layer[layers.size()]); + } + + public SF2Sample[] getSamples() { + return samples.toArray(new SF2Sample[samples.size()]); + } + + public Instrument getInstrument(Patch patch) { + int program = patch.getProgram(); + int bank = patch.getBank(); + boolean percussion = false; + if (patch instanceof ModelPatch) + percussion = ((ModelPatch) patch).isPercussion(); + for (Instrument instrument : instruments) { + Patch patch2 = instrument.getPatch(); + int program2 = patch2.getProgram(); + int bank2 = patch2.getBank(); + if (program == program2 && bank == bank2) { + boolean percussion2 = false; + if (patch2 instanceof ModelPatch) + percussion2 = ((ModelPatch) patch2).isPercussion(); + if (percussion == percussion2) + return instrument; + } + } + return null; + } + + public String getCreationDate() { + return creationDate; + } + + public void setCreationDate(String creationDate) { + this.creationDate = creationDate; + } + + public String getProduct() { + return product; + } + + public void setProduct(String product) { + this.product = product; + } + + public String getRomName() { + return romName; + } + + public void setRomName(String romName) { + this.romName = romName; + } + + public int getRomVersionMajor() { + return romVersionMajor; + } + + public void setRomVersionMajor(int romVersionMajor) { + this.romVersionMajor = romVersionMajor; + } + + public int getRomVersionMinor() { + return romVersionMinor; + } + + public void setRomVersionMinor(int romVersionMinor) { + this.romVersionMinor = romVersionMinor; + } + + public String getTargetEngine() { + return targetEngine; + } + + public void setTargetEngine(String targetEngine) { + this.targetEngine = targetEngine; + } + + public String getTools() { + return tools; + } + + public void setTools(String tools) { + this.tools = tools; + } + + public void addResource(SoundbankResource resource) + { + if(resource instanceof SF2Instrument) instruments.add((SF2Instrument)resource); + if(resource instanceof SF2Layer) layers.add((SF2Layer)resource); + if(resource instanceof SF2Sample) samples.add((SF2Sample)resource); + } + + public void removeResource(SoundbankResource resource) + { + if(resource instanceof SF2Instrument) instruments.remove((SF2Instrument)resource); + if(resource instanceof SF2Layer) layers.remove((SF2Layer)resource); + if(resource instanceof SF2Sample) samples.remove((SF2Sample)resource); + } + + public void addInstrument(SF2Instrument resource) + { + instruments.add(resource); + } + + public void removeInstrument(SF2Instrument resource) + { + instruments.remove(resource); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2SoundbankReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2SoundbankReader.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,86 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Soundbank; +import javax.sound.midi.spi.SoundbankReader; + +/** + * + * This class is used to connect the SF2SoundBank class + * to the SoundbankReader SPI interface. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SF2SoundbankReader extends SoundbankReader { + + + public Soundbank getSoundbank(URL url) throws InvalidMidiDataException, IOException { + try + { + return new SF2Soundbank(url); + } + catch(RIFFInvalidFormatException e) + { + return null; + } + } + + public Soundbank getSoundbank(InputStream stream) throws InvalidMidiDataException, IOException { + try + { + stream.mark(512); + return new SF2Soundbank(stream); + } + catch(RIFFInvalidFormatException e) + { + stream.reset(); + return null; + } + } + + public Soundbank getSoundbank(File file) throws InvalidMidiDataException, IOException { + if(!file.getPath().toLowerCase().endsWith(".sf2")) return null; + try + { + return new SF2Soundbank(file); + } + catch(RIFFInvalidFormatException e) + { + return null; + } + } + + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SimpleInstrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SimpleInstrument.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,210 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; + +import javax.sound.midi.Patch; + +/** + * A simple instrument that is made of other ModelInstrument, ModelPerformer + * objects. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class SimpleInstrument extends ModelInstrument { + + private class SimpleInstrumentPart { + ModelPerformer[] performers; + + int keyFrom; + + int keyTo; + + int velFrom; + + int velTo; + + int exclusiveClass; + } + + protected int preset = 0; + + protected int bank = 0; + + protected boolean percussion = false; + + protected String name = ""; + + protected List parts = new ArrayList(); + + public SimpleInstrument() { + super(null, null, null, null); + } + + public void clear() { + parts.clear(); + } + + public void add(ModelPerformer[] performers, int keyFrom, int keyTo, + int velFrom, int velTo, int exclusiveClass) { + SimpleInstrumentPart part = new SimpleInstrumentPart(); + part.performers = performers; + part.keyFrom = keyFrom; + part.keyTo = keyTo; + part.velFrom = velFrom; + part.velTo = velTo; + part.exclusiveClass = exclusiveClass; + parts.add(part); + } + + public void add(ModelPerformer[] performers, int keyFrom, int keyTo, + int velFrom, int velTo) { + add(performers, keyFrom, keyTo, velFrom, velTo, -1); + } + + public void add(ModelPerformer[] performers, int keyFrom, int keyTo) { + add(performers, keyFrom, keyTo, 0, 127, -1); + } + + public void add(ModelPerformer[] performers) { + add(performers, 0, 127, 0, 127, -1); + } + + public void add(ModelPerformer performer, int keyFrom, int keyTo, + int velFrom, int velTo, int exclusiveClass) { + add(new ModelPerformer[] { performer }, keyFrom, keyTo, velFrom, velTo, + exclusiveClass); + } + + public void add(ModelPerformer performer, int keyFrom, int keyTo, + int velFrom, int velTo) { + add(new ModelPerformer[] { performer }, keyFrom, keyTo, velFrom, velTo); + } + + public void add(ModelPerformer performer, int keyFrom, int keyTo) { + add(new ModelPerformer[] { performer }, keyFrom, keyTo); + } + + public void add(ModelPerformer performer) { + add(new ModelPerformer[] { performer }); + } + + public void add(ModelInstrument ins, int keyFrom, int keyTo, int velFrom, + int velTo, int exclusiveClass) { + add(ins.getPerformers(), keyFrom, keyTo, velFrom, velTo, exclusiveClass); + } + + public void add(ModelInstrument ins, int keyFrom, int keyTo, int velFrom, + int velTo) { + add(ins.getPerformers(), keyFrom, keyTo, velFrom, velTo); + } + + public void add(ModelInstrument ins, int keyFrom, int keyTo) { + add(ins.getPerformers(), keyFrom, keyTo); + } + + public void add(ModelInstrument ins) { + add(ins.getPerformers()); + } + + public ModelPerformer[] getPerformers() { + + int percount = 0; + for (SimpleInstrumentPart part : parts) + if (part.performers != null) + percount += part.performers.length; + + ModelPerformer[] performers = new ModelPerformer[percount]; + int px = 0; + for (SimpleInstrumentPart part : parts) { + if (part.performers != null) { + for (ModelPerformer mperfm : part.performers) { + ModelPerformer performer = new ModelPerformer(); + performer.setName(getName()); + performers[px++] = performer; + + performer.setDefaultConnectionsEnabled(mperfm + .isDefaultConnectionsEnabled()); + performer.setKeyFrom(mperfm.getKeyFrom()); + performer.setKeyTo(mperfm.getKeyTo()); + performer.setVelFrom(mperfm.getVelFrom()); + performer.setVelTo(mperfm.getVelTo()); + performer.setExclusiveClass(mperfm.getExclusiveClass()); + performer.setSelfNonExclusive(mperfm.isSelfNonExclusive()); + performer.setReleaseTriggered(mperfm.isReleaseTriggered()); + if (part.exclusiveClass != -1) + performer.setExclusiveClass(part.exclusiveClass); + if (part.keyFrom > performer.getKeyFrom()) + performer.setKeyFrom(part.keyFrom); + if (part.keyTo < performer.getKeyTo()) + performer.setKeyTo(part.keyTo); + if (part.velFrom > performer.getVelFrom()) + performer.setVelFrom(part.velFrom); + if (part.velTo < performer.getVelTo()) + performer.setVelTo(part.velTo); + performer.getOscillators().addAll(mperfm.getOscillators()); + performer.getConnectionBlocks().addAll( + mperfm.getConnectionBlocks()); + } + } + } + + return performers; + } + + public Object getData() { + return null; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public ModelPatch getPatch() { + return new ModelPatch(bank, preset, percussion); + } + + public void setPatch(Patch patch) { + if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) { + percussion = true; + bank = patch.getBank(); + preset = patch.getProgram(); + } else { + percussion = false; + bank = patch.getBank(); + preset = patch.getProgram(); + } + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SimpleSoundbank.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SimpleSoundbank.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,155 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.sound.midi.Instrument; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; + +/** + * A simple soundbank that contains instruments and soundbankresources. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class SimpleSoundbank implements Soundbank { + + String name = ""; + + String version = ""; + + String vendor = ""; + + String description = ""; + + List resources = new ArrayList(); + + List instruments = new ArrayList(); + + public String getName() { + return name; + } + + public String getVersion() { + return version; + } + + public String getVendor() { + return vendor; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setName(String name) { + this.name = name; + } + + public void setVendor(String vendor) { + this.vendor = vendor; + } + + public void setVersion(String version) { + this.version = version; + } + + public SoundbankResource[] getResources() { + return (SoundbankResource[]) resources + .toArray(new SoundbankResource[resources.size()]); + } + + public Instrument[] getInstruments() { + Instrument[] inslist_array = (Instrument[]) instruments.toArray(new Instrument[resources + .size()]); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + + public Instrument getInstrument(Patch patch) { + int program = patch.getProgram(); + int bank = patch.getBank(); + boolean percussion = false; + if (patch instanceof ModelPatch) + percussion = ((ModelPatch) patch).isPercussion(); + for (Instrument instrument : instruments) { + Patch patch2 = instrument.getPatch(); + int program2 = patch2.getProgram(); + int bank2 = patch2.getBank(); + if (program == program2 && bank == bank2) { + boolean percussion2 = false; + if (patch2 instanceof ModelPatch) + percussion2 = ((ModelPatch) patch2).isPercussion(); + if (percussion == percussion2) + return instrument; + } + } + return null; + } + + public void addResource(SoundbankResource resource) { + if (resource instanceof Instrument) + instruments.add((Instrument) resource); + else + resources.add(resource); + } + + public void removeResource(SoundbankResource resource) { + if (resource instanceof Instrument) + instruments.remove((Instrument) resource); + else + resources.remove(resource); + } + + public void addInstrument(Instrument resource) { + instruments.add(resource); + } + + public void removeInstrument(Instrument resource) { + instruments.remove(resource); + } + + public void addAllInstruments(Soundbank soundbank) { + for(Instrument ins : soundbank.getInstruments()) + addInstrument(ins); + } + + public void removeAllInstruments(Soundbank soundbank) { + for(Instrument ins : soundbank.getInstruments()) + removeInstrument(ins); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAbstractResampler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAbstractResampler.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,422 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; +import java.util.Arrays; + +import javax.sound.midi.MidiChannel; +import javax.sound.midi.VoiceStatus; + +/** + * + * Abstract resampler class. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public abstract class SoftAbstractResampler implements SoftResampler { + + private class ModelAbstractResamplerStream implements SoftResamplerStreamer { + AudioFloatInputStream stream; + + boolean stream_eof = false; + + int loopmode; + boolean loopdirection = true; // true = forward + + float loopstart; + + float looplen; + + float target_pitch; + + float[] current_pitch = new float[1]; + + boolean started; + + boolean eof; + + boolean loopreadevent = false; + + int sector_pos = 0; + + int sector_size = 400; + + int sector_loopstart = -1; + + boolean markset = false; + + int marklimit = 0; + + int streampos = 0; + + int nrofchannels = 2; + + boolean noteOff_flag = false; + + float[][] ibuffer; + boolean ibuffer_order = true; + + float[] sbuffer; + + int pad; + + int pad2; + + float[] ix = new float[1]; + + int[] ox = new int[1]; + + float samplerateconv = 1; + + float pitchcorrection = 0; + + boolean streammarked = true; + + public ModelAbstractResamplerStream() { + pad = getPadding(); + pad2 = getPadding() * 2; + ibuffer = new float[2][sector_size + pad2]; + ibuffer_order = true; + } + + public void noteOn(MidiChannel channel, VoiceStatus voice, + int noteNumber, int velocity) { + } + + public void noteOff(int velocity) { + noteOff_flag = true; + } + + public void open(ModelWavetable osc, float outputsamplerate) + throws IOException { + + eof = false; + nrofchannels = osc.getChannels(); + if (ibuffer.length < nrofchannels) + { + ibuffer = new float[nrofchannels][sector_size + pad2]; + } + + stream = osc.openStream(); + streampos = 0; + stream_eof = false; + pitchcorrection = osc.getPitchcorrection(); + samplerateconv = stream.getFormat().getSampleRate() + / outputsamplerate; + looplen = osc.getLoopLength(); + loopstart = osc.getLoopStart(); + sector_loopstart = (int) (loopstart / sector_size); + sector_loopstart = sector_loopstart - 1; + + sector_pos = 0; + + if (sector_loopstart < 0) + sector_loopstart = 0; + started = false; + loopmode = osc.getLoopType(); + + if (loopmode != 0) { + markset = false; + marklimit = nrofchannels * (int) (looplen + pad2 + 1); + } else + markset = true; + // loopmode = 0; + + target_pitch = samplerateconv; + current_pitch[0] = samplerateconv; + + ibuffer_order = true; + loopdirection = true; + noteOff_flag = false; + + for (int i = 0; i < nrofchannels; i++) + Arrays.fill(ibuffer[i], sector_size, sector_size + pad2, 0); + ix[0] = pad; + eof = false; + loopreadevent = false; + + ix[0] = sector_size + pad; + sector_pos = -1; + streampos = -sector_size; + + nextBuffer(); + } + + public void setPitch(float pitch) { + /* + this.pitch = (float) Math.pow(2f, + (pitchcorrection + pitch) / 1200.0f) + * samplerateconv; + */ + this.target_pitch = (float) Math.exp( + (pitchcorrection + pitch) * (Math.log(2.0) / 1200.0)) + * samplerateconv; + + if (!started) + current_pitch[0] = this.target_pitch; + } + + public void nextBuffer() throws IOException { + if (ix[0] < pad) { + if (markset) { + // reset to target sector + stream.reset(); + ix[0] += streampos - (sector_loopstart * sector_size); + sector_pos = sector_loopstart; + streampos = sector_pos * sector_size; + ; + + // and go one sector backward + ix[0] += sector_size; + sector_pos -= 1; + streampos -= sector_size; + stream_eof = false; + } + } + + if (ix[0] >= sector_size + pad) + if (stream_eof) { + eof = true; + return; + } + + if(ix[0] >= sector_size*4 + pad) + { + int skips = (int)( (ix[0] - sector_size*4 + pad)/sector_size ); + ix[0] -= sector_size*skips; + sector_pos += skips; + streampos += sector_size*skips; + stream.skip(sector_size*skips); + } + + while (ix[0] >= sector_size + pad) { + if (!markset) + if (sector_pos + 1 == sector_loopstart) { + stream.mark(marklimit); + markset = true; + } + ix[0] -= sector_size; + sector_pos++; + streampos += sector_size; + + for (int c = 0; c < nrofchannels; c++) { + float[] cbuffer = ibuffer[c]; + for (int i = 0; i < pad2; i++) + cbuffer[i] = cbuffer[i + sector_size]; + } + + int ret; + if (nrofchannels == 1) + ret = stream.read(ibuffer[0], pad2, sector_size); + else { + int slen = sector_size * nrofchannels; + if (sbuffer == null || sbuffer.length < slen) + sbuffer = new float[slen]; + int sret = stream.read(sbuffer, 0, slen); + if (sret == -1) + ret = -1; + else { + ret = sret / nrofchannels; + for (int i = 0; i < nrofchannels; i++) { + float[] buff = ibuffer[i]; + int ix = i; + int ix_step = nrofchannels; + int ox = pad2; + for (int j = 0; j < ret; j++, ix += ix_step, ox++) + buff[ox] = sbuffer[ix]; + } + } + + } + + if (ret == -1) { + ret = 0; + stream_eof = true; + for (int i = 0; i < nrofchannels; i++) + Arrays.fill(ibuffer[i], pad2, pad2 + sector_size, 0f); + return; + } + if (ret != sector_size) + for (int i = 0; i < nrofchannels; i++) + Arrays.fill(ibuffer[i], pad2 + ret, pad2 + sector_size, + 0f); + + ibuffer_order = true; + + } + + } + + public void reverseBuffers() + { + ibuffer_order = !ibuffer_order; + for (int c = 0; c < nrofchannels; c++) + { + float[] cbuff = ibuffer[c]; + int len = cbuff.length-1; + int len2 = cbuff.length/2; + for (int i = 0; i < len2; i++) { + float x = cbuff[i]; + cbuff[i] = cbuff[len - i]; + cbuff[len - i] = x; + } + } + } + + public int read(float[][] buffer, int offset, int len) + throws IOException { + + if (eof) + return -1; + + if(noteOff_flag) + if((loopmode & 2) != 0) + if(loopdirection) + loopmode = 0; + + + float pitchstep = (target_pitch - current_pitch[0]) / len; + float[] current_pitch = this.current_pitch; + started = true; + + int[] ox = this.ox; + ox[0] = offset; + int ox_end = len + offset; + + float ixend = sector_size + pad; + if(!loopdirection) ixend = pad; + while (ox[0] != ox_end) { + nextBuffer(); + if(!loopdirection) + { + // If we are in backward playing part of pingpong or reverse loop + + if (streampos < (loopstart + pad)) { + ixend = loopstart - streampos + pad2; + if(ix[0] <= ixend) + { + if((loopmode & 4) != 0) + { + // Ping pong loop, change loopdirection + loopdirection = true; + ixend = sector_size + pad; + continue; + } + + ix[0] += looplen; + ixend = pad; + continue; + } + } + + if(ibuffer_order != loopdirection) reverseBuffers(); + + ix[0] = (sector_size + pad2) - ix[0]; + ixend = (sector_size + pad2) - ixend; + ixend++; + + float bak_ix = ix[0]; + int bak_ox = ox[0]; + float bak_pitch = current_pitch[0]; + for (int i = 0; i < nrofchannels; i++) + if (buffer[i] != null) { + ix[0] = bak_ix; + ox[0] = bak_ox; + current_pitch[0] = bak_pitch; + interpolate(ibuffer[i], ix, ixend, current_pitch, pitchstep, + buffer[i], ox, ox_end); + } + + ix[0] = (sector_size + pad2) - ix[0]; + ixend--; + ixend = (sector_size + pad2) - ixend; + + if (eof) { + current_pitch[0] = this.target_pitch; + return ox[0] - offset; + } + + continue; + } + if (loopmode != 0) + if (streampos + sector_size > (looplen + loopstart + pad)) { + ixend = loopstart + looplen - streampos + pad2; + if (ix[0] >= ixend) { + if((loopmode & 4) != 0 || (loopmode & 8) != 0 ) + { + // Ping pong or revese loop, change loopdirection + loopdirection = false; + ixend = pad; + continue; + } + ixend = sector_size + pad; + ix[0] -= looplen; + continue; + } + } + + if(ibuffer_order != loopdirection) reverseBuffers(); + + float bak_ix = ix[0]; + int bak_ox = ox[0]; + float bak_pitch = current_pitch[0]; + for (int i = 0; i < nrofchannels; i++) + if (buffer[i] != null) { + ix[0] = bak_ix; + ox[0] = bak_ox; + current_pitch[0] = bak_pitch; + interpolate(ibuffer[i], ix, ixend, current_pitch, pitchstep, + buffer[i], ox, ox_end); + } + + if (eof) { + current_pitch[0] = this.target_pitch; + return ox[0] - offset; + } + } + + current_pitch[0] = this.target_pitch; + return len; + } + + public void close() throws IOException { + stream.close(); + } + } + + public abstract int getPadding(); + + public abstract void interpolate(float[] in, float[] in_offset, + float in_end, float[] pitch, float pitchstep, float[] out, + int[] out_offset, int out_end); + + public SoftResamplerStreamer openStreamer() { + return new ModelAbstractResamplerStream(); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioBuffer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,112 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; + +/** + * This class is used to store audio buffer. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftAudioBuffer { + + private int size; + + private float[] buffer; + + private boolean empty = true; + + private AudioFormat format; + + private AudioFloatConverter converter; + + private byte[] converter_buffer; + + public SoftAudioBuffer(int size, AudioFormat format) { + this.size = size; + this.format = format; + converter = AudioFloatConverter.getConverter(format); + } + + public AudioFormat getFormat() { + return format; + } + + public int getSize() { + return size; + } + + public void clear() { + if (!empty) { + Arrays.fill(buffer, 0); + empty = true; + } + } + + public boolean isSilent() { + return empty; + } + + public float[] array() { + empty = false; + if (buffer == null) + buffer = new float[size]; + return buffer; + } + + public void get(byte[] buffer, int channel) { + + int framesize_pc = (format.getFrameSize() / format.getChannels()); + int c_len = size * framesize_pc; + if (converter_buffer == null || converter_buffer.length < c_len) + converter_buffer = new byte[c_len]; + + if (format.getChannels() == 1) { + converter.toByteArray(array(), size, buffer); + } else { + converter.toByteArray(array(), size, converter_buffer); + if (channel >= format.getChannels()) + return; + int z_stepover = format.getChannels() * framesize_pc; + int k_stepover = framesize_pc; + for (int j = 0; j < framesize_pc; j++) { + int k = j; + int z = channel * framesize_pc + j; + for (int i = 0; i < size; i++) { + buffer[z] = converter_buffer[k]; + z += z_stepover; + k += k_stepover; + } + } + } + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioProcessor.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * Audio processor interface. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface SoftAudioProcessor { + + public void globalParameterControlChange(int[] slothpath, long param, + long value); + + public void init(SoftSynthesizer synthesizer); + + public void setInput(int pin, SoftAudioBuffer input); + + public void setOutput(int pin, SoftAudioBuffer output); + + public void setMixMode(boolean mix); + + public void processAudio(); + + public void processControlLogic(); + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.SourceDataLine; + +/** + * This is a processor object that writes into SourceDataLine + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftAudioPusher implements Runnable { + + private volatile boolean active = false; + + private SourceDataLine sourceDataLine = null; + + private Thread audiothread; + + private AudioInputStream ais; + + private byte[] buffer; + + public SoftAudioPusher(SourceDataLine sourceDataLine, AudioInputStream ais, + int workbuffersizer) { + this.ais = ais; + this.buffer = new byte[workbuffersizer]; + this.sourceDataLine = sourceDataLine; + } + + public synchronized void start() { + if (active) + return; + active = true; + audiothread = new Thread(this); + audiothread.setPriority(Thread.MAX_PRIORITY); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + audiothread.start(); + } + + public synchronized void stop() { + if (!active) + return; + active = false; + try { + audiothread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void run() { + byte[] buffer = SoftAudioPusher.this.buffer; + AudioInputStream ais = SoftAudioPusher.this.ais; + SourceDataLine sourceDataLine = SoftAudioPusher.this.sourceDataLine; + + try { + while (active) { + // Read from audio source + ais.read(buffer); + // Write byte buffer to source output + sourceDataLine.write(buffer, 0, buffer.length); + } + } catch (IOException e) { + active = false; + e.printStackTrace(); + } + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,1502 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.MidiChannel; +import javax.sound.midi.Patch; + +/** + * + * Software Synthesizer MIDI channel class. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftChannel implements MidiChannel, ModelDirectedPlayer { + private static boolean[] dontResetControls = new boolean[128]; + static { + for (int i = 0; i < dontResetControls.length; i++) + dontResetControls[i] = false; + + dontResetControls[0] = true; // Bank Select (MSB) + dontResetControls[32] = true; // Bank Select (LSB) + dontResetControls[7] = true; // Channel Volume (MSB) + dontResetControls[8] = true; // Balance (MSB) + dontResetControls[10] = true; // Pan (MSB) + dontResetControls[11] = true; // Expression (MSB) + dontResetControls[91] = true; // Effects 1 Depth (default: Reverb Send) + dontResetControls[92] = true; // Effects 2 Depth (default: Tremolo Depth) + dontResetControls[93] = true; // Effects 3 Depth (default: Chorus Send) + dontResetControls[94] = true; // Effects 4 Depth (default: Celeste [Detune] Depth) + dontResetControls[95] = true; // Effects 5 Depth (default: Phaser Depth) + dontResetControls[70] = true; // Sound Controller 1 (default: Sound Variation) + dontResetControls[71] = true; // Sound Controller 2 (default: Timbre / Harmonic Quality) + dontResetControls[72] = true; // Sound Controller 3 (default: Release Time) + dontResetControls[73] = true; // Sound Controller 4 (default: Attack Time) + dontResetControls[74] = true; // Sound Controller 5 (default: Brightness) + dontResetControls[75] = true; // Sound Controller 6 (GM2 default: Decay Time) + dontResetControls[76] = true; // Sound Controller 7 (GM2 default: Vibrato Rate) + dontResetControls[77] = true; // Sound Controller 8 (GM2 default: Vibrato Depth) + dontResetControls[78] = true; // Sound Controller 9 (GM2 default: Vibrato Delay) + dontResetControls[79] = true; // Sound Controller 10 (GM2 default: Undefined) + dontResetControls[120] = true; // All Sound Off + dontResetControls[121] = true; // Reset All Controllers + dontResetControls[122] = true; // Local Control On/Off + dontResetControls[123] = true; // All Notes Off + dontResetControls[124] = true; // Omni Mode Off + dontResetControls[125] = true; // Omni Mode On + dontResetControls[126] = true; // Poly Mode Off + dontResetControls[127] = true; // Poly Mode On + + dontResetControls[6] = true; // Data Entry (MSB) + dontResetControls[38] = true; // Data Entry (LSB) + dontResetControls[96] = true; // Data Increment + dontResetControls[97] = true; // Data Decrement + dontResetControls[98] = true; // Non-Registered Parameter Number (LSB) + dontResetControls[99] = true; // Non-Registered Parameter Number(MSB) + dontResetControls[100] = true; // RPN = Null + dontResetControls[101] = true; // RPN = Null + + + } + + private static final int RPN_NULL_VALUE = (127 << 7) + 127; + private int rpn_control = RPN_NULL_VALUE; + private int nrpn_control = RPN_NULL_VALUE; + + protected double portamento_time = 1; // keyschanges per control buffer time + protected int[] portamento_lastnote = new int[128]; + protected int portamento_lastnote_ix = 0; + private int portamento_control_note = -1; + private boolean portamento = false; + private boolean mono = false; + private boolean mute = false; + private boolean solo = false; + private boolean solomute = false; + + private Object control_mutex; + + private int channel; + + private SoftVoice[] voices; + + private int bank; + + private int program; + + private SoftSynthesizer synthesizer; + private SoftMainMixer mainmixer; + + private int[] polypressure = new int[128]; + + private int channelpressure = 0; + + private int[] controller = new int[128]; + + private int pitchbend; + + private double[] co_midi_pitch = new double[1]; + private double[] co_midi_channel_pressure = new double[1]; + + protected SoftTuning tuning = new SoftTuning(); + protected int tuning_bank = 0; + protected int tuning_program = 0; + + protected SoftInstrument current_instrument = null; + protected ModelChannelMixer current_mixer = null; + private ModelDirector current_director = null;; + + // Controller Destination Settings + protected int cds_control_number = -1; + protected ModelConnectionBlock[] cds_control_connections = null; + protected ModelConnectionBlock[] cds_channelpressure_connections = null; + protected ModelConnectionBlock[] cds_polypressure_connections = null; + + protected boolean sustain = false; + protected boolean[][] keybasedcontroller_active = null; + protected double[][] keybasedcontroller_value = null; + + private class MidiControlObject implements SoftControl + { + double[] pitch = co_midi_pitch; + double[] channel_pressure = co_midi_channel_pressure; + double[] poly_pressure = new double[1]; + public double[] get(int instance, String name) { + if(name == null) return null; + if(name.equals("pitch")) return pitch; + if(name.equals("channel_pressure")) return channel_pressure; + if(name.equals("poly_pressure")) return poly_pressure; + return null; + } + }; + private SoftControl[] co_midi = new SoftControl[128]; + { + for (int i = 0; i < co_midi.length; i++) { + co_midi[i] = new MidiControlObject(); + } + } + private double[][] co_midi_cc_cc = new double[128][1]; + private SoftControl co_midi_cc = new SoftControl() + { + double[][] cc = co_midi_cc_cc; + public double[] get(int instance, String name) { + if(name == null) return null; + return cc[Integer.parseInt(name)]; + } + }; + + Mapco_midi_rpn_rpn_i = new HashMap(); + Mapco_midi_rpn_rpn = new HashMap(); + private SoftControl co_midi_rpn = new SoftControl() + { + Map rpn = co_midi_rpn_rpn; + public double[] get(int instance, String name) { + if(name == null) return null; + int iname = Integer.parseInt(name); + double[] v = rpn.get(iname); + if(v == null) + { + v = new double[1]; + rpn.put(iname, v); + } + return v; + } + }; + + + Mapco_midi_nrpn_nrpn_i = new HashMap(); + Mapco_midi_nrpn_nrpn = new HashMap(); + private SoftControl co_midi_nrpn = new SoftControl() + { + Map nrpn = co_midi_nrpn_nrpn; + public double[] get(int instance, String name) { + if(name == null) return null; + int iname = Integer.parseInt(name); + double[] v = nrpn.get(iname); + if(v == null) + { + v = new double[1]; + nrpn.put(iname, v); + } + return v; + } + }; + + public SoftChannel(SoftSynthesizer synth, int channel) { + this.channel = channel; + this.voices = synth.getVoices(); + this.synthesizer = synth; + this.mainmixer = synth.getMainMixer(); + control_mutex = synth.control_mutex; + resetAllControllers(true); + } + + private int findFreeVoice(int x) { + for (int i = x; i < voices.length; i++) + if (!voices[i].active) + return i; + + // No free voice was found, we must steal one + + int vmode = synthesizer.getVoiceAllocationMode(); + if(vmode == 1) + { + // DLS Static Voice Allocation + + // * priority ( 10, 1-9, 11-16) + // Search for channel to steal from + int steal_channel = channel; + for (int j = 0; j < voices.length; j++) { + if(voices[j].stealer_channel == null) + { + if(steal_channel == 9) + { + steal_channel = voices[j].channel; + } + else + { + if(voices[j].channel != 9) + { + if(voices[j].channel > steal_channel) steal_channel = voices[j].channel; + } + } + } + } + + int voiceNo = -1; + + SoftVoice v = null; + // Search for oldest voice in off state on steal_channel + for (int j = 0; j < voices.length; j++) { + if(voices[j].channel == steal_channel) + if(voices[j].stealer_channel == null && !voices[j].on) + { + if(v == null) + { + v = voices[j]; + voiceNo = j; + } + if(voices[j].voiceID < v.voiceID) + { + v = voices[j]; + voiceNo = j; + } + } + } + // Search for oldest voice in on state on steal_channel + if(voiceNo == -1) + { + for (int j = 0; j < voices.length; j++) { + if(voices[j].channel == steal_channel) + if(voices[j].stealer_channel == null) + { + if(v == null) + { + v = voices[j]; + voiceNo = j; + } + if(voices[j].voiceID < v.voiceID) + { + v = voices[j]; + voiceNo = j; + } + } + } + } + + return voiceNo; + + } + else + { + // Default Voice Allocation + // * Find voice that is on + // and Find voice which has lowest voiceID ( oldest voice) + // * Or find voice that is off + // and Find voice which has lowest voiceID ( oldest voice) + + int voiceNo = -1; + + SoftVoice v = null; + // Search for oldest voice in off state + for (int j = 0; j < voices.length; j++) { + if(voices[j].stealer_channel == null && !voices[j].on) + { + if(v == null) + { + v = voices[j]; + voiceNo = j; + } + if(voices[j].voiceID < v.voiceID) + { + v = voices[j]; + voiceNo = j; + } + } + } + // Search for oldest voice in on state + if(voiceNo == -1) + { + + for (int j = 0; j < voices.length; j++) { + if(voices[j].stealer_channel == null) + { + if(v == null) + { + v = voices[j]; + voiceNo = j; + } + if(voices[j].voiceID < v.voiceID) + { + v = voices[j]; + voiceNo = j; + } + } + } + } + + return voiceNo; + } + + } + + protected void initVoice(SoftVoice voice, SoftPerformer p, int voiceID, int noteNumber, int velocity, ModelConnectionBlock[] connectionBlocks, ModelChannelMixer channelmixer, boolean releaseTriggered) + { + if(voice.active) + { + // Voice is active , we must steal the voice + voice.stealer_channel = this; + voice.stealer_performer = p; + voice.stealer_voiceID = voiceID; + voice.stealer_noteNumber = noteNumber; + voice.stealer_velocity = velocity; + voice.stealer_extendedConnectionBlocks = connectionBlocks; + voice.stealer_channelmixer = channelmixer; + voice.stealer_releaseTriggered = releaseTriggered; + for (int i = 0; i < voices.length; i++) + if(voices[i].active && voices[i].voiceID == voice.voiceID) + voices[i].soundOff(); + return; + } + + voice.extendedConnectionBlocks = connectionBlocks; + voice.channelmixer = channelmixer; + voice.releaseTriggered = releaseTriggered; + voice.voiceID = voiceID; + voice.tuning = tuning; + voice.exclusiveClass = p.exclusiveClass; + voice.softchannel = this; + voice.channel = channel; + voice.bank = bank; + voice.program = program; + voice.instrument = current_instrument; + voice.performer = p; + voice.objects.clear(); + voice.objects.put("midi", co_midi[noteNumber]); + voice.objects.put("midi_cc", co_midi_cc); + voice.objects.put("midi_rpn", co_midi_rpn); + voice.objects.put("midi_nrpn", co_midi_nrpn); + voice.noteOn(noteNumber, velocity); + voice.setMute(mute); + voice.setSoloMute(solomute); + if(releaseTriggered) return; + if(portamento_control_note != -1) + { + voice.co_noteon_keynumber[0] = (tuning.getTuning(portamento_control_note) / 100.0) * (1f/128f); + voice.portamento = true; + portamento_control_note = -1; + } + else + if(portamento) + { + if(mono) + { + if(portamento_lastnote[0] != -1) + { + voice.co_noteon_keynumber[0] = (tuning.getTuning(portamento_lastnote[0]) / 100.0)*(1f/128f); + voice.portamento = true; + portamento_control_note = -1; + } + portamento_lastnote[0] = noteNumber; + } + else + { + if(portamento_lastnote_ix != 0) + { + portamento_lastnote_ix--; + voice.co_noteon_keynumber[0] = (tuning.getTuning(portamento_lastnote[portamento_lastnote_ix]) / 100.0)*(1f/128f); + voice.portamento = true; + } + } + } + } + + public void noteOn(int noteNumber, int velocity) { + + noteOn_internal(noteNumber, velocity); + if(current_mixer != null) current_mixer.noteOn(noteNumber, velocity); + } + + private void noteOn_internal(int noteNumber, int velocity) { + + if (velocity == 0) { + noteOff_internal(noteNumber, 64); + return; + } + + synchronized (control_mutex) { + + if(sustain) + { + sustain = false; + for (int i = 0; i < voices.length; i++) + if ((voices[i].sustain || voices[i].on) + && voices[i].channel == channel + && voices[i].active && voices[i].note == noteNumber ) { + + voices[i].sustain = false; + voices[i].on = true; + voices[i].noteOff(0); + } + sustain = true; + } + + mainmixer.msec_last_activity = mainmixer.msec_pos; + + if(mono) + { + if(portamento) + { + + boolean n_found = false; + for (int i = 0; i < voices.length; i++) + if (voices[i].on && voices[i].channel == channel + && voices[i].active + && voices[i].releaseTriggered == false ) { + voices[i].portamento = true; + voices[i].setNote(noteNumber); + n_found = true; + } + if(n_found) + { + portamento_lastnote[0] = noteNumber; + return; + } + } + + if(portamento_control_note != -1) + { + boolean n_found = false; + for (int i = 0; i < voices.length; i++) + if (voices[i].on && voices[i].channel == channel + && voices[i].active && voices[i].note == portamento_control_note + && voices[i].releaseTriggered == false ) { + voices[i].portamento = true; + voices[i].setNote(noteNumber); + n_found = true; + } + portamento_control_note = -1; + if(n_found) return; + } + } + + if(mono) allNotesOff(); + + if(current_instrument == null) + { + current_instrument = synthesizer.findInstrument(program, bank, channel); + if(current_instrument == null) return; + if(current_mixer != null) mainmixer.stopMixer(current_mixer); + current_mixer = current_instrument.getSourceInstrument().getChannelMixer(this, synthesizer.getFormat()); + if(current_mixer != null) mainmixer.registerMixer(current_mixer); + current_director = current_instrument.getDirector(this, this); + applyInstrumentCustomization(); + + } + prevVoiceID = synthesizer.voiceIDCounter++; + firstVoice = true; + voiceNo = 0; + + int tunedKey = (int)( Math.round(tuning.getTuning()[noteNumber] / 100.0)); + play_noteNumber = noteNumber; + play_velocity = velocity; + play_releasetriggered = false; + lastVelocity[noteNumber] = velocity; + current_director.noteOn(tunedKey, velocity); + + /* + SoftPerformer[] performers = current_instrument.getPerformers(); + for (int i = 0; i < performers.length; i++) { + SoftPerformer p = performers[i]; + if (p.keyFrom <= tunedKey && p.keyTo >= tunedKey) + if (p.velFrom <= velocity && p.velTo >= velocity) { + + if(firstVoice) + { + firstVoice = false; + if(p.exclusiveClass != 0) + { + int x = p.exclusiveClass; + for (int j = 0; j < voices.length; j++) + if (voices[j].active && voices[j].channel == channel + && voices[j].exclusiveClass == x) { + if(!(p.selfNonExclusive && voices[j].note == noteNumber)) + voices[j].shutdown(); + } + } + } + + voiceNo = findFreeVoice(voiceNo); + + if(voiceNo == -1) + return; + + initVoice(voices[voiceNo], p, prevVoiceID, noteNumber, velocity); + + + } + }*/ + } + } + + public void noteOff(int noteNumber, int velocity) { + + noteOff_internal(noteNumber, velocity); + + if(current_mixer != null) current_mixer.noteOff(noteNumber, velocity); + + } + + private void noteOff_internal(int noteNumber, int velocity) { + synchronized (control_mutex) { + + if(!mono) + if(portamento) + { + if(portamento_lastnote_ix != 127) + { + portamento_lastnote[portamento_lastnote_ix] = noteNumber; + portamento_lastnote_ix++; + } + } + + mainmixer.msec_last_activity = mainmixer.msec_pos; + for (int i = 0; i < voices.length; i++) + if (voices[i].on && voices[i].channel == channel + && voices[i].note == noteNumber && voices[i].releaseTriggered == false) { + voices[i].noteOff(velocity); + } + + // Try play back note-off triggered voices, + + if(current_instrument == null) + { + current_instrument = synthesizer.findInstrument(program, bank, channel); + if(current_instrument == null) return; + if(current_mixer != null) mainmixer.stopMixer(current_mixer); + current_mixer = current_instrument.getSourceInstrument().getChannelMixer(this, synthesizer.getFormat()); + if(current_mixer != null) mainmixer.registerMixer(current_mixer); + current_director = current_instrument.getDirector(this, this); + applyInstrumentCustomization(); + + } + prevVoiceID = synthesizer.voiceIDCounter++; + firstVoice = true; + voiceNo = 0; + + int tunedKey = (int)( Math.round(tuning.getTuning()[noteNumber] / 100.0)); + play_noteNumber = noteNumber; + play_velocity = lastVelocity[noteNumber]; + play_releasetriggered = true; + current_director.noteOff(tunedKey, velocity); + + } + } + + private int[] lastVelocity = new int[128]; + private int prevVoiceID; + private boolean firstVoice = true; + private int voiceNo = 0; + private int play_noteNumber = 0; + private int play_velocity = 0; + private boolean play_releasetriggered = false; + + public void play(int performerIndex, ModelConnectionBlock[] connectionBlocks) + { + + int noteNumber = play_noteNumber; + int velocity = play_velocity; + boolean releasetriggered = play_releasetriggered; + + SoftPerformer p = current_instrument.getPerformers()[performerIndex]; + + if(firstVoice) + { + firstVoice = false; + if(p.exclusiveClass != 0) + { + int x = p.exclusiveClass; + for (int j = 0; j < voices.length; j++) + if (voices[j].active && voices[j].channel == channel + && voices[j].exclusiveClass == x) { + if(!(p.selfNonExclusive && voices[j].note == noteNumber)) + voices[j].shutdown(); + } + } + } + + voiceNo = findFreeVoice(voiceNo); + + if(voiceNo == -1) + return; + + initVoice(voices[voiceNo], p, prevVoiceID, noteNumber, velocity, connectionBlocks, current_mixer, releasetriggered); + } + + public void noteOff(int noteNumber) { + noteOff_internal(noteNumber, 64); + } + + public void setPolyPressure(int noteNumber, int pressure) { + if(current_mixer != null) current_mixer.setPolyPressure(noteNumber, pressure); + + synchronized (control_mutex) { + mainmixer.msec_last_activity = mainmixer.msec_pos; + co_midi[noteNumber].get(0,"poly_pressure")[0] = pressure * (1.0/128.0); + polypressure[noteNumber] = pressure; + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].note == noteNumber) + voices[i].setPolyPressure(pressure); + } + } + + public int getPolyPressure(int noteNumber) { + synchronized (control_mutex) { + return polypressure[noteNumber]; + } + } + + public void setChannelPressure(int pressure) { + if(current_mixer != null) current_mixer.setChannelPressure(pressure); + synchronized (control_mutex) { + mainmixer.msec_last_activity = mainmixer.msec_pos; + co_midi_channel_pressure[0] = pressure * (1.0/128.0); + channelpressure = pressure; + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].setChannelPressure(pressure); + } + } + + public int getChannelPressure() { + synchronized (control_mutex) { + return channelpressure; + } + } + + protected void applyInstrumentCustomization() + { + if(cds_control_connections == null + && cds_channelpressure_connections == null + && cds_polypressure_connections == null) return; + + ModelInstrument src_instrument = current_instrument.getSourceInstrument(); + ModelPerformer[] performers = src_instrument.getPerformers(); + ModelPerformer[] new_performers = new ModelPerformer[performers.length]; + for (int i = 0; i < new_performers.length; i++) { + ModelPerformer performer = performers[i]; + ModelPerformer new_performer = new ModelPerformer(); + new_performer.setName(performer.getName()); + new_performer.setExclusiveClass(performer.getExclusiveClass()); + new_performer.setKeyFrom(performer.getKeyFrom()); + new_performer.setKeyTo(performer.getKeyTo()); + new_performer.setVelFrom(performer.getVelFrom()); + new_performer.setVelTo(performer.getVelTo()); + new_performer.getOscillators().addAll(performer.getOscillators()); + new_performer.getConnectionBlocks().addAll(performer.getConnectionBlocks()); + new_performers[i] = new_performer; + + List connblocks = new_performer.getConnectionBlocks(); + + if(cds_control_connections != null) + { + String cc = Integer.toString(cds_control_number); + Iterator iter = connblocks.iterator(); + while (iter.hasNext()) { + ModelConnectionBlock conn = iter.next(); + ModelSource[] sources = conn.getSources(); + boolean removeok = false; + if(sources != null) + for (int j = 0; j < sources.length; j++) { + ModelSource src = sources[j]; + if("midi_cc".equals(src.getIdentifier().getObject()) + && cc.equals(src.getIdentifier().getVariable())) + removeok = true; + } + if(removeok) iter.remove(); + } + for (int j = 0; j < cds_control_connections.length; j++) + connblocks.add(cds_control_connections[j]); + } + + if(cds_polypressure_connections != null) + { + Iterator iter = connblocks.iterator(); + while (iter.hasNext()) { + ModelConnectionBlock conn = iter.next(); + ModelSource[] sources = conn.getSources(); + boolean removeok = false; + if(sources != null) + for (int j = 0; j < sources.length; j++) { + ModelSource src = sources[j]; + if("midi".equals(src.getIdentifier().getObject()) + && "poly_pressure".equals(src.getIdentifier().getVariable())) + removeok = true; + } + if(removeok) iter.remove(); + } + for (int j = 0; j < cds_polypressure_connections.length; j++) + connblocks.add(cds_polypressure_connections[j]); + } + + + if(cds_channelpressure_connections != null) + { + Iterator iter = connblocks.iterator(); + while (iter.hasNext()) { + ModelConnectionBlock conn = iter.next(); + ModelSource[] sources = conn.getSources(); + boolean removeok = false; + if(sources != null) + for (int j = 0; j < sources.length; j++) { + ModelIdentifier srcid = sources[j].getIdentifier(); + if("midi".equals(srcid.getObject()) + && "channel_pressure".equals(srcid.getVariable())) + removeok = true; + } + if(removeok) iter.remove(); + } + for (int j = 0; j < cds_channelpressure_connections.length; j++) + connblocks.add(cds_channelpressure_connections[j]); + } + + } + + current_instrument = new SoftInstrument(src_instrument, new_performers); + + } + + private ModelConnectionBlock[] createModelConnections(ModelIdentifier sid, int[] destination, int[] range) { + + // controlled parameter (pp) range (rr) Description Default + // ------------------------------------------------------------------------------ + // 00 Pitch Control 28H - 58H -24 - +24 semitones 40H + // 01 Filter Cutoff Control 00H - 7FH -9600 - +9450 cents 40H + // 02 Amplitude Control 00H - 7FH 0 - (127/64) * 100 percent 40H + // 03 LFO Pitch Depth 00H - 7FH 0 - 600 cents 0 + // 04 LFO Filter Depth 00H - 7FH 0 - 2400 cents 0 + // 05 LFO Amplitude Depth 00H - 7FH 0 - 100 percent 0 + + List conns = new ArrayList(); + + for (int i = 0; i < destination.length; i++) { + int d = destination[i]; + int r = range[i]; + if(d == 0) + { + double scale = (r - 64)*100; + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR) + ,scale,new ModelDestination(new ModelIdentifier("osc", "pitch"))); + conns.add(conn); + + } + if(d == 1) + { + double scale = (r / 64.0 - 1.0) * 9600.0; + ModelConnectionBlock conn; + if(scale > 0) + conn = new ModelConnectionBlock( + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MAX2MIN,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR) + ,-scale,new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ)); + else + conn = new ModelConnectionBlock( + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR) + ,scale,new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ)); + conns.add(conn); + } + if(d == 2) + { + final double scale = (r / 64.0); + + ModelTransform mt = new ModelTransform() + { + double s = scale; + public double transform(double value) { + if(s < 1) value = s + (value*(1.0-s)); + else + if(s > 1) value = 1 + (value*(s - 1.0)); + else + return 0; + return -((5.0/12.0)/Math.log(10))*Math.log(value); + } + }; + + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(sid,mt),-960,new ModelDestination(ModelDestination.DESTINATION_GAIN)); + conns.add(conn); + + } + if(d == 3) + { + double scale = (r / 64.0 - 1.0) * 9600.0; + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR), + scale,new ModelDestination(ModelDestination.DESTINATION_PITCH)); + conns.add(conn); + } + if(d == 4) + { + double scale = (r / 128.0) * 2400.0; + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR), + scale,new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ)); + conns.add(conn); + } + if(d == 5) + { + final double scale = (r / 127.0); + + ModelTransform mt = new ModelTransform() + { + double s = scale; + public double transform(double value) { + return -((5.0/12.0)/Math.log(10))*Math.log(1 - value*s); + } + }; + + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(sid, + mt), + -960,new ModelDestination(ModelDestination.DESTINATION_GAIN)); + conns.add(conn); + } + } + + return (ModelConnectionBlock[])conns.toArray(new ModelConnectionBlock[conns.size()]); + } + + public void mapPolyPressureToDestination(int[] destination, int[] range) { + current_instrument = null; + if(destination.length == 0) + { + cds_polypressure_connections = null; + return; + } + cds_polypressure_connections = createModelConnections(new ModelIdentifier("midi","poly_pressure"), destination, range); + } + + public void mapChannelPressureToDestination(int[] destination, int[] range) { + current_instrument = null; + if(destination.length == 0) + { + cds_channelpressure_connections = null; + return; + } + cds_channelpressure_connections = createModelConnections(new ModelIdentifier("midi","channel_pressure"), destination, range); + } + + public void mapControlToDestination(int control, int[] destination, int[] range) { + + if(!( (control >= 0x01 && control <= 0x1F) || (control >= 0x40 && control <= 0x5F) ) ) + { + cds_control_connections = null; + return; + } + + current_instrument = null; + cds_control_number = control; + if(destination.length == 0) + { + cds_control_connections = null; + return; + } + cds_control_connections = createModelConnections(new ModelIdentifier("midi_cc",Integer.toString(control)), destination, range); + } + + + public void controlChangePerNote(int noteNumber, int controller, int value) { + + /* + + CC# nn Name vv default description + -------------------------------------------------------------------------------------------------------------------- + 7 07H Note Volume 00H-40H-7FH 40H 0-100-(127/64)*100 (%) (Relative) + 10 0AH *Pan 00H-7FH absolute (Preset Value) Left-Center-Right (absolute) + 33-63 21-3FH LSB for 01H-1FH + 71 47H Timbre/Harmonic Intensity 00H-40H-7FH 40H (???) + 72 48H Release Time 00H-40H-7FH 40H (???) + 73 49H Attack Time 00H-40H-7FH 40H (???) + 74 4AH Brightness 00H-40H-7FH 40H (???) + 75 4BH Decay Time 00H-40H-7FH 40H (???) + 76 4CH Vibrato Rate 00H-40H-7FH 40H (???) + 77 4DH Vibrato Depth 00H-40H-7FH 40H (???) + 78 4EH Vibrato Delay 00H-40H-7FH 40H (???) + 91 5BH *Reverb Send 00H-7FH absolute (Preset Value) Left-Center-RIght (absolute) + 93 5DH *Chorus Send 00H-7FH absolute (Preset Value) Left-Center-RIght (absolute) + 120 78H **Fine Tuning 00H-40H-7FH 40H (???) + 121 79H **Coarse Tuning 00H-40H-7FH 40H (???) + + */ + + if(keybasedcontroller_active == null) + { + keybasedcontroller_active = new boolean[128][]; + keybasedcontroller_value = new double[128][]; + } + if(keybasedcontroller_active[noteNumber] == null) + { + keybasedcontroller_active[noteNumber] = new boolean[128]; + Arrays.fill(keybasedcontroller_active[noteNumber], false); + keybasedcontroller_value[noteNumber] = new double[128]; + Arrays.fill(keybasedcontroller_value[noteNumber], 0); + } + + if(value == -1) + { + keybasedcontroller_active[noteNumber][controller] = false; + } + else + { + keybasedcontroller_active[noteNumber][controller] = true; + keybasedcontroller_value[noteNumber][controller] = value/128.0; + } + + if(controller < 120) + { + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].controlChange(controller,-1); + } + else if(controller == 120) + { + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].rpnChange(1,-1); + } + else if(controller == 121) + { + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].rpnChange(2,-1); + } + + + } + public int getControlPerNote(int noteNumber, int controller) { + if(keybasedcontroller_active == null) return -1; + if(keybasedcontroller_active[noteNumber] == null) return -1; + if(!keybasedcontroller_active[noteNumber][controller]) return -1; + return (int)(keybasedcontroller_value[noteNumber][controller]*128); + } + + public void controlChange(int controller, int value) { + { + if(current_mixer != null) current_mixer.controlChange(controller, value); + + synchronized (control_mutex) { + + switch (controller) { + + /* + Mapco_midi_rpn_rpn_i = new HashMap(); + Mapco_midi_rpn_rpn = new HashMap(); + Mapco_midi_nrpn_nrpn_i = new HashMap(); + Mapco_midi_nrpn_nrpn = new HashMap(); + */ + + case 5: + // This produce asin-like curve + // as described in General Midi Level 2 Specification, page 6 + double x = -Math.asin((value / 128.0)*2-1)/Math.PI + 0.5; + x = Math.pow(100000.0, x)/100.0; // x is now cent/msec + // Convert x from cent/msec to key/controlbuffertime + x = x / 100.0; // x is now keys/msec + x = x * 1000.0; // x is now keys/sec + x = x / synthesizer.getControlRate() ; // x is now keys/controlbuffertime + portamento_time = x; + break; + case 6: + case 38: + case 96: + case 97: + int val = 0; + if(nrpn_control != RPN_NULL_VALUE) + { + int[] val_i = co_midi_nrpn_nrpn_i.get(nrpn_control); + if(val_i != null) val = val_i[0]; + } + if(rpn_control != RPN_NULL_VALUE) + { + int[] val_i = co_midi_rpn_rpn_i.get(rpn_control); + if(val_i != null) val = val_i[0]; + } + + if(controller == 6) + val = (val & 127) + (value << 7); + else if(controller == 38) + val = (val & (127 << 7)) + value; + else if(controller == 96 || controller == 97) + { + int step = 1; + if(rpn_control == 2 || rpn_control == 3 || rpn_control == 4) + step = 128; + if(controller == 96) + val += step; + if(controller == 97) + val -= step; + } + + if(nrpn_control != RPN_NULL_VALUE) + nrpnChange(nrpn_control, val); + if(rpn_control != RPN_NULL_VALUE) + rpnChange(rpn_control, val); + + break; + case 64: // Hold1 (Damper) (cc#64) + boolean on = value >= 64; + if(sustain != on) + { + sustain = on; + if(!on) + { + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].sustain && voices[i].channel == channel) + { + voices[i].sustain = false; + if(!voices[i].on) + { + voices[i].on = true; + voices[i].noteOff(0); + } + } + } + else + { + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].channel == channel) + { + voices[i].redamp(); + } + } + } + break; + case 65: + //allNotesOff(); + portamento = value >= 64; + portamento_lastnote[0] = -1; + /* + for (int i = 0; i < portamento_lastnote.length; i++) { + portamento_lastnote[i] = -1; + }*/ + portamento_lastnote_ix = 0; + break; + case 66: // Sostenuto (cc#66) + on = value >= 64; + if(on) + { + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].on && voices[i].channel == channel) + voices[i].sostenuto = true; + } + if(!on) + { + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].sostenuto && voices[i].channel == channel) + { + voices[i].sostenuto = false; + if(!voices[i].on) + { + voices[i].on = true; + voices[i].noteOff(0); + } + } + } + break; + case 84: + portamento_control_note = value; + break; + case 98: + nrpn_control = (nrpn_control & (127 << 7)) + value; + rpn_control = RPN_NULL_VALUE; + break; + case 99: + nrpn_control = (nrpn_control & 127) + (value << 7); + rpn_control = RPN_NULL_VALUE; + break; + case 100: + rpn_control = (rpn_control & (127 << 7)) + value; + nrpn_control = RPN_NULL_VALUE; + break; + case 101: + rpn_control = (rpn_control & 127) + (value << 7); + nrpn_control = RPN_NULL_VALUE; + break; + case 120: allSoundOff(); break; + case 121: resetAllControllers(value == 127); break; + case 122: localControl(value >= 64); break; + case 123: allNotesOff(); break; + case 124: setOmni(false); break; + case 125: setOmni(true); break; + case 126: if(value == 1) setMono(true); break; + case 127: setMono(false); break; + + default: + break; + } + + + co_midi_cc_cc[controller][0] = value * (1.0/128.0); + + + if (controller == 0x00) { + bank = (bank & 127) + (value << 7); + return; + } + + if (controller == 0x20) { + bank = (bank & (127 << 7)) + value; + return; + } + + this.controller[controller] = value; + + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].controlChange(controller, value); + + } + } + } + + public int getController(int controller) { + synchronized (control_mutex) { + return this.controller[controller]; + } + } + + public void tuningChange(int program) + { + tuningChange(0, program); + } + + public void tuningChange(int bank, int program) + { + synchronized (control_mutex) { + tuning = synthesizer.getTuning(new Patch(bank , program)); + } + } + + public void programChange(int program) { + programChange(bank, program); + } + + public void programChange(int bank, int program) { + synchronized (control_mutex) { + mainmixer.msec_last_activity = mainmixer.msec_pos; + this.bank = bank; + this.program = program; + current_instrument = null; + } + } + + public int getProgram() { + synchronized (control_mutex) { + return program; + } + } + + public void setPitchBend(int bend) { + if(current_mixer != null) current_mixer.setPitchBend(bend); + synchronized (control_mutex) { + mainmixer.msec_last_activity = mainmixer.msec_pos; + co_midi_pitch[0] = bend * (1.0/16384.0); + pitchbend = bend; + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].setPitchBend(bend); + } + } + + public int getPitchBend() { + synchronized (control_mutex) { + return pitchbend; + } + } + + public void nrpnChange(int controller, int value) { + + /* + System.out.println("(" + channel + ").nrpnChange(" + + Integer.toHexString(controller >> 7) + " " + Integer.toHexString(controller & 127) + + ", " + Integer.toHexString(value >> 7) + " " + Integer.toHexString(value & 127) + ")"); + */ + + if(synthesizer.getGeneralMidiMode() == 0) + { + if(controller == (0x01<<7) + (0x08) ) controlChange(76, value >> 7); // Vibrato Rate + if(controller == (0x01<<7) + (0x09) ) controlChange(77, value >> 7); // Vibrato Depth + if(controller == (0x01<<7) + (0x0A) ) controlChange(78, value >> 7); // Vibrato Delay + if(controller == (0x01<<7) + (0x20) ) controlChange(74, value >> 7); // Brightness + if(controller == (0x01<<7) + (0x21) ) controlChange(71, value >> 7); // Filter Resonance + if(controller == (0x01<<7) + (0x63) ) controlChange(73, value >> 7); // Attack Time + if(controller == (0x01<<7) + (0x64) ) controlChange(75, value >> 7); // Decay Time + if(controller == (0x01<<7) + (0x66) ) controlChange(72, value >> 7); // Release Time + + + if(controller>>7 == 0x18) controlChangePerNote(controller % 128, 120, value >> 7); // Pitch coarse + if(controller>>7 == 0x1A) controlChangePerNote(controller % 128, 7, value >> 7); // Volume + if(controller>>7 == 0x1C) controlChangePerNote(controller % 128, 10, value >> 7); // Panpot + if(controller>>7 == 0x1D) controlChangePerNote(controller % 128, 91, value >> 7); // Reverb + if(controller>>7 == 0x1E) controlChangePerNote(controller % 128, 93, value >> 7); // Chorus + } + + int[] val_i = co_midi_nrpn_nrpn_i.get(controller); + double[] val_d = co_midi_nrpn_nrpn.get(controller); + if(val_i == null) + { + val_i = new int[1]; + co_midi_nrpn_nrpn_i.put(controller, val_i); + } + if(val_d == null) + { + val_d = new double[1]; + co_midi_nrpn_nrpn.put(controller, val_d); + } + val_i[0] = value; + val_d[0] = val_i[0] * (1.0/16384.0); + + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].nrpnChange(controller, val_i[0]); + + } + + public void rpnChange(int controller, int value) { + + /* + System.out.println("(" + channel + ").rpnChange(" + + Integer.toHexString(controller >> 7) + " " + Integer.toHexString(controller & 127) + + ", " + Integer.toHexString(value >> 7) + " " + Integer.toHexString(value & 127) + ")"); + */ + + if(controller == 3) + { + tuning_program = (value >> 7) & 127; + tuningChange(tuning_bank, tuning_program); + } + if(controller == 4) + { + tuning_bank = (value >> 7) & 127; + } + + int[] val_i = co_midi_rpn_rpn_i.get(controller); + double[] val_d = co_midi_rpn_rpn.get(controller); + if(val_i == null) + { + val_i = new int[1]; + co_midi_rpn_rpn_i.put(controller, val_i); + } + if(val_d == null) + { + val_d = new double[1]; + co_midi_rpn_rpn.put(controller, val_d); + } + val_i[0] = value; + val_d[0] = val_i[0] * (1.0/16384.0); + + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].rpnChange(controller, val_i[0]); + } + + public void resetAllControllers() { + resetAllControllers(false); + } + + public void resetAllControllers(boolean allControls) { + synchronized (control_mutex) { + mainmixer.msec_last_activity = mainmixer.msec_pos; + + + for (int i = 0; i < 128; i++) { + setPolyPressure(i, 0); + } + setChannelPressure(0); + setPitchBend(8192); + for (int i = 0; i < 128; i++) { + if(!dontResetControls[i]) + controlChange(i, 0); + } + + controlChange(71, 64); // Filter Resonance + controlChange(72, 64); // Release Time + controlChange(73, 64); // Attack Time + controlChange(74, 64); // Brightness + controlChange(75, 64); // Decay Time + controlChange(76, 64); // Vibrato Rate + controlChange(77, 64); // Vibrato Depth + controlChange(78, 64); // Vibrato Delay + + controlChange(8, 64); // Balance + controlChange(11, 127); // Expression + controlChange(98, 127); // NRPN Null + controlChange(99, 127); // NRPN Null + controlChange(100, 127); // RPN = Null + controlChange(101, 127); // RPN = Null + + // see DLS 2.1 (Power-on Default Values) + if(allControls) + { + + keybasedcontroller_active = null; + keybasedcontroller_value = null; + + controlChange(7, 100); // Volume + controlChange(10, 64); // Pan + controlChange(91, 40); // Reverb + + for(int controller : co_midi_rpn_rpn.keySet()) + { + // don't reset tuning settings + if(controller != 3 && controller != 4) + rpnChange(controller, 0); + } + for(int controller : co_midi_nrpn_nrpn.keySet()) + nrpnChange(controller, 0); + rpnChange(0, 2 << 7); // Bitch Bend sensitivity + rpnChange(1, 64 << 7); // Channel fine tunning + rpnChange(2, 64 << 7); // Channel Coarse Tuning + rpnChange(5, 64); // Modulation Depth, +/- 50 cent + + tuning_bank = 0; + tuning_program = 0; + tuning = new SoftTuning(); + + } + + } + } + + public void allNotesOff() { + if(current_mixer != null) current_mixer.allNotesOff(); + synchronized (control_mutex) { + for (int i = 0; i < voices.length; i++) + if (voices[i].on && voices[i].channel == channel && voices[i].releaseTriggered == false) + voices[i].noteOff(0); + } + } + + public void allSoundOff() { + if(current_mixer != null) current_mixer.allSoundOff(); + synchronized (control_mutex) { + for (int i = 0; i < voices.length; i++) + if (voices[i].on && voices[i].channel == channel) + voices[i].soundOff(); + } + } + + public boolean localControl(boolean on) { + return false; + } + + public void setMono(boolean on) { + if(current_mixer != null) current_mixer.setMono(on); + synchronized (control_mutex) { + allNotesOff(); + mono = on; + } + } + + public boolean getMono() { + synchronized (control_mutex) { + return mono; + } + } + + public void setOmni(boolean on) { + if(current_mixer != null) current_mixer.setOmni(on); + allNotesOff(); + // Omni is not supported by GM2 + } + + public boolean getOmni() { + return false; + } + + public void setMute(boolean mute) { + if(current_mixer != null) current_mixer.setMute(mute); + synchronized (control_mutex) { + this.mute = mute; + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].channel == channel) + voices[i].setMute(mute); + + } + } + + public boolean getMute() { + synchronized (control_mutex) { + return mute; + } + } + + + public void setSolo(boolean soloState) { + if(current_mixer != null) current_mixer.setSolo(soloState); + + synchronized (control_mutex) { + + this.solo = soloState; + + boolean soloinuse = false; + for(SoftChannel c : synthesizer.channels) + if(c.solo) + { + soloinuse = true; + break; + } + + if(!soloinuse) + { + for(SoftChannel c : synthesizer.channels) + c.setSoloMute(false); + return; + } + + for(SoftChannel c : synthesizer.channels) + c.setSoloMute(!c.solo); + + } + + } + + private void setSoloMute(boolean mute) { + synchronized (control_mutex) { + if(solomute == mute) return; + this.solomute = mute; + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].channel == channel) + voices[i].setSoloMute(solomute); + + } + } + + public boolean getSolo() { + synchronized (control_mutex) { + return solo; + } + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannelProxy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannelProxy.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,206 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import javax.sound.midi.MidiChannel; + +/** + * + * A MidiChannel proxy object used for external access to synthesizer internal + * channel objects. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftChannelProxy implements MidiChannel { + + private MidiChannel channel = null; + + public MidiChannel getChannel() { + return channel; + } + + public void setChannel(MidiChannel channel) { + this.channel = channel; + } + + public void allNotesOff() { + if (channel == null) + return; + channel.allNotesOff(); + } + + public void allSoundOff() { + if (channel == null) + return; + channel.allSoundOff(); + } + + public void controlChange(int controller, int value) { + if (channel == null) + return; + channel.controlChange(controller, value); + } + + public int getChannelPressure() { + if (channel == null) + return 0; + return channel.getChannelPressure(); + } + + public int getController(int controller) { + if (channel == null) + return 0; + return channel.getController(controller); + } + + public boolean getMono() { + if (channel == null) + return false; + return channel.getMono(); + } + + public boolean getMute() { + if (channel == null) + return false; + return channel.getMute(); + } + + public boolean getOmni() { + if (channel == null) + return false; + return channel.getOmni(); + } + + public int getPitchBend() { + if (channel == null) + return 8192; + return channel.getPitchBend(); + } + + public int getPolyPressure(int noteNumber) { + if (channel == null) + return 0; + return channel.getPolyPressure(noteNumber); + } + + public int getProgram() { + if (channel == null) + return 0; + return channel.getProgram(); + } + + public boolean getSolo() { + if (channel == null) + return false; + return channel.getSolo(); + } + + public boolean localControl(boolean on) { + if (channel == null) + return false; + return channel.localControl(on); + } + + public void noteOff(int noteNumber) { + if (channel == null) + return; + channel.noteOff(noteNumber); + } + + public void noteOff(int noteNumber, int velocity) { + if (channel == null) + return; + channel.noteOff(noteNumber, velocity); + } + + public void noteOn(int noteNumber, int velocity) { + if (channel == null) + return; + channel.noteOn(noteNumber, velocity); + } + + public void programChange(int program) { + if (channel == null) + return; + channel.programChange(program); + } + + public void programChange(int bank, int program) { + if (channel == null) + return; + channel.programChange(bank, program); + } + + public void resetAllControllers() { + if (channel == null) + return; + channel.resetAllControllers(); + } + + public void setChannelPressure(int pressure) { + if (channel == null) + return; + channel.setChannelPressure(pressure); + } + + public void setMono(boolean on) { + if (channel == null) + return; + channel.setMono(on); + } + + public void setMute(boolean mute) { + if (channel == null) + return; + channel.setMute(mute); + } + + public void setOmni(boolean on) { + if (channel == null) + return; + channel.setOmni(on); + } + + public void setPitchBend(int bend) { + if (channel == null) + return; + channel.setPitchBend(bend); + } + + public void setPolyPressure(int noteNumber, int pressure) { + if (channel == null) + return; + channel.setPolyPressure(noteNumber, pressure); + } + + public void setSolo(boolean soloState) { + if (channel == null) + return; + channel.setSolo(soloState); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChorus.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChorus.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,383 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.Arrays; + +/** + * A chorus effect made using LFO and variable delay. One for each channel + * (left,right), with different starting phase for stereo effect. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftChorus implements SoftAudioProcessor { + + private class VariableDelay { + private float[] delaybuffer; + + private int rovepos = 0; + + private volatile float gain = 1; + + private volatile float rgain = 0; + + private volatile float delay = 0; + + private float lastdelay = 0; + + private volatile float feedback = 0; + + public VariableDelay(int maxbuffersize) { + delaybuffer = new float[maxbuffersize]; + } + + public void setDelay(float delay) { + this.delay = delay; + } + + public void setFeedBack(float feedback) { + this.feedback = feedback; + } + + public void setGain(float gain) { + this.gain = gain; + } + + public void setReverbSendGain(float rgain) { + this.rgain = rgain; + } + + public void processMix(float[] in, float[] out, float[] rout) { + float gain = this.gain; + float delay = this.delay; + float feedback = this.feedback; + + float[] delaybuffer = this.delaybuffer; + int len = in.length; + float delaydelta = (delay - lastdelay) / len; + int rnlen = delaybuffer.length; + int rovepos = this.rovepos; + + if (rout == null) + for (int i = 0; i < len; i++) { + float r = rovepos - (lastdelay + 2) + rnlen; + int ri = (int) r; + float s = r - ri; + float a = delaybuffer[ri % rnlen]; + float b = delaybuffer[(ri + 1) % rnlen]; + float o = a * (1 - s) + b * (s); + out[i] += o * gain; + delaybuffer[rovepos] = in[i] + o * feedback; + rovepos = (rovepos + 1) % rnlen; + lastdelay += delaydelta; + } + else + for (int i = 0; i < len; i++) { + float r = rovepos - (lastdelay + 2) + rnlen; + int ri = (int) r; + float s = r - ri; + float a = delaybuffer[ri % rnlen]; + float b = delaybuffer[(ri + 1) % rnlen]; + float o = a * (1 - s) + b * (s); + out[i] += o * gain; + rout[i] += o * rgain; + delaybuffer[rovepos] = in[i] + o * feedback; + rovepos = (rovepos + 1) % rnlen; + lastdelay += delaydelta; + } + this.rovepos = rovepos; + lastdelay = delay; + } + + public void processReplace(float[] in, float[] out, float[] rout) { + Arrays.fill(out, 0); + Arrays.fill(rout, 0); + processMix(in, out, rout); + } + + } + + private class LFODelay { + + private volatile double c_cos_delta; + + private volatile double c_sin_delta; + + private double c_cos = 1; + + private double c_sin = 0; + + private double depth = 0; + + private VariableDelay vdelay; + + private double samplerate; + + private double controlrate; + + public LFODelay(double samplerate, double controlrate) { + this.samplerate = samplerate; + this.controlrate = controlrate; + // vdelay = new VariableDelay((int)(samplerate*4)); + vdelay = new VariableDelay((int) ((this.depth + 10) * 2)); + + } + + public void setDepth(double depth) { + this.depth = depth * samplerate; + vdelay = new VariableDelay((int) ((this.depth + 10) * 2)); + } + + public void setRate(double rate) { + double g = (Math.PI * 2) * (rate / controlrate); + c_cos_delta = Math.cos(g); + c_sin_delta = Math.sin(g); + } + + public void setPhase(double phase) { + c_cos = Math.cos(phase); + c_sin = Math.sin(phase); + } + + public void setFeedBack(float feedback) { + vdelay.setFeedBack(feedback); + } + + public void setGain(float gain) { + vdelay.setGain(gain); + } + + public void setReverbSendGain(float rgain) { + vdelay.setReverbSendGain(rgain); + } + + public void processMix(float[] in, float[] out, float[] rout) { + c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta; + c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta; + vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2))); + vdelay.processMix(in, out, rout); + } + + public void processReplace(float[] in, float[] out, float[] rout) { + c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta; + c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta; + vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2))); + vdelay.processReplace(in, out, rout); + + } + } + + private boolean mix = true; + + private SoftAudioBuffer inputA; + + private SoftAudioBuffer left; + + private SoftAudioBuffer right; + + private SoftAudioBuffer reverb; + + private LFODelay vdelay1L; + + private LFODelay vdelay1R; + + private float rgain = 0; + + private SoftSynthesizer synth; + + private boolean dirty = true; + + private double dirty_vdelay1L_rate; + + private double dirty_vdelay1R_rate; + + private double dirty_vdelay1L_depth; + + private double dirty_vdelay1R_depth; + + private float dirty_vdelay1L_feedback; + + private float dirty_vdelay1R_feedback; + + private float dirty_vdelay1L_reverbsendgain; + + private float dirty_vdelay1R_reverbsendgain; + + public void init(SoftSynthesizer synth) { + this.synth = synth; + double samplerate = synth.getFormat().getSampleRate(); + double controlrate = synth.getControlRate(); + vdelay1L = new LFODelay(samplerate, controlrate); + vdelay1R = new LFODelay(samplerate, controlrate); + vdelay1L.setGain(1.0f); // % + vdelay1R.setGain(1.0f); // % + vdelay1L.setPhase(0.5 * Math.PI); + vdelay1R.setPhase(0); + + globalParameterControlChange(new int[] { 0x01 * 128 + 0x02 }, 0, 2); + } + + public void globalParameterControlChange(int[] slothpath, long param, + long value) { + if (slothpath.length == 1) + if (slothpath[0] == 0x01 * 128 + 0x02) { + + if (param == 0) // Chorus Type + { + switch ((int) value) { + case 0: // Chorus 1 0 (0%) 3 (0.4Hz) 5 (1.9ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 0); + globalParameterControlChange(slothpath, 1, 3); + globalParameterControlChange(slothpath, 2, 5); + globalParameterControlChange(slothpath, 4, 0); + break; + case 1: // Chorus 2 5 (4%) 9 (1.1Hz) 19 (6.3ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 5); + globalParameterControlChange(slothpath, 1, 9); + globalParameterControlChange(slothpath, 2, 19); + globalParameterControlChange(slothpath, 4, 0); + break; + case 2: // Chorus 3 8 (6%) 3 (0.4Hz) 19 (6.3ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 8); + globalParameterControlChange(slothpath, 1, 3); + globalParameterControlChange(slothpath, 2, 19); + globalParameterControlChange(slothpath, 4, 0); + break; + case 3: // Chorus 4 16 (12%) 9 (1.1Hz) 16 (5.3ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 16); + globalParameterControlChange(slothpath, 1, 9); + globalParameterControlChange(slothpath, 2, 16); + globalParameterControlChange(slothpath, 4, 0); + break; + case 4: // FB Chorus 64 (49%) 2 (0.2Hz) 24 (7.8ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 64); + globalParameterControlChange(slothpath, 1, 2); + globalParameterControlChange(slothpath, 2, 24); + globalParameterControlChange(slothpath, 4, 0); + break; + case 5: // Flanger 112 (86%) 1 (0.1Hz) 5 (1.9ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 112); + globalParameterControlChange(slothpath, 1, 1); + globalParameterControlChange(slothpath, 2, 5); + globalParameterControlChange(slothpath, 4, 0); + break; + default: + break; + } + } else if (param == 1) // Mod Rate + { + dirty_vdelay1L_rate = (value * 0.122); + dirty_vdelay1R_rate = (value * 0.122); + dirty = true; + } else if (param == 2) // Mod Depth + { + dirty_vdelay1L_depth = ((value + 1) / 3200.0); + dirty_vdelay1R_depth = ((value + 1) / 3200.0); + dirty = true; + } else if (param == 3) // Feedback + { + dirty_vdelay1L_feedback = (value * 0.00763f); + dirty_vdelay1R_feedback = (value * 0.00763f); + dirty = true; + } + if (param == 4) // Send to Reverb + { + rgain = value * 0.00787f; + dirty_vdelay1L_reverbsendgain = (value * 0.00787f); + dirty_vdelay1R_reverbsendgain = (value * 0.00787f); + dirty = true; + } + + } + } + + public void processControlLogic() { + if (dirty) { + dirty = false; + vdelay1L.setRate(dirty_vdelay1L_rate); + vdelay1R.setRate(dirty_vdelay1R_rate); + vdelay1L.setDepth(dirty_vdelay1L_depth); + vdelay1R.setDepth(dirty_vdelay1R_depth); + vdelay1L.setFeedBack(dirty_vdelay1L_feedback); + vdelay1R.setFeedBack(dirty_vdelay1R_feedback); + vdelay1L.setReverbSendGain(dirty_vdelay1L_reverbsendgain); + vdelay1R.setReverbSendGain(dirty_vdelay1R_reverbsendgain); + } + } + + double silentcounter = 1000; + + public void processAudio() { + + if (inputA.isSilent()) { + silentcounter += 1 / synth.getControlRate(); + + if (silentcounter > 1) { + if (!mix) { + left.clear(); + right.clear(); + } + return; + } + } else + silentcounter = 0; + + float[] inputA = this.inputA.array(); + float[] left = this.left.array(); + float[] right = this.right == null ? null : this.right.array(); + float[] reverb = rgain != 0 ? this.reverb.array() : null; + + if (mix) { + vdelay1L.processMix(inputA, left, reverb); + if (right != null) + vdelay1R.processMix(inputA, right, reverb); + } else { + vdelay1L.processReplace(inputA, left, reverb); + if (right != null) + vdelay1R.processReplace(inputA, right, reverb); + } + } + + public void setInput(int pin, SoftAudioBuffer input) { + if (pin == 0) + inputA = input; + } + + public void setMixMode(boolean mix) { + this.mix = mix; + } + + public void setOutput(int pin, SoftAudioBuffer output) { + if (pin == 0) + left = output; + if (pin == 1) + right = output; + if (pin == 2) + reverb = output; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftControl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftControl.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * SoftControl are the basic controls + * used for control-rate processing. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface SoftControl { + + public double[] get(int instance, String name); + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * A resampler that uses third-order (cubic) interpolation. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftCubicResampler extends SoftAbstractResampler { + + public int getPadding() { + return 3; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0) { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float fix = ix - iix; + float y0 = in[iix - 1]; + float y1 = in[iix]; + float y2 = in[iix + 1]; + float y3 = in[iix + 2]; + float a0 = y3 - y2 + y1 - y0; + float a1 = y0 - y1 - a0; + float a2 = y2 - y0; + float a3 = y1; + //float fix2 = fix * fix; + //out[ox++] = (a0 * fix + a1) * fix2 + (a2 * fix + a3); + out[ox++] = ((a0 * fix + a1) * fix + a2) * fix + a3; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float fix = ix - iix; + float y0 = in[iix - 1]; + float y1 = in[iix]; + float y2 = in[iix + 1]; + float y3 = in[iix + 2]; + float a0 = y3 - y2 + y1 - y0; + float a1 = y0 - y1 - a0; + float a2 = y2 - y0; + float a3 = y1; + //float fix2 = fix * fix; + //out[ox++] = (a0 * fix + a1) * fix2 + (a2 * fix + a3); + out[ox++] = ((a0 * fix + a1) * fix + a2) * fix + a3; + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,338 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * AHDSR control signal envelope generator. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftEnvelopeGenerator implements SoftProcess { + + public final static int EG_OFF = 0; + + public final static int EG_DELAY = 1; + + public final static int EG_ATTACK = 2; + + public final static int EG_HOLD = 3; + + public final static int EG_DECAY = 4; + + public final static int EG_SUSTAIN = 5; + + public final static int EG_RELEASE = 6; + + public final static int EG_SHUTDOWN = 7; + + public final static int EG_END = 8; + + int max_count = 10; + + int used_count = 0; + + private int[] stage = new int[max_count]; + + private int[] stage_ix = new int[max_count]; + + private double[] stage_v = new double[max_count]; + + private int[] stage_count = new int[max_count]; + + private double[][] on = new double[max_count][1]; + + private double[][] active = new double[max_count][1]; + + private double[][] out = new double[max_count][1]; + + private double[][] delay = new double[max_count][1]; + + private double[][] attack = new double[max_count][1]; + + private double[][] hold = new double[max_count][1]; + + private double[][] decay = new double[max_count][1]; + + private double[][] sustain = new double[max_count][1]; + + private double[][] release = new double[max_count][1]; + + private double[][] shutdown = new double[max_count][1]; + + private double[][] release2 = new double[max_count][1]; + + private double[][] attack2 = new double[max_count][1]; + + private double[][] decay2 = new double[max_count][1]; + + private double control_time = 0; + + public void reset() { + for (int i = 0; i < used_count; i++) { + stage[i] = 0; + on[i][0] = 0; + out[i][0] = 0; + delay[i][0] = 0; + attack[i][0] = 0; + hold[i][0] = 0; + decay[i][0] = 0; + sustain[i][0] = 0; + release[i][0] = 0; + shutdown[i][0] = 0; + attack2[i][0] = 0; + decay2[i][0] = 0; + release2[i][0] = 0; + + } + used_count = 0; + } + + public void init(SoftSynthesizer synth) { + control_time = 1.0 / synth.getControlRate(); + processControlLogic(); + } + + public double[] get(int instance, String name) { + if (instance >= used_count) + used_count = instance + 1; + if (name == null) + return out[instance]; + if (name.equals("on")) + return on[instance]; + if (name.equals("active")) + return active[instance]; + if (name.equals("delay")) + return delay[instance]; + if (name.equals("attack")) + return attack[instance]; + if (name.equals("hold")) + return hold[instance]; + if (name.equals("decay")) + return decay[instance]; + if (name.equals("sustain")) + return sustain[instance]; + if (name.equals("release")) + return release[instance]; + if (name.equals("shutdown")) + return shutdown[instance]; + if (name.equals("attack2")) + return attack2[instance]; + if (name.equals("decay2")) + return decay2[instance]; + if (name.equals("release2")) + return release2[instance]; + + return null; + } + + public void processControlLogic() { + for (int i = 0; i < used_count; i++) { + + if (stage[i] == EG_END) { + continue; + } + + if ((stage[i] > EG_OFF) && (stage[i] < EG_RELEASE)) + if (on[i][0] < 0.5) { + + if (on[i][0] < -0.5) { + stage_count[i] = (int) (Math.pow(2, + this.shutdown[i][0] / 1200.0) / control_time); + if (stage_count[i] < 0) + stage_count[i] = 0; + stage_v[i] = out[i][0]; + stage_ix[i] = 0; + stage[i] = EG_SHUTDOWN; + } else { + + if ((release2[i][0] < 0.000001) && release[i][0] < 0 + && Double.isInfinite(release[i][0])) { + out[i][0] = 0; + active[i][0] = 0; + stage[i] = EG_END; + continue; + } + + stage_count[i] = (int) (Math.pow(2, + this.release[i][0] / 1200.0) / control_time); + stage_count[i] += (int) (this.release2[i][0] / (control_time * 1000)); + if (stage_count[i] < 0) + stage_count[i] = 0; + // stage_v[i] = out[i][0]; + stage_ix[i] = 0; // þetta á ekki að vera svona !!!! + + double m = 1 - out[i][0]; + stage_ix[i] = (int) (stage_count[i] * m); + + stage[i] = EG_RELEASE; + + } + } + + switch (stage[i]) { + case EG_OFF: + active[i][0] = 1; + if (on[i][0] < 0.5) break; + stage[i] = EG_DELAY; + stage_ix[i] = (int) (Math.pow(2, this.delay[i][0] / 1200.0) / control_time); + if(stage_ix[i] < 0) stage_ix[i] = 0; + case EG_DELAY: + if (stage_ix[i] == 0) { + double attack = this.attack[i][0]; + double attack2 = this.attack2[i][0]; + + if (attack2 < 0.000001 + && (attack < 0 && Double.isInfinite(attack))) { + out[i][0] = 1; + stage[i] = EG_HOLD; + stage_count[i] = (int) (Math.pow(2, + this.hold[i][0] / 1200.0) / control_time); + stage_ix[i] = 0; + } else { + stage[i] = EG_ATTACK; + stage_count[i] = (int) (Math.pow(2, attack / 1200.0) / control_time); + stage_count[i] += (int) (attack2 / (control_time * 1000)); + if (stage_count[i] < 0) + stage_count[i] = 0; + stage_ix[i] = 0; + } + } + else + stage_ix[i]--; + break; + case EG_ATTACK: + stage_ix[i]++; + if (stage_ix[i] >= stage_count[i]) { + out[i][0] = 1; + stage[i] = EG_HOLD; + } else { + // CONVEX attack + double a = ((double) stage_ix[i]) + / ((double) stage_count[i]); + a = 1 + ((40.0 / 96.0) / Math.log(10)) * Math.log(a); + if (a < 0) + a = 0; + else if (a > 1) + a = 1; + out[i][0] = a; + + } + break; + case EG_HOLD: + stage_ix[i]++; + if (stage_ix[i] >= stage_count[i]) { + stage[i] = EG_DECAY; + stage_count[i] = (int) (Math.pow(2, + this.decay[i][0] / 1200.0) / control_time); + stage_count[i] += (int) (this.decay2[i][0] / (control_time * 1000)); + if (stage_count[i] < 0) + stage_count[i] = 0; + stage_ix[i] = 0; + + } + break; + case EG_DECAY: + + stage_ix[i]++; + double sustain = this.sustain[i][0] * (1.0 / 1000.0); + if (stage_ix[i] >= stage_count[i]) { + out[i][0] = sustain; + stage[i] = EG_SUSTAIN; + if (sustain < 0.001) { + out[i][0] = 0; + active[i][0] = 0; + stage[i] = EG_END; + } + } else { + double m = ((double) stage_ix[i]) + / ((double) stage_count[i]); + out[i][0] = (1 - m) + sustain * m; + } + + break; + case EG_SUSTAIN: + break; + case EG_RELEASE: + stage_ix[i]++; + if (stage_ix[i] >= stage_count[i]) { + out[i][0] = 0; + active[i][0] = 0; + stage[i] = EG_END; + } else { + double m = ((double) stage_ix[i]) + / ((double) stage_count[i]); + out[i][0] = (1 - m); // *stage_v[i]; + + if (on[i][0] < -0.5) { + stage_count[i] = (int) (Math.pow(2, + this.shutdown[i][0] / 1200.0) / control_time); + if (stage_count[i] < 0) + stage_count[i] = 0; + stage_v[i] = out[i][0]; + stage_ix[i] = 0; + stage[i] = EG_SHUTDOWN; + } + + // re-damping + if (on[i][0] > 0.5) { + sustain = this.sustain[i][0] * (1.0 / 1000.0); + if (out[i][0] > sustain) { + + stage[i] = EG_DECAY; + stage_count[i] = (int) (Math.pow(2, + this.decay[i][0] / 1200.0) / control_time); + stage_count[i] += (int) (this.decay2[i][0] / (control_time * 1000)); + if (stage_count[i] < 0) + stage_count[i] = 0; + m = (out[i][0] - 1) / (sustain - 1); + stage_ix[i] = (int) (stage_count[i] * m); + } + } + + } + break; + case EG_SHUTDOWN: + stage_ix[i]++; + if (stage_ix[i] >= stage_count[i]) { + out[i][0] = 0; + active[i][0] = 0; + stage[i] = EG_END; + } else { + double m = ((double) stage_ix[i]) + / ((double) stage_count[i]); + out[i][0] = (1 - m) * stage_v[i]; + } + break; + default: + break; + } + } + + } + +} \ No newline at end of file diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,657 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * Infinite impulse response (IIR) filter class. + * + * The filters where implemented and adapted using algorithms from musicdsp.org + * archive: 1-RC and C filter, Simple 2-pole LP LP and HP filter, biquad, + * tweaked butterworth RBJ Audio-EQ-Cookbook, EQ filter kookbook + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftFilter { + + public static int FILTERTYPE_LP6 = 0x00; + + public static int FILTERTYPE_LP12 = 0x01; + + public static int FILTERTYPE_HP12 = 0x11; + + public static int FILTERTYPE_BP12 = 0x21; + + public static int FILTERTYPE_NP12 = 0x31; + + public static int FILTERTYPE_LP24 = 0x03; + + public static int FILTERTYPE_HP24 = 0x13; + + // + // 0x0 = 1st-order, 6 dB/oct + // 0x1 = 2nd-order, 12 dB/oct + // 0x2 = 3rd-order, 18 dB/oct + // 0x3 = 4th-order, 24 db/oct + // + // 0x00 = LP, Low Pass Filter + // 0x10 = HP, High Pass Filter + // 0x20 = BP, Band Pass Filter + // 0x30 = NP, Notch or Band Elimination Filter + // + + private int filtertype = FILTERTYPE_LP6; + + private float samplerate; + + private float x1; + + private float x2; + + private float y1; + + private float y2; + + private float xx1; + + private float xx2; + + private float yy1; + + private float yy2; + + private float a0; + + private float a1; + + private float a2; + + private float b1; + + private float b2; + + private float q; + + private float gain = 1; + + private float wet = 0; + + private float last_wet = 0; + + private float last_a0; + + private float last_a1; + + private float last_a2; + + private float last_b1; + + private float last_b2; + + private float last_q; + + private float last_gain; + + private boolean last_set = false; + + private double cutoff = 44100; + + private double resonancedB = 0; + + private boolean dirty = true; + + public SoftFilter(float samplerate) { + this.samplerate = samplerate; + dirty = true; + } + + public void setFrequency(double cent) { + if (cutoff == cent) + return; + cutoff = cent; + dirty = true; + } + + public void setResonance(double db) { + if (resonancedB == db) + return; + resonancedB = db; + dirty = true; + } + + public void reset() { + dirty = true; + last_set = false; + x1 = 0; + x2 = 0; + y1 = 0; + y2 = 0; + xx1 = 0; + xx2 = 0; + yy1 = 0; + yy2 = 0; + wet = 0.0f; + gain = 1.0f; + a0 = 0; + a1 = 0; + a2 = 0; + b1 = 0; + b2 = 0; + } + + public void setFilterType(int filtertype) { + this.filtertype = filtertype; + } + + public void processAudio(SoftAudioBuffer sbuffer) { + if (filtertype == FILTERTYPE_LP6) + filter1(sbuffer); + if (filtertype == FILTERTYPE_LP12) + filter2(sbuffer); + if (filtertype == FILTERTYPE_HP12) + filter2(sbuffer); + if (filtertype == FILTERTYPE_BP12) + filter2(sbuffer); + if (filtertype == FILTERTYPE_NP12) + filter2(sbuffer); + if (filtertype == FILTERTYPE_LP24) + filter4(sbuffer); + if (filtertype == FILTERTYPE_HP24) + filter4(sbuffer); + } + + public void filter4(SoftAudioBuffer sbuffer) { + + float[] buffer = sbuffer.array(); + + if (dirty) { + filter2calc(); + dirty = false; + } + if (!last_set) { + last_a0 = a0; + last_a1 = a1; + last_a2 = a2; + last_b1 = b1; + last_b2 = b2; + last_gain = gain; + last_wet = wet; + last_set = true; + } + + if (wet > 0 || last_wet > 0) { + + int len = buffer.length; + float a0 = this.last_a0; + float a1 = this.last_a1; + float a2 = this.last_a2; + float b1 = this.last_b1; + float b2 = this.last_b2; + float gain = this.last_gain; + float wet = this.last_wet; + float a0_delta = (this.a0 - this.last_a0) / len; + float a1_delta = (this.a1 - this.last_a1) / len; + float a2_delta = (this.a2 - this.last_a2) / len; + float b1_delta = (this.b1 - this.last_b1) / len; + float b2_delta = (this.b2 - this.last_b2) / len; + float gain_delta = (this.gain - this.last_gain) / len; + float wet_delta = (this.wet - this.last_wet) / len; + float x1 = this.x1; + float x2 = this.x2; + float y1 = this.y1; + float y2 = this.y2; + float xx1 = this.xx1; + float xx2 = this.xx2; + float yy1 = this.yy1; + float yy2 = this.yy2; + + if (wet_delta != 0) { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + a1 += a1_delta; + a2 += a2_delta; + b1 += b1_delta; + b2 += b2_delta; + gain += gain_delta; + wet += wet_delta; + float x = buffer[i]; + float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2); + float xx = (y * gain) * wet + (x) * (1 - wet); + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + float yy = (a0 * xx + a1 * xx1 + a2 * xx2 - b1 * yy1 - b2 + * yy2); + buffer[i] = (yy * gain) * wet + (xx) * (1 - wet); + xx2 = xx1; + xx1 = xx; + yy2 = yy1; + yy1 = yy; + } + } else if (a0_delta == 0 && a1_delta == 0 && a2_delta == 0 + && b1_delta == 0 && b2_delta == 0) { + for (int i = 0; i < len; i++) { + float x = buffer[i]; + float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2); + float xx = (y * gain) * wet + (x) * (1 - wet); + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + float yy = (a0 * xx + a1 * xx1 + a2 * xx2 - b1 * yy1 - b2 + * yy2); + buffer[i] = (yy * gain) * wet + (xx) * (1 - wet); + xx2 = xx1; + xx1 = xx; + yy2 = yy1; + yy1 = yy; + } + } else { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + a1 += a1_delta; + a2 += a2_delta; + b1 += b1_delta; + b2 += b2_delta; + gain += gain_delta; + float x = buffer[i]; + float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2); + float xx = (y * gain) * wet + (x) * (1 - wet); + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + float yy = (a0 * xx + a1 * xx1 + a2 * xx2 - b1 * yy1 - b2 + * yy2); + buffer[i] = (yy * gain) * wet + (xx) * (1 - wet); + xx2 = xx1; + xx1 = xx; + yy2 = yy1; + yy1 = yy; + } + } + + if (Math.abs(x1) < 1.0E-8) + x1 = 0; + if (Math.abs(x2) < 1.0E-8) + x2 = 0; + if (Math.abs(y1) < 1.0E-8) + y1 = 0; + if (Math.abs(y2) < 1.0E-8) + y2 = 0; + this.x1 = x1; + this.x2 = x2; + this.y1 = y1; + this.y2 = y2; + this.xx1 = xx1; + this.xx2 = xx2; + this.yy1 = yy1; + this.yy2 = yy2; + } + + this.last_a0 = this.a0; + this.last_a1 = this.a1; + this.last_a2 = this.a2; + this.last_b1 = this.b1; + this.last_b2 = this.b2; + this.last_gain = this.gain; + this.last_wet = this.wet; + + } + + private double sinh(double x) { + return (Math.exp(x) - Math.exp(-x)) * 0.5; + } + + public void filter2calc() { + + double resonancedB = this.resonancedB; + if (resonancedB < 0) + resonancedB = 0; // Negative dB are illegal. + if (resonancedB > 30) + resonancedB = 30; // At least 22.5 dB is needed. + if (filtertype == FILTERTYPE_LP24 || filtertype == FILTERTYPE_HP24) + resonancedB *= 0.6; + + if (filtertype == FILTERTYPE_BP12) { + wet = 1; + double r = (cutoff / samplerate); + if (r > 0.45) + r = 0.45; + + double bandwidth = Math.PI * Math.pow(10.0, -(resonancedB / 20)); + + double omega = 2 * Math.PI * r; + double cs = Math.cos(omega); + double sn = Math.sin(omega); + double alpha = sn + * sinh((Math.log(2) * bandwidth * omega) / (sn * 2)); + + double b0 = alpha; + double b1 = 0; + double b2 = -alpha; + double a0 = 1 + alpha; + double a1 = -2 * cs; + double a2 = 1 - alpha; + + double cf = 1.0 / a0; + this.b1 = (float) (a1 * cf); + this.b2 = (float) (a2 * cf); + this.a0 = (float) (b0 * cf); + this.a1 = (float) (b1 * cf); + this.a2 = (float) (b2 * cf); + } + + if (filtertype == FILTERTYPE_NP12) { + wet = 1; + double r = (cutoff / samplerate); + if (r > 0.45) + r = 0.45; + + double bandwidth = Math.PI * Math.pow(10.0, -(resonancedB / 20)); + + double omega = 2 * Math.PI * r; + double cs = Math.cos(omega); + double sn = Math.sin(omega); + double alpha = sn + * sinh((Math.log(2) * bandwidth * omega) / (sn * 2)); + + double b0 = 1; + double b1 = -2 * cs; + double b2 = 1; + double a0 = 1 + alpha; + double a1 = -2 * cs; + double a2 = 1 - alpha; + + double cf = 1.0 / a0; + this.b1 = (float) (a1 * cf); + this.b2 = (float) (a2 * cf); + this.a0 = (float) (b0 * cf); + this.a1 = (float) (b1 * cf); + this.a2 = (float) (b2 * cf); + } + + if (filtertype == FILTERTYPE_LP12 || filtertype == FILTERTYPE_LP24) { + double r = (cutoff / samplerate); + if (r > 0.45) { + if (wet == 0) + if (resonancedB < 0.00001) + wet = 0.0f; + else + wet = 1.0f; + r = 0.45; + } else + wet = 1.0f; + + double c = 1.0 / (Math.tan(Math.PI * r)); + double csq = c * c; + double resonance = Math.pow(10.0, -(resonancedB / 20)); + double q = Math.sqrt(2.0f) * resonance; + double a0 = 1.0 / (1.0 + (q * c) + (csq)); + double a1 = 2.0 * a0; + double a2 = a0; + double b1 = (2.0 * a0) * (1.0 - csq); + double b2 = a0 * (1.0 - (q * c) + csq); + + this.a0 = (float) a0; + this.a1 = (float) a1; + this.a2 = (float) a2; + this.b1 = (float) b1; + this.b2 = (float) b2; + + } + + if (filtertype == FILTERTYPE_HP12 || filtertype == FILTERTYPE_HP24) { + double r = (cutoff / samplerate); + if (r > 0.45) + r = 0.45; + if (r < 0.0001) + r = 0.0001; + wet = 1.0f; + double c = (Math.tan(Math.PI * (r))); + double csq = c * c; + double resonance = Math.pow(10.0, -(resonancedB / 20)); + double q = Math.sqrt(2.0f) * resonance; + double a0 = 1.0 / (1.0 + (q * c) + (csq)); + double a1 = -2.0 * a0; + double a2 = a0; + double b1 = (2.0 * a0) * (csq - 1.0); + double b2 = a0 * (1.0 - (q * c) + csq); + + this.a0 = (float) a0; + this.a1 = (float) a1; + this.a2 = (float) a2; + this.b1 = (float) b1; + this.b2 = (float) b2; + + } + + } + + public void filter2(SoftAudioBuffer sbuffer) { + + float[] buffer = sbuffer.array(); + + if (dirty) { + filter2calc(); + dirty = false; + } + if (!last_set) { + last_a0 = a0; + last_a1 = a1; + last_a2 = a2; + last_b1 = b1; + last_b2 = b2; + last_q = q; + last_gain = gain; + last_wet = wet; + last_set = true; + } + + if (wet > 0 || last_wet > 0) { + + int len = buffer.length; + float a0 = this.last_a0; + float a1 = this.last_a1; + float a2 = this.last_a2; + float b1 = this.last_b1; + float b2 = this.last_b2; + float gain = this.last_gain; + float wet = this.last_wet; + float a0_delta = (this.a0 - this.last_a0) / len; + float a1_delta = (this.a1 - this.last_a1) / len; + float a2_delta = (this.a2 - this.last_a2) / len; + float b1_delta = (this.b1 - this.last_b1) / len; + float b2_delta = (this.b2 - this.last_b2) / len; + float gain_delta = (this.gain - this.last_gain) / len; + float wet_delta = (this.wet - this.last_wet) / len; + float x1 = this.x1; + float x2 = this.x2; + float y1 = this.y1; + float y2 = this.y2; + + if (wet_delta != 0) { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + a1 += a1_delta; + a2 += a2_delta; + b1 += b1_delta; + b2 += b2_delta; + gain += gain_delta; + wet += wet_delta; + float x = buffer[i]; + float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2); + buffer[i] = (y * gain) * wet + (x) * (1 - wet); + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + } else if (a0_delta == 0 && a1_delta == 0 && a2_delta == 0 + && b1_delta == 0 && b2_delta == 0) { + for (int i = 0; i < len; i++) { + float x = buffer[i]; + float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2); + buffer[i] = y * gain; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + } else { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + a1 += a1_delta; + a2 += a2_delta; + b1 += b1_delta; + b2 += b2_delta; + gain += gain_delta; + float x = buffer[i]; + float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2); + buffer[i] = y * gain; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + } + + if (Math.abs(x1) < 1.0E-8) + x1 = 0; + if (Math.abs(x2) < 1.0E-8) + x2 = 0; + if (Math.abs(y1) < 1.0E-8) + y1 = 0; + if (Math.abs(y2) < 1.0E-8) + y2 = 0; + this.x1 = x1; + this.x2 = x2; + this.y1 = y1; + this.y2 = y2; + } + + this.last_a0 = this.a0; + this.last_a1 = this.a1; + this.last_a2 = this.a2; + this.last_b1 = this.b1; + this.last_b2 = this.b2; + this.last_q = this.q; + this.last_gain = this.gain; + this.last_wet = this.wet; + + } + + public void filter1calc() { + if (cutoff < 120) + cutoff = 120; + double c = (7.0 / 6.0) * Math.PI * 2 * cutoff / samplerate; + if (c > 1) + c = 1; + a0 = (float) (Math.sqrt(1 - Math.cos(c)) * Math.sqrt(0.5 * Math.PI)); + if (resonancedB < 0) + resonancedB = 0; + if (resonancedB > 20) + resonancedB = 20; + q = (float) (Math.sqrt(0.5) * Math.pow(10.0, -(resonancedB / 20))); + gain = (float) Math.pow(10, -((resonancedB)) / 40.0); + if (wet == 0.0f) + if (resonancedB > 0.00001 || c < 0.9999999) + wet = 1.0f; + } + + public void filter1(SoftAudioBuffer sbuffer) { + + float[] buffer = sbuffer.array(); + + if (dirty) { + filter1calc(); + dirty = false; + } + if (!last_set) { + last_a0 = a0; + last_q = q; + last_gain = gain; + last_wet = wet; + last_set = true; + } + + if (wet > 0 || last_wet > 0) { + + int len = buffer.length; + float a0 = this.last_a0; + float q = this.last_q; + float gain = this.last_gain; + float wet = this.last_wet; + float a0_delta = (this.a0 - this.last_a0) / len; + float q_delta = (this.q - this.last_q) / len; + float gain_delta = (this.gain - this.last_gain) / len; + float wet_delta = (this.wet - this.last_wet) / len; + float y2 = this.y2; + float y1 = this.y1; + + if (wet_delta != 0) { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + q += q_delta; + gain += gain_delta; + wet += wet_delta; + y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i]; + y2 = (1 - q * a0) * y2 + (a0) * y1; + buffer[i] = y2 * gain * wet + buffer[i] * (1 - wet); + } + } else if (a0_delta == 0 && q_delta == 0) { + for (int i = 0; i < len; i++) { + y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i]; + y2 = (1 - q * a0) * y2 + (a0) * y1; + buffer[i] = y2 * gain; + } + } else { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + q += q_delta; + gain += gain_delta; + y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i]; + y2 = (1 - q * a0) * y2 + (a0) * y1; + buffer[i] = y2 * gain; + } + } + + if (Math.abs(y2) < 1.0E-8) + y2 = 0; + if (Math.abs(y1) < 1.0E-8) + y1 = 0; + this.y2 = y2; + this.y1 = y1; + } + + this.last_a0 = this.a0; + this.last_q = this.q; + this.last_gain = this.gain; + this.last_wet = this.wet; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftInstrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftInstrument.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; + +/** + * + * Software synthesizer internal instrument. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftInstrument extends Instrument { + + private SoftPerformer[] performers; + + private ModelPerformer[] modelperformers; + + private Object data; + + private ModelInstrument ins; + + public SoftInstrument(ModelInstrument ins) { + super(ins.getSoundbank(), ins.getPatch(), ins.getName(), ins + .getDataClass()); + if (!(ins instanceof ModelInstrument)) + throw new IllegalArgumentException( + "Instrument doesn't implement ModelInstrument interface!"); + data = ins.getData(); + this.ins = ins; + initPerformers(((ModelInstrument) ins).getPerformers()); + } + + public SoftInstrument(ModelInstrument ins, + ModelPerformer[] overrideperformers) { + super(ins.getSoundbank(), ins.getPatch(), ins.getName(), ins + .getDataClass()); + if (!(ins instanceof ModelInstrument)) + throw new IllegalArgumentException( + "Instrument doesn't implement ModelInstrument interface!"); + data = ins.getData(); + this.ins = ins; + initPerformers(overrideperformers); + } + + private void initPerformers(ModelPerformer[] modelperformers) { + this.modelperformers = modelperformers; + performers = new SoftPerformer[modelperformers.length]; + for (int i = 0; i < modelperformers.length; i++) + performers[i] = new SoftPerformer(modelperformers[i]); + } + + public ModelDirector getDirector(MidiChannel channel, ModelDirectedPlayer player) + { + return ins.getDirector(modelperformers, channel, player); + } + + public ModelInstrument getSourceInstrument() { + return ins; + } + + public Object getData() { + return data; + } + + public SoftPerformer[] getPerformers() { + return performers; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,278 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; + +/** + * A jitter corrector to be used with SoftAudioPusher. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftJitterCorrector extends AudioInputStream { + private static class JitterStream extends InputStream { + + static int MAX_BUFFER_SIZE = 1048576; + + boolean active = true; + Thread thread; + AudioInputStream stream; + + // Cyclic buffer + int writepos = 0; + int readpos = 0; + byte[][] buffers; + byte[] nullbuff; + + // Adapative Drift Statistics + int w_count = 1000; + int w_min_tol = 2; + int w_max_tol = 10; + int w = 0; + int w_min = -1; + + // Current read buffer + int bbuffer_pos = 0; + int bbuffer_max = 0; + byte[] bbuffer = null; + + public byte[] nextReadBuffer() + { + synchronized(buffers) + { + if(writepos > readpos) + { + int w_m = writepos - readpos; + if(w_m < w_min) w_min = w_m; + + int buffpos = readpos; + readpos++; + return buffers[buffpos % buffers.length]; + } + w_min = -1; + w = w_count-1; + } + while(true) + { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + return null; + } + synchronized(buffers) + { + if(writepos > readpos) + { + w = 0; + w_min = -1; + w = w_count-1; + int buffpos = readpos; + readpos++; + return buffers[buffpos % buffers.length]; + } + } + } + } + + public byte[] nextWriteBuffer() + { + synchronized(buffers) + { + return buffers[writepos % buffers.length]; + } + } + + public void commit() + { + synchronized(buffers) + { + writepos++; + if((writepos - readpos) > buffers.length) + { + int newsize = (writepos - readpos) + 10; + newsize = Math.max(buffers.length*2, newsize); + buffers = new byte[newsize][buffers[0].length]; + } + } + } + + public JitterStream(AudioInputStream s, int buffersize, int smallbuffersize) + { + this.w_count = 10 * (buffersize/smallbuffersize); + if(w_count < 100) w_count = 100; + this.buffers = new byte[(buffersize/smallbuffersize)+10][smallbuffersize]; + this.bbuffer_max = MAX_BUFFER_SIZE / smallbuffersize; + this.nullbuff = new byte[smallbuffersize]; + this.stream = s; + + + Runnable runnable = new Runnable() + { + public void run() + { + AudioFormat format = stream.getFormat(); + int bufflen = buffers[0].length; + int frames = bufflen / format.getFrameSize(); + long nanos = (long) ( frames * 1000000000.0 / format.getSampleRate() ); + long now = System.nanoTime(); + long next = now + nanos; + int correction = 0; + while(true) + { + synchronized (JitterStream.this) { + if(!active) break; + } + int curbuffsize; + synchronized (buffers) { + curbuffsize = writepos - readpos; + if(correction == 0) + { + w++; + if(w_min != Integer.MAX_VALUE) + if(w == w_count) + { + correction = 0; + if(w_min < w_min_tol) correction = (w_min_tol+ w_max_tol)/2 - w_min; + if(w_min > w_max_tol) correction = (w_min_tol+ w_max_tol)/2 - w_min; + w = 0; + w_min = Integer.MAX_VALUE; + } + } + } + while(curbuffsize > bbuffer_max) + { + synchronized (buffers) { + curbuffsize = writepos - readpos; + } + synchronized (JitterStream.this) { + if(!active) break; + } + try { + Thread.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + if(correction < 0) + { + correction++; + } + else + { + byte[] buff = nextWriteBuffer(); + try { + stream.read(buff, 0, buff.length); + } catch (IOException e1) { + e1.printStackTrace(); + } + commit(); + } + + if(correction > 0) + { + correction--; + next = System.nanoTime() + nanos; + continue; + } + long wait = next - System.nanoTime(); + if(wait > 0) + { + try { + Thread.sleep(wait / 1000000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + next += nanos; + } + } + }; + + thread = new Thread(runnable); + thread.setPriority(Thread.MAX_PRIORITY); + thread.start(); + } + + public void close() throws IOException { + synchronized (this) { + active = false; + } + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + stream.close(); + } + + public int read() throws IOException { + byte[] b = new byte[1]; + if (read(b) == -1) + return -1; + return b[0] & 0xFF; + } + + public void fillBuffer() { + bbuffer = nextReadBuffer(); + bbuffer_pos = 0; + } + + public int read(byte[] b, int off, int len) { + if(bbuffer == null) fillBuffer(); + int bbuffer_len = bbuffer.length; + int offlen = off + len; + while (off < offlen) + if (available() == 0) + fillBuffer(); + else { + byte[] bbuffer = this.bbuffer; + int bbuffer_pos = this.bbuffer_pos; + while (off < offlen && bbuffer_pos < bbuffer_len) + b[off++] = bbuffer[bbuffer_pos++]; + this.bbuffer_pos = bbuffer_pos; + } + return len; + } + + public int available() { + return bbuffer.length - bbuffer_pos; + } + + }; + + public SoftJitterCorrector(AudioInputStream stream, int buffersize, int smallbuffersize) { + super(new JitterStream(stream, buffersize, smallbuffersize), stream.getFormat(), stream + .getFrameLength()); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLanczosResampler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLanczosResampler.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,121 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * Lanczos interpolation resampler. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftLanczosResampler extends SoftAbstractResampler { + + double[] din; + + float[][] sinc_table; + + int sinc_table_fsize = 2000; + + int sinc_table_size = 5; + + int sinc_table_center = sinc_table_size / 2; + + public SoftLanczosResampler() { + super(); + sinc_table = new float[sinc_table_fsize][]; + for (int i = 0; i < sinc_table_fsize; i++) + sinc_table[i] = sincTable(sinc_table_size, -i + / ((float) sinc_table_fsize)); + } + + // Normalized sinc function + public static double sinc(double x) { + return (x == 0.0) ? 1.0 : Math.sin(Math.PI * x) / (Math.PI * x); + } + + // Generate sinc table + public static float[] sincTable(int size, float offset) { + int center = size / 2; + float[] w = new float[size]; + for (int k = 0; k < size; k++) { + float x = (-center + k + offset); + if (x < -2 || x > 2) + w[k] = 0; + else if (x == 0) + w[k] = 1; + else + w[k] = (float) (2.0 * Math.sin(Math.PI * x) + * Math.sin(Math.PI * x / 2.0) / ((Math.PI * x) * (Math.PI * x))); + } + return w; + } + + public int getPadding() // must be at least half of sinc_table_size + { + return sinc_table_size / 2 + 2; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + + if (pitchstep == 0) { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float[] sinc_table = this.sinc_table[(int) ((ix - iix) * sinc_table_fsize)]; + int xx = iix - sinc_table_center; + float y = 0; + for (int i = 0; i < sinc_table_size; i++, xx++) + y += in[xx] * sinc_table[i]; + out[ox++] = y; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float[] sinc_table = this.sinc_table[(int) ((ix - iix) * sinc_table_fsize)]; + int xx = iix - sinc_table_center; + float y = 0; + for (int i = 0; i < sinc_table_size; i++, xx++) + y += in[xx] * sinc_table[i]; + out[ox++] = y; + + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLimiter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLimiter.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,202 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * A simple look-ahead volume limiter with very fast attack and fast release. + * This filter is used for preventing clipping. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftLimiter implements SoftAudioProcessor { + + float lastmax = 0; + + float gain = 1; + + float[] temp_bufferL; + + float[] temp_bufferR; + + boolean mix = false; + + SoftAudioBuffer bufferL; + + SoftAudioBuffer bufferR; + + SoftAudioBuffer bufferLout; + + SoftAudioBuffer bufferRout; + + SoftSynthesizer synth; + + public void init(SoftSynthesizer synth) { + this.synth = synth; + } + + public void setInput(int pin, SoftAudioBuffer input) { + if (pin == 0) + bufferL = input; + if (pin == 1) + bufferR = input; + } + + public void setOutput(int pin, SoftAudioBuffer output) { + if (pin == 0) + bufferLout = output; + if (pin == 1) + bufferRout = output; + } + + public void setMixMode(boolean mix) { + this.mix = mix; + } + + public void globalParameterControlChange(int[] slothpath, long param, + long value) { + + } + + double silentcounter = 0; + + public void processAudio() { + if (this.bufferL.isSilent() + && (this.bufferR == null || this.bufferR.isSilent())) { + silentcounter += 1 / synth.getControlRate(); + + if (silentcounter > 60) { + if (!mix) { + bufferLout.clear(); + bufferRout.clear(); + } + return; + } + } else + silentcounter = 0; + + float[] bufferL = this.bufferL.array(); + float[] bufferR = this.bufferR == null ? null : this.bufferR.array(); + float[] bufferLout = this.bufferLout.array(); + float[] bufferRout = this.bufferRout == null ? null : this.bufferRout + .array(); + + if (temp_bufferL == null || temp_bufferL.length < bufferL.length) + temp_bufferL = new float[bufferL.length]; + if (bufferR != null) + if (temp_bufferR == null || temp_bufferR.length < bufferR.length) + temp_bufferR = new float[bufferR.length]; + + float max = 0; + int len = bufferL.length; + + if (bufferR == null) + for (int i = 0; i < len; i++) { + if (bufferL[i] > max) + max = bufferL[i]; + if (-bufferL[i] > max) + max = -bufferL[i]; + } + else + for (int i = 0; i < len; i++) { + if (bufferL[i] > max) + max = bufferL[i]; + if (bufferR[i] > max) + max = bufferR[i]; + if (-bufferL[i] > max) + max = -bufferL[i]; + if (-bufferR[i] > max) + max = -bufferR[i]; + } + + float lmax = lastmax; + lastmax = max; + if (lmax > max) + max = lmax; + + float newgain = 1; + if (max > 0.99f) + newgain = 0.99f / max; + else + newgain = 1; + + if (newgain > gain) + newgain = (newgain + gain * 9) / 10f; + + float gaindelta = (newgain - gain) / len; + if (mix) { + if (bufferR == null) + for (int i = 0; i < len; i++) { + gain += gaindelta; + float bL = bufferL[i]; + float tL = temp_bufferL[i]; + temp_bufferL[i] = bL; + bufferLout[i] += tL * gain; + } + else + for (int i = 0; i < len; i++) { + gain += gaindelta; + float bL = bufferL[i]; + float bR = bufferR[i]; + float tL = temp_bufferL[i]; + float tR = temp_bufferR[i]; + temp_bufferL[i] = bL; + temp_bufferR[i] = bR; + bufferLout[i] += tL * gain; + bufferRout[i] += tR * gain; + } + + } else { + if (bufferR == null) + for (int i = 0; i < len; i++) { + gain += gaindelta; + float bL = bufferL[i]; + float tL = temp_bufferL[i]; + temp_bufferL[i] = bL; + bufferLout[i] = tL * gain; + } + else + for (int i = 0; i < len; i++) { + gain += gaindelta; + float bL = bufferL[i]; + float bR = bufferR[i]; + float tL = temp_bufferL[i]; + float tR = temp_bufferR[i]; + temp_bufferL[i] = bL; + temp_bufferR[i] = bR; + bufferLout[i] = tL * gain; + bufferRout[i] = tR * gain; + } + + } + gain = newgain; + } + + public void processControlLogic() { + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * A resampler that uses first-order (linear) interpolation. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftLinearResampler extends SoftAbstractResampler { + + public int getPadding() { + return 2; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0f) { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float fix = ix - iix; + float i = in[iix]; + out[ox++] = i + (in[iix + 1] - i) * fix; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float fix = ix - iix; + float i = in[iix]; + out[ox++] = i + (in[iix + 1] - i) * fix; + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler2.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,110 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * A resampler that uses first-order (linear) interpolation. + * + * This one doesn't perform float to int casting + * inside the processing loop. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftLinearResampler2 extends SoftAbstractResampler { + + public int getPadding() { + return 2; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + + // Check if we have do anything + if(!(ix < ix_end && ox < ox_end)) return; + + // 15 bit shift was choosed because + // it resulted in no drift between p_ix and ix. + int p_ix = (int)(ix * (1 << 15)); + int p_ix_end = (int)(ix_end * (1 << 15)); + int p_pitch = (int)(pitch * (1 << 15)); + // Pitch needs to recalculated + // to ensure no drift between p_ix and ix. + pitch = p_pitch * (1f/(1 << 15)); + + if (pitchstep == 0f) { + + // To reduce + // while (p_ix < p_ix_end && ox < ox_end) + // into + // while (ox < ox_end) + // We need to calculate new ox_end value. + int p_ix_len = p_ix_end - p_ix; + int p_mod = p_ix_len % p_pitch; + if(p_mod != 0) p_ix_len += p_pitch - p_mod; + int ox_end2 = ox + p_ix_len/p_pitch; + if(ox_end2 < ox_end) ox_end = ox_end2; + + while (ox < ox_end) { + int iix = p_ix >> 15; + float fix = ix - iix; + float i = in[iix]; + out[ox++] = i + (in[iix + 1] - i) * fix; + p_ix += p_pitch; + ix += pitch; + } + + } else { + + int p_pitchstep = (int)(pitchstep * (1 << 15)); + pitchstep = p_pitchstep * (1f/(1 << 15)); + + while (p_ix < p_ix_end && ox < ox_end) { + int iix = p_ix >> 15; + float fix = ix - iix; + float i = in[iix]; + out[ox++] = i + (in[iix + 1] - i) * fix; + ix += pitch; + p_ix += p_pitch; + pitch += pitchstep; + p_pitch += p_pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,138 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * LFO control signal generator. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftLowFrequencyOscillator implements SoftProcess { + + private int max_count = 10; + + private int used_count = 0; + + private double[][] out = new double[max_count][1]; + + private double[][] delay = new double[max_count][1]; + + private double[][] delay2 = new double[max_count][1]; + + private double[][] freq = new double[max_count][1]; + + private int[] delay_counter = new int[max_count]; + + private double[] sin_phase = new double[max_count]; + + private double[] sin_stepfreq = new double[max_count]; + private double[] sin_step = new double[max_count]; + + private double control_time = 0; + + private double sin_factor = 0; + + private static double PI2 = 2.0 * Math.PI; + + public void reset() { + for (int i = 0; i < used_count; i++) { + out[i][0] = 0; + delay[i][0] = 0; + delay2[i][0] = 0; + freq[i][0] = 0; + delay_counter[i] = 0; + sin_phase[i] = 0; + sin_stepfreq[i] = 0; + sin_step[i] = 0; + } + used_count = 0; + } + + public void init(SoftSynthesizer synth) { + control_time = 1.0 / synth.getControlRate(); + sin_factor = control_time * 2 * Math.PI; + for (int i = 0; i < used_count; i++) { + delay_counter[i] = (int) (Math.pow(2, this.delay[i][0] / 1200.0) / control_time); + delay_counter[i] += (int) (delay2[i][0] / (control_time * 1000)); + } + processControlLogic(); + } + + public void processControlLogic() { + for (int i = 0; i < used_count; i++) { + if (delay_counter[i] > 0) { + delay_counter[i]--; + out[i][0] = 0.5; + } else { + double f = freq[i][0]; + + if(sin_stepfreq[i] != f) + { + sin_stepfreq[i] = f; + double fr = 440.0 * Math.exp( + (f - 6900.0) * (Math.log(2)/ 1200.0)); + sin_step[i] = fr * sin_factor; + } + /* + double fr = 440.0 * Math.pow(2.0, + (freq[i][0] - 6900.0) / 1200.0); + sin_phase[i] += fr * sin_factor; + */ + /* + sin_phase[i] += sin_step[i]; + while (sin_phase[i] > PI2) + sin_phase[i] -= PI2; + out[i][0] = 0.5 + Math.sin(sin_phase[i]) * 0.5; + */ + double p = sin_phase[i]; + p += sin_step[i]; + while (p > PI2) + p -= PI2; + out[i][0] = 0.5 + Math.sin(p) * 0.5; + sin_phase[i] = p; + + + } + } + } + + public double[] get(int instance, String name) { + if (instance >= used_count) + used_count = instance + 1; + if (name == null) + return out[instance]; + if (name.equals("delay")) + return delay[instance]; + if (name.equals("delay2")) + return delay2[instance]; + if (name.equals("freq")) + return freq[instance]; + return null; + } + +} \ No newline at end of file diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,1003 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.TreeMap; +import java.util.Map.Entry; + +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Patch; +import javax.sound.midi.ShortMessage; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * Software synthesizer main audio mixer. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftMainMixer { + + public final static int CHANNEL_LEFT = 0; + + public final static int CHANNEL_RIGHT = 1; + + public final static int CHANNEL_EFFECT1 = 2; + + public final static int CHANNEL_EFFECT2 = 3; + + public final static int CHANNEL_EFFECT3 = 4; + + public final static int CHANNEL_EFFECT4 = 5; + + public final static int CHANNEL_LEFT_DRY = 10; + + public final static int CHANNEL_RIGHT_DRY = 11; + + public final static int CHANNEL_SCRATCH1 = 12; + + public final static int CHANNEL_SCRATCH2 = 13; + + public final static int CHANNEL_CHANNELMIXER_LEFT = 14; + + public final static int CHANNEL_CHANNELMIXER_RIGHT = 15; + + protected boolean active_sensing_on = false; + + protected long msec_last_activity = -1; + + protected long msec_pos = 0; + + protected boolean readfully = true; + + private Object control_mutex; + + private SoftSynthesizer synth; + + private int nrofchannels = 2; + + private SoftVoice[] voicestatus = null; + + private SoftAudioBuffer[] buffers; + + private SoftAudioProcessor reverb; + + private SoftAudioProcessor chorus; + + private SoftAudioProcessor agc; + + private long msec_buffer_len = 0; + + protected TreeMap midimessages = new TreeMap(); + + double finetuning = 0; + + double coarsetuning = 0; + + double last_volume_left = 1.0; + + double last_volume_right = 1.0; + + private double[] co_master_balance = new double[1]; + + private double[] co_master_volume = new double[1]; + + private double[] co_master_coarse_tuning = new double[1]; + + private double[] co_master_fine_tuning = new double[1]; + + private AudioInputStream ais; + + private Set registeredMixers = null; + + private Set stoppedMixers = null; + + private ModelChannelMixer[] cur_registeredMixers = null; + + protected SoftControl co_master = new SoftControl() { + double[] balance = co_master_balance; + + double[] volume = co_master_volume; + + double[] coarse_tuning = co_master_coarse_tuning; + + double[] fine_tuning = co_master_fine_tuning; + + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("balance")) + return balance; + if (name.equals("volume")) + return volume; + if (name.equals("coarse_tuning")) + return coarse_tuning; + if (name.equals("fine_tuning")) + return fine_tuning; + return null; + } + }; + + private void processSystemExclusiveMessage(byte[] data) { + synchronized (synth.control_mutex) { + msec_last_activity = msec_pos; + + // Universal Non-Real-Time SysEx + if ((data[1] & 0xFF) == 0x7E) { + int deviceID = data[2] & 0xFF; + if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { + int subid1 = data[3] & 0xFF; + int subid2; + switch (subid1) { + case 0x08: // MIDI Tuning Standard + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // BULK TUNING DUMP + { + // http://www.midi.org/about-midi/tuning.shtml + SoftTuning tuning = synth.getTuning(new Patch(0, + data[5] & 0xFF)); + tuning.load(data); + break; + } + case 0x04: // KEY-BASED TUNING DUMP + case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format + case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format + case 0x07: // SINGLE NOTE TUNING CHANGE (NON REAL-TIME) + // (BANK) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + SoftTuning tuning = synth.getTuning(new Patch( + data[5] & 0xFF, data[6] & 0xFF)); + tuning.load(data); + break; + } + case 0x08: // scale/octave tuning 1-byte form (Non + // Real-Time) + case 0x09: // scale/octave tuning 2-byte form (Non + // Real-Time) + { + // http://www.midi.org/about-midi/tuning-scale.shtml + SoftTuning tuning = new SoftTuning(data); + int channelmask = (data[5] & 0xFF) * 16384 + + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); + SoftChannel[] channels = synth.channels; + for (int i = 0; i < channels.length; i++) + if ((channelmask & (1 << i)) != 0) + channels[i].tuning = tuning; + break; + } + default: + break; + } + break; + case 0x09: // General Midi Message + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // General Midi 1 On + synth.setGeneralMidiMode(1); + reset(); + break; + case 0x02: // General Midi Off + synth.setGeneralMidiMode(0); + reset(); + break; + case 0x03: // General MidI Level 2 On + synth.setGeneralMidiMode(2); + reset(); + break; + default: + break; + } + break; + case 0x0A: // DLS Message + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // DLS On + if (synth.getGeneralMidiMode() == 0) + synth.setGeneralMidiMode(1); + synth.voice_allocation_mode = 1; + reset(); + break; + case 0x02: // DLS Off + synth.setGeneralMidiMode(0); + synth.voice_allocation_mode = 0; + reset(); + break; + case 0x03: // DLS Static Voice Allocation Off + synth.voice_allocation_mode = 0; + break; + case 0x04: // DLS Static Voice Allocation On + synth.voice_allocation_mode = 1; + break; + default: + break; + } + break; + + default: + break; + } + } + } + + // Universal Real-Time SysEx + if ((data[1] & 0xFF) == 0x7F) { + int deviceID = data[2] & 0xFF; + if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { + int subid1 = data[3] & 0xFF; + int subid2; + switch (subid1) { + case 0x04: // Device Control + + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // Master Volume + case 0x02: // Master Balane + case 0x03: // Master fine tuning + case 0x04: // Master coarse tuning + int val = (data[5] & 0x7F) + + ((data[6] & 0x7F) * 128); + if (subid2 == 0x01) + setVolume(val); + else if (subid2 == 0x02) + setBalance(val); + else if (subid2 == 0x03) + setFineTuning(val); + else if (subid2 == 0x04) + setCoarseTuning(val); + break; + case 0x05: // Global Parameter Control + int ix = 5; + int slotPathLen = (data[ix++] & 0xFF); + int paramWidth = (data[ix++] & 0xFF); + int valueWidth = (data[ix++] & 0xFF); + int[] slotPath = new int[slotPathLen]; + for (int i = 0; i < slotPathLen; i++) { + int msb = (data[ix++] & 0xFF); + int lsb = (data[ix++] & 0xFF); + slotPath[i] = msb * 128 + lsb; + } + int paramCount = (data.length - 1 - ix) + / (paramWidth + valueWidth); + long[] params = new long[paramCount]; + long[] values = new long[paramCount]; + for (int i = 0; i < paramCount; i++) { + values[i] = 0; + for (int j = 0; j < paramWidth; j++) + params[i] = params[i] * 128 + + (data[ix++] & 0xFF); + for (int j = 0; j < valueWidth; j++) + values[i] = values[i] * 128 + + (data[ix++] & 0xFF); + + } + globalParameterControlChange(slotPath, params, values); + break; + default: + break; + } + break; + + case 0x08: // MIDI Tuning Standard + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME) + { + // http://www.midi.org/about-midi/tuning.shtml + SoftTuning tuning = synth.getTuning(new Patch(0, + data[5] & 0xFF)); + tuning.load(data); + SoftVoice[] voices = synth.getVoices(); + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + if (voices[i].tuning == tuning) + voices[i].updateTuning(tuning); + break; + } + case 0x07: // SINGLE NOTE TUNING CHANGE (REAL-TIME) + // (BANK) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + SoftTuning tuning = synth.getTuning(new Patch( + data[5] & 0xFF, data[6] & 0xFF)); + tuning.load(data); + SoftVoice[] voices = synth.getVoices(); + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + if (voices[i].tuning == tuning) + voices[i].updateTuning(tuning); + + break; + } + case 0x08: // scale/octave tuning 1-byte form + // (Real-Time) + case 0x09: // scale/octave tuning 2-byte form + // (Real-Time) + { + // http://www.midi.org/about-midi/tuning-scale.shtml + SoftTuning tuning = new SoftTuning(data); + int channelmask = (data[5] & 0xFF) * 16384 + + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); + SoftChannel[] channels = synth.channels; + for (int i = 0; i < channels.length; i++) + if ((channelmask & (1 << i)) != 0) + channels[i].tuning = tuning; + SoftVoice[] voices = synth.getVoices(); + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + if ((channelmask & (1 << (voices[i].channel))) != 0) + voices[i].updateTuning(tuning); + break; + } + default: + break; + } + break; + case 0x09: // Control Destination Settings + + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // Channel Pressure + { + int[] destinations = new int[(data.length - 7) / 2]; + int[] ranges = new int[(data.length - 7) / 2]; + int ix = 0; + for (int j = 6; j < data.length - 1; j += 2) { + destinations[ix] = data[j] & 0xFF; + ranges[ix] = data[j + 1] & 0xFF; + ix++; + } + int channel = data[5] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + softchannel.mapChannelPressureToDestination( + destinations, ranges); + break; + } + case 0x02: // Poly Pressure + { + int[] destinations = new int[(data.length - 7) / 2]; + int[] ranges = new int[(data.length - 7) / 2]; + int ix = 0; + for (int j = 6; j < data.length - 1; j += 2) { + destinations[ix] = data[j] & 0xFF; + ranges[ix] = data[j + 1] & 0xFF; + ix++; + } + int channel = data[5] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + softchannel.mapPolyPressureToDestination( + destinations, ranges); + break; + } + case 0x03: // Control Change + { + + int[] destinations = new int[(data.length - 7) / 2]; + int[] ranges = new int[(data.length - 7) / 2]; + int ix = 0; + for (int j = 7; j < data.length - 1; j += 2) { + destinations[ix] = data[j] & 0xFF; + ranges[ix] = data[j + 1] & 0xFF; + ix++; + } + int channel = data[5] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + int control = data[6] & 0xFF; + softchannel.mapControlToDestination(control, + destinations, ranges); + break; + } + default: + break; + } + break; + + case 0x0A: // Key Based Instrument Control + { + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // Basic Message + int channel = data[5] & 0xFF; + int keynumber = data[6] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + for (int j = 7; j < data.length - 1; j += 2) { + int controlnumber = data[j] & 0xFF; + int controlvalue = data[j + 1] & 0xFF; + softchannel.controlChangePerNote(keynumber, + controlnumber, controlvalue); + } + break; + default: + break; + } + break; + } + default: + break; + } + } + } + + } + } + + private void processMessages(long timeStamp) { + + Iterator> iter = midimessages.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + if (entry.getKey() > (timeStamp + 100)) + return; + processMessage(entry.getValue()); + iter.remove(); + } + } + + protected void processAudioBuffers() { + for (int i = 0; i < buffers.length; i++) { + buffers[i].clear(); + } + + double volume_left; + double volume_right; + + ModelChannelMixer[] act_registeredMixers; + + // perform control logic + synchronized (control_mutex) { + + processMessages(msec_pos); + + if (active_sensing_on) { + // Active Sensing + // if no message occurs for max 1000 ms + // then do AllSoundOff on all channels + if ((msec_pos - msec_last_activity) > 1000000) { + active_sensing_on = false; + for (SoftChannel c : synth.channels) + c.allSoundOff(); + } + + } + + for (int i = 0; i < voicestatus.length; i++) + if (voicestatus[i].active) + voicestatus[i].processControlLogic(); + msec_pos += msec_buffer_len; + + double volume = co_master_volume[0]; + volume_left = volume; + volume_right = volume; + + double balance = co_master_balance[0]; + if (balance > 0.5) + volume_left *= (1 - balance) * 2; + else + volume_right *= balance * 2; + + chorus.processControlLogic(); + reverb.processControlLogic(); + agc.processControlLogic(); + + if(cur_registeredMixers == null) + if(registeredMixers != null) + { + cur_registeredMixers = new ModelChannelMixer[registeredMixers.size()]; + registeredMixers.toArray(cur_registeredMixers); + } + + act_registeredMixers = cur_registeredMixers; + if(act_registeredMixers != null) + if(act_registeredMixers.length == 0) + act_registeredMixers = null; + + } + + if(act_registeredMixers != null) + { + + // Reroute default left,right output + // to channelmixer left,right input/output + SoftAudioBuffer leftbak = buffers[CHANNEL_LEFT]; + SoftAudioBuffer rightbak = buffers[CHANNEL_RIGHT]; + buffers[CHANNEL_LEFT] = buffers[CHANNEL_CHANNELMIXER_LEFT]; + buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_LEFT]; + + int bufferlen = buffers[CHANNEL_LEFT].getSize(); + + float[][] cbuffer = new float[nrofchannels][]; + cbuffer[0] = buffers[CHANNEL_LEFT].array(); + if (nrofchannels != 1) + cbuffer[1] = buffers[CHANNEL_RIGHT].array(); + + float[][] obuffer = new float[nrofchannels][]; + obuffer[0] = leftbak.array(); + if (nrofchannels != 1) + obuffer[1] = rightbak.array(); + + for (ModelChannelMixer cmixer : act_registeredMixers) { + for (int i = 0; i < cbuffer.length; i++) + Arrays.fill(cbuffer[i], 0); + boolean hasactivevoices = false; + for (int i = 0; i < voicestatus.length; i++) + if (voicestatus[i].active) + if(voicestatus[i].channelmixer == cmixer) + { + voicestatus[i].processAudioLogic(buffers); + hasactivevoices = true; + } + if(!cmixer.process(cbuffer, 0, bufferlen)) + { + synchronized (control_mutex) { + registeredMixers.remove(cmixer); + cur_registeredMixers = null; + } + } + + for (int i = 0; i < cbuffer.length; i++) + { + float[] cbuff = cbuffer[i]; + float[] obuff = obuffer[i]; + for (int j = 0; j < bufferlen; j++) + obuff[j] += cbuff[j]; + } + + if(!hasactivevoices) + { + synchronized (control_mutex) { + if(stoppedMixers != null) + if(stoppedMixers.contains(cmixer)) + { + stoppedMixers.remove(cmixer); + cmixer.stop(); + } + } + } + + } + + buffers[CHANNEL_LEFT] = leftbak; + buffers[CHANNEL_RIGHT] = rightbak; + + } + + for (int i = 0; i < voicestatus.length; i++) + if (voicestatus[i].active) + if(voicestatus[i].channelmixer == null) + voicestatus[i].processAudioLogic(buffers); + + // Run effects + if(synth.chorus_on) + chorus.processAudio(); + + if(synth.reverb_on) + reverb.processAudio(); + + if (nrofchannels == 1) + volume_left = (volume_left + volume_right) / 2; + + // Set Volume / Balance + if (last_volume_left != volume_left + || last_volume_right != volume_right) { + float[] left = buffers[CHANNEL_LEFT].array(); + float[] right = buffers[CHANNEL_RIGHT].array(); + int bufferlen = buffers[CHANNEL_LEFT].getSize(); + + float amp; + float amp_delta; + amp = (float) (last_volume_left * last_volume_left); + amp_delta = (float) ((volume_left * volume_left - amp) / bufferlen); + for (int i = 0; i < bufferlen; i++) { + amp += amp_delta; + left[i] *= amp; + } + if (nrofchannels != 1) { + amp = (float) (last_volume_right * last_volume_right); + amp_delta = (float) ((volume_right * volume_right - amp) / bufferlen); + for (int i = 0; i < bufferlen; i++) { + amp += amp_delta; + right[i] *= volume_right; + } + } + last_volume_left = volume_left; + last_volume_right = volume_right; + + } else { + if (volume_left != 1.0 || volume_right != 1.0) { + float[] left = buffers[CHANNEL_LEFT].array(); + float[] right = buffers[CHANNEL_RIGHT].array(); + int bufferlen = buffers[CHANNEL_LEFT].getSize(); + float amp; + amp = (float) (volume_left * volume_left); + for (int i = 0; i < bufferlen; i++) + left[i] *= amp; + if (nrofchannels != 1) { + amp = (float) (volume_right * volume_right); + for (int i = 0; i < bufferlen; i++) + right[i] *= amp; + } + + } + } + + if(synth.agc_on) + agc.processAudio(); + + } + + public void stopMixer(ModelChannelMixer mixer) + { + if(stoppedMixers == null) + stoppedMixers = new HashSet(); + stoppedMixers.add(mixer); + } + + public void registerMixer(ModelChannelMixer mixer) + { + if(registeredMixers == null) + registeredMixers = new HashSet(); + registeredMixers.add(mixer); + cur_registeredMixers = null; + } + + + public SoftMainMixer(SoftSynthesizer synth) { + this.synth = synth; + + msec_pos = 0; + + co_master_balance[0] = 0.5; + co_master_volume[0] = 1; + co_master_coarse_tuning[0] = 0.5; + co_master_fine_tuning[0] = 0.5; + + msec_buffer_len = (long) (1000000.0 / synth.getControlRate()); + + nrofchannels = synth.getFormat().getChannels(); + + int buffersize = (int) (synth.getFormat().getSampleRate() / synth + .getControlRate()); + ; + + control_mutex = synth.control_mutex; + buffers = new SoftAudioBuffer[16]; + for (int i = 0; i < buffers.length; i++) { + buffers[i] = new SoftAudioBuffer(buffersize, synth.getFormat()); + + } + voicestatus = synth.getVoices(); + + reverb = new SoftReverb(); + chorus = new SoftChorus(); + agc = new SoftLimiter(); + + reverb.init(synth); + chorus.init(synth); + agc.init(synth); + + reverb.setMixMode(true); + chorus.setMixMode(true); + agc.setMixMode(false); + + chorus.setInput(0, buffers[CHANNEL_EFFECT2]); + chorus.setOutput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + chorus.setOutput(1, buffers[CHANNEL_RIGHT]); + chorus.setOutput(2, buffers[CHANNEL_EFFECT1]); + + reverb.setInput(0, buffers[CHANNEL_EFFECT1]); + reverb.setOutput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + reverb.setOutput(1, buffers[CHANNEL_RIGHT]); + + agc.setInput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + agc.setInput(1, buffers[CHANNEL_RIGHT]); + agc.setOutput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + agc.setOutput(1, buffers[CHANNEL_RIGHT]); + + InputStream in = new InputStream() { + + private SoftAudioBuffer[] buffers = SoftMainMixer.this.buffers; + private int nrofchannels = SoftMainMixer.this.synth.getFormat().getChannels(); + private int buffersize = buffers[0].getSize(); + private byte[] bbuffer = new byte[buffersize + * (SoftMainMixer.this.synth.getFormat().getSampleSizeInBits() / 8) * nrofchannels]; + private int bbuffer_pos = 0; + private byte[] single = new byte[1]; + + public void fillBuffer() { + processAudioBuffers(); + for (int i = 0; i < nrofchannels; i++) + buffers[i].get(bbuffer, i); + bbuffer_pos = 0; + } + + public int read(byte[] b, int off, int len) { + int bbuffer_len = bbuffer.length; + int offlen = off + len; + int orgoff = off; + byte[] bbuffer = this.bbuffer; + while (off < offlen) + if (available() == 0) + fillBuffer(); + else { + int bbuffer_pos = this.bbuffer_pos; + while (off < offlen && bbuffer_pos < bbuffer_len) + b[off++] = bbuffer[bbuffer_pos++]; + this.bbuffer_pos = bbuffer_pos; + if(!readfully) + return off - orgoff; + } + return len; + } + + public int read() throws IOException { + int ret = read(single); + if(ret == -1) return -1; + return single[0] & 0xFF; + } + + public int available() { + return bbuffer.length - bbuffer_pos; + } + + public void close() { + SoftMainMixer.this.synth.close(); + } + + }; + + ais = new AudioInputStream(in, synth.getFormat(), AudioSystem.NOT_SPECIFIED); + + } + + public AudioInputStream getInputStream() { + return ais; + } + + public void reset() { + + SoftChannel[] channels = synth.channels; + for (int i = 0; i < channels.length; i++) { + channels[i].allSoundOff(); + channels[i].resetAllControllers(true); + + if (synth.getGeneralMidiMode() == 2) { + if (i == 9) + channels[i].programChange(0, 0x78 * 128); + else + channels[i].programChange(0, 0x79 * 128); + } else + channels[i].programChange(0, 0); + } + setVolume(0x7F * 128 + 0x7F); + setBalance(0x40 * 128 + 0x00); + setCoarseTuning(0x40 * 128 + 0x00); + setFineTuning(0x40 * 128 + 0x00); + // Reset Reverb + globalParameterControlChange( + new int[] { 0x01 * 128 + 0x01 }, new long[] { 0 }, + new long[] { 4 }); + // Reset Chorus + globalParameterControlChange( + new int[] { 0x01 * 128 + 0x02 }, new long[] { 0 }, + new long[] { 2 }); + } + + + public void setVolume(int value) { + synchronized (control_mutex) { + co_master_volume[0] = value / 16384.0; + } + } + + public void setBalance(int value) { + synchronized (control_mutex) { + co_master_balance[0] = value / 16384.0; + } + } + + public void setFineTuning(int value) { + synchronized (control_mutex) { + co_master_fine_tuning[0] = value / 16384.0; + } + } + + public void setCoarseTuning(int value) { + synchronized (control_mutex) { + co_master_coarse_tuning[0] = value / 16384.0; + } + } + + public int getVolume() { + synchronized (control_mutex) { + return (int)(co_master_volume[0] * 16384.0); + } + } + + public int getBalance() { + synchronized (control_mutex) { + return (int)(co_master_balance[0] * 16384.0); + } + } + + public int getFineTuning() { + synchronized (control_mutex) { + return (int)(co_master_fine_tuning[0] * 16384.0); + } + } + + public int getCoarseTuning() { + synchronized (control_mutex) { + return (int)(co_master_coarse_tuning[0] * 16384.0); + } + } + + public void globalParameterControlChange(int[] slothpath, long[] params, + long[] paramsvalue) { + if (slothpath.length == 0) + return; + + synchronized (control_mutex) { + + // slothpath: 01xx are reserved only for GM2 + + if (slothpath[0] == 0x01 * 128 + 0x01) { + for (int i = 0; i < paramsvalue.length; i++) { + reverb.globalParameterControlChange(slothpath, params[i], + paramsvalue[i]); + } + } + if (slothpath[0] == 0x01 * 128 + 0x02) { + for (int i = 0; i < paramsvalue.length; i++) { + chorus.globalParameterControlChange(slothpath, params[i], + paramsvalue[i]); + } + + } + + } + } + + public void processMessage(Object object) { + if(object instanceof byte[]) + processMessage((byte[])object); + if(object instanceof MidiMessage) + processMessage((MidiMessage)object); + } + + public void processMessage(MidiMessage message) { + if(message instanceof ShortMessage) + { + ShortMessage sms = (ShortMessage)message; + processMessage( + sms.getChannel(), sms.getCommand(), + sms.getData1(), sms.getData2()); + return; + } + processMessage(message.getMessage()); + } + + public void processMessage(byte[] data) { + int status = 0; + if (data.length > 0) + status = data[0] & 0xFF; + + if (status == 0xF0) { + processSystemExclusiveMessage(data); + return; + } + + int cmd = (status & 0xF0); + int ch = (status & 0x0F); + + int data1; + int data2; + if (data.length > 1) + data1 = data[1] & 0xFF; + else + data1 = 0; + if (data.length > 2) + data2 = data[2] & 0xFF; + else + data2 = 0; + + processMessage(ch, cmd, data1, data2); + + } + + public void processMessage(int ch, int cmd, int data1, int data2) { + synchronized (synth.control_mutex) { + msec_last_activity = msec_pos; + } + + if(cmd == 0xF0) + { + int status = cmd | ch; + switch (status) { + case ShortMessage.ACTIVE_SENSING: + synchronized (synth.control_mutex) { + active_sensing_on = true; + } + break; + default: + break; + } + return; + } + + SoftChannel[] channels = synth.channels; + if(ch >= channels.length) return; + SoftChannel softchannel = channels[ch]; + + switch (cmd) { + case ShortMessage.NOTE_ON: + softchannel.noteOn(data1, data2); + break; + case ShortMessage.NOTE_OFF: + softchannel.noteOff(data1, data2); + break; + case ShortMessage.POLY_PRESSURE: + softchannel.setPolyPressure(data1, data2); + break; + case ShortMessage.CONTROL_CHANGE: + softchannel.controlChange(data1, data2); + break; + case ShortMessage.PROGRAM_CHANGE: + softchannel.programChange(data1); + break; + case ShortMessage.CHANNEL_PRESSURE: + softchannel.setChannelPressure(data1); + break; + case ShortMessage.PITCH_BEND: + softchannel.setPitchBend(data1 + data2 * 128); + break; + default: + break; + } + + } + + public long getMicrosecondPosition() { + return msec_pos; + } + + public void close() + { + } + + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,218 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequence; +import javax.sound.midi.Track; +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.AudioFileFormat.Type; +import javax.sound.sampled.spi.AudioFileReader; + +/** + * MIDI File Audio Renderer/Reader + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class SoftMidiAudioFileReader extends AudioFileReader { + + public static final Type MIDI = new Type("MIDI", "mid"); + private static AudioFormat format = new AudioFormat(44100, 16, 2, true, false); + + public AudioFileFormat getAudioFileFormat(Sequence seq) + throws UnsupportedAudioFileException, IOException { + + long totallen = seq.getMicrosecondLength() / 1000000; + long len = (long) (format.getFrameRate() * (totallen + 4)); + return new AudioFileFormat(MIDI, format, (int)len); + } + + public AudioInputStream getAudioInputStream(Sequence seq) + throws UnsupportedAudioFileException, IOException { + AudioSynthesizer synth = (AudioSynthesizer) new SoftSynthesizer(); + AudioInputStream stream; + Receiver recv; + try { + stream = synth.openStream(format, null); + recv = synth.getReceiver(); + } catch (MidiUnavailableException e) { + throw new IOException(e.toString()); + } + float divtype = seq.getDivisionType(); + Track[] tracks = seq.getTracks(); + int[] trackspos = new int[tracks.length]; + int mpq = 500000; + int seqres = seq.getResolution(); + long lasttick = 0; + long curtime = 0; + while (true) { + MidiEvent selevent = null; + int seltrack = -1; + for (int i = 0; i < tracks.length; i++) { + int trackpos = trackspos[i]; + Track track = tracks[i]; + if (trackpos < track.size()) { + MidiEvent event = track.get(trackpos); + if (selevent == null + || event.getTick() < selevent.getTick()) { + selevent = event; + seltrack = i; + } + } + } + if (seltrack == -1) + break; + trackspos[seltrack]++; + long tick = selevent.getTick(); + if(divtype == Sequence.PPQ) + curtime += ((tick - lasttick) * mpq) / seqres; + else + curtime = (long)((tick * 1000000.0 * divtype) / seqres); + lasttick = tick; + MidiMessage msg = selevent.getMessage(); + if (msg instanceof MetaMessage) { + if(divtype == Sequence.PPQ) + if (((MetaMessage) msg).getType() == 0x51) { + byte[] data = ((MetaMessage) msg).getData(); + mpq = ((data[0] & 0xff) << 16) + | ((data[1] & 0xff) << 8) | (data[2] & 0xff); + } + } else { + recv.send(msg, curtime); + } + } + + long totallen = curtime / 1000000; + long len = (long) (stream.getFormat().getFrameRate() * (totallen + 4)); + stream = new AudioInputStream(stream, stream.getFormat(), len); + return stream; + } + + + public AudioInputStream getAudioInputStream(InputStream inputstream) + throws UnsupportedAudioFileException, IOException { + + inputstream.mark(200); + Sequence seq; + try { + seq = MidiSystem.getSequence(inputstream); + } catch (InvalidMidiDataException e) { + inputstream.reset(); + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + inputstream.reset(); + throw new UnsupportedAudioFileException(); + } + return getAudioInputStream(seq); + } + + public AudioFileFormat getAudioFileFormat(URL url) + throws UnsupportedAudioFileException, IOException { + Sequence seq; + try { + seq = MidiSystem.getSequence(url); + } catch (InvalidMidiDataException e) { + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + throw new UnsupportedAudioFileException(); + } + return getAudioFileFormat(seq); + } + + public AudioFileFormat getAudioFileFormat(File file) + throws UnsupportedAudioFileException, IOException { + Sequence seq; + try { + seq = MidiSystem.getSequence(file); + } catch (InvalidMidiDataException e) { + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + throw new UnsupportedAudioFileException(); + } + return getAudioFileFormat(seq); + } + + public AudioInputStream getAudioInputStream(URL url) + throws UnsupportedAudioFileException, IOException { + Sequence seq; + try { + seq = MidiSystem.getSequence(url); + } catch (InvalidMidiDataException e) { + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + throw new UnsupportedAudioFileException(); + } + return getAudioInputStream(seq); + } + + public AudioInputStream getAudioInputStream(File file) + throws UnsupportedAudioFileException, IOException { + if (!file.getName().toLowerCase().endsWith(".mid")) + throw new UnsupportedAudioFileException(); + Sequence seq; + try { + seq = MidiSystem.getSequence(file); + } catch (InvalidMidiDataException e) { + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + throw new UnsupportedAudioFileException(); + } + return getAudioInputStream(seq); } + + public AudioFileFormat getAudioFileFormat(InputStream inputstream) + throws UnsupportedAudioFileException, IOException { + + inputstream.mark(200); + Sequence seq; + try { + seq = MidiSystem.getSequence(inputstream); + } catch (InvalidMidiDataException e) { + inputstream.reset(); + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + inputstream.reset(); + throw new UnsupportedAudioFileException(); + } + return getAudioFileFormat(seq); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftPerformer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftPerformer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,763 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class decodes information from ModelPeformer for use in SoftVoice. It + * also adds default connections if they where missing in ModelPerformer. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftPerformer { + + static ModelConnectionBlock[] defaultconnections = new ModelConnectionBlock[42]; + static { + + int o = 0; + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("noteon", "on", 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 1, + new ModelDestination(new ModelIdentifier("eg", "on", 0))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("noteon", "on", 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 1, + new ModelDestination(new ModelIdentifier("eg", "on", 1))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("eg", "active", 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 1, + new ModelDestination(new ModelIdentifier("mixer", "active", 0))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("eg", 0), + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), -960, + new ModelDestination(new ModelIdentifier("mixer", "gain"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("noteon", "velocity"), + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_CONCAVE), -960, + new ModelDestination(new ModelIdentifier("mixer", "gain"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi", "pitch"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), new ModelSource( + new ModelIdentifier("midi_rpn", "0"), new ModelTransform() { + public double transform(double value) { + int v = (int) (value * 16384.0); + int msb = v >> 7; + int lsb = v & 127; + return msb * 100 + lsb; + } + }), new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("noteon", "keynumber"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 12800, + new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "7"), + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_CONCAVE), -960, + new ModelDestination(new ModelIdentifier("mixer", "gain"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "8"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 1000, + new ModelDestination(new ModelIdentifier("mixer", "balance"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "10"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 1000, + new ModelDestination(new ModelIdentifier("mixer", "pan"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "11"), + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_CONCAVE), -960, + new ModelDestination(new ModelIdentifier("mixer", "gain"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "91"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 1000, + new ModelDestination(new ModelIdentifier("mixer", "reverb"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "93"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 1000, + new ModelDestination(new ModelIdentifier("mixer", "chorus"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "71"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 200, + new ModelDestination(new ModelIdentifier("filter", "q"))); + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "74"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 9600, + new ModelDestination(new ModelIdentifier("filter", "freq"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "72"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 6000, + new ModelDestination(new ModelIdentifier("eg", "release2"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "73"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 2000, + new ModelDestination(new ModelIdentifier("eg", "attack2"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "75"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 6000, + new ModelDestination(new ModelIdentifier("eg", "decay2"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "67"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_SWITCH), -50, + new ModelDestination(ModelDestination.DESTINATION_GAIN)); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "67"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_SWITCH), -2400, + new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ)); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_rpn", "1"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 100, + new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_rpn", "2"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 12800, + new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("master", "fine_tuning"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 100, + new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("master", "coarse_tuning"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 12800, + new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock(13500, + new ModelDestination(new ModelIdentifier("filter", "freq", 0))); + + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "delay", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "attack", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "hold", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "decay", 0))); + defaultconnections[o++] = new ModelConnectionBlock(1000, + new ModelDestination(new ModelIdentifier("eg", "sustain", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "release", 0))); + defaultconnections[o++] = new ModelConnectionBlock(1200.0 + * Math.log(0.015) / Math.log(2), new ModelDestination( + new ModelIdentifier("eg", "shutdown", 0))); // 15 msec default + + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "delay", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "attack", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "hold", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "decay", 1))); + defaultconnections[o++] = new ModelConnectionBlock(1000, + new ModelDestination(new ModelIdentifier("eg", "sustain", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "release", 1))); + + defaultconnections[o++] = new ModelConnectionBlock(-8.51318, + new ModelDestination(new ModelIdentifier("lfo", "freq", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("lfo", "delay", 0))); + defaultconnections[o++] = new ModelConnectionBlock(-8.51318, + new ModelDestination(new ModelIdentifier("lfo", "freq", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("lfo", "delay", 1))); + + } + + public int keyFrom = 0; + + public int keyTo = 127; + + public int velFrom = 0; + + public int velTo = 127; + + public int exclusiveClass = 0; + + public boolean selfNonExclusive = false; + + public boolean forcedVelocity = false; + + public boolean forcedKeynumber = false; + + public ModelPerformer performer; + + public ModelConnectionBlock[] connections; + + public ModelOscillator[] oscillators; + + public Map midi_rpn_connections = new HashMap(); + + public Map midi_nrpn_connections = new HashMap(); + + public int[][] midi_ctrl_connections; + + public int[][] midi_connections; + + public int[] ctrl_connections; + + private List ctrl_connections_list = new ArrayList(); + + private static class KeySortComparator implements Comparator { + public int compare(ModelSource o1, ModelSource o2) { + return o1.getIdentifier().toString().compareTo( + o2.getIdentifier().toString()); + } + } + + private static KeySortComparator keySortComparator = new KeySortComparator(); + + private String extractKeys(ModelConnectionBlock conn) { + StringBuffer sb = new StringBuffer(); + if (conn.getSources() != null) { + sb.append("["); + ModelSource[] srcs = conn.getSources(); + ModelSource[] srcs2 = new ModelSource[srcs.length]; + for (int i = 0; i < srcs.length; i++) + srcs2[i] = srcs[i]; + Arrays.sort(srcs2, keySortComparator); + for (int i = 0; i < srcs.length; i++) { + sb.append(srcs[i].getIdentifier()); + sb.append(";"); + } + sb.append("]"); + } + sb.append(";"); + if (conn.getDestination() != null) { + sb.append(conn.getDestination().getIdentifier()); + } + sb.append(";"); + return sb.toString(); + } + + private void processSource(ModelSource src, int ix) { + ModelIdentifier id = src.getIdentifier(); + String o = id.getObject(); + if (o.equals("midi_cc")) + processMidiControlSource(src, ix); + else if (o.equals("midi_rpn")) + processMidiRpnSource(src, ix); + else if (o.equals("midi_nrpn")) + processMidiNrpnSource(src, ix); + else if (o.equals("midi")) + processMidiSource(src, ix); + else if (o.equals("noteon")) + processNoteOnSource(src, ix); + else if (o.equals("osc")) + return; + else if (o.equals("mixer")) + return; + else + ctrl_connections_list.add(ix); + } + + private void processMidiControlSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + if (v == null) + return; + int c = Integer.parseInt(v); + if (midi_ctrl_connections[c] == null) + midi_ctrl_connections[c] = new int[] { ix }; + else { + int[] olda = midi_ctrl_connections[c]; + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_ctrl_connections[c] = newa; + } + } + + private void processNoteOnSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + int c = -1; + if (v.equals("on")) + c = 3; + if (v.equals("keynumber")) + c = 4; + if (c == -1) + return; + if (midi_connections[c] == null) + midi_connections[c] = new int[] { ix }; + else { + int[] olda = midi_connections[c]; + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_connections[c] = newa; + } + } + + private void processMidiSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + int c = -1; + if (v.equals("pitch")) + c = 0; + if (v.equals("channel_pressure")) + c = 1; + if (v.equals("poly_pressure")) + c = 2; + if (c == -1) + return; + if (midi_connections[c] == null) + midi_connections[c] = new int[] { ix }; + else { + int[] olda = midi_connections[c]; + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_connections[c] = newa; + } + } + + private void processMidiRpnSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + if (v == null) + return; + int c = Integer.parseInt(v); + if (midi_rpn_connections.get(c) == null) + midi_rpn_connections.put(c, new int[] { ix }); + else { + int[] olda = midi_rpn_connections.get(c); + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_rpn_connections.put(c, newa); + } + } + + private void processMidiNrpnSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + if (v == null) + return; + int c = Integer.parseInt(v); + if (midi_nrpn_connections.get(c) == null) + midi_nrpn_connections.put(c, new int[] { ix }); + else { + int[] olda = midi_nrpn_connections.get(c); + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_nrpn_connections.put(c, newa); + } + } + + public SoftPerformer(ModelPerformer performer) { + this.performer = performer; + + keyFrom = performer.getKeyFrom(); + keyTo = performer.getKeyTo(); + velFrom = performer.getVelFrom(); + velTo = performer.getVelTo(); + exclusiveClass = performer.getExclusiveClass(); + selfNonExclusive = performer.isSelfNonExclusive(); + + Map connmap = new HashMap(); + + List performer_connections = new ArrayList(); + performer_connections.addAll(performer.getConnectionBlocks()); + + if (performer.isDefaultConnectionsEnabled()) { + + // Add modulation depth range (RPN 5) to the modulation wheel (cc#1) + + boolean isModulationWheelConectionFound = false; + for (int j = 0; j < performer_connections.size(); j++) { + ModelConnectionBlock connection = performer_connections.get(j); + ModelSource[] sources = connection.getSources(); + ModelDestination dest = connection.getDestination(); + boolean isModulationWheelConection = false; + if (dest != null && sources != null && sources.length > 1) + for (int i = 0; i < sources.length; i++) { + // check if connection block has the source "modulation + // wheel cc#1" + if (sources[i].getIdentifier().getObject().equals( + "midi_cc")) + if (sources[i].getIdentifier().getVariable() + .equals("1")) { + isModulationWheelConection = true; + isModulationWheelConectionFound = true; + break; + } + } + if (isModulationWheelConection) { + + ModelConnectionBlock newconnection = new ModelConnectionBlock(); + newconnection.setSources(connection.getSources()); + newconnection.setDestination(connection.getDestination()); + newconnection.addSource(new ModelSource( + new ModelIdentifier("midi_rpn", "5"))); + newconnection.setScale(connection.getScale() * 256.0); + performer_connections.set(j, newconnection); + } + } + + if (!isModulationWheelConectionFound) { + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(new ModelIdentifier("midi_cc", "1", 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 50, + new ModelDestination(ModelDestination.DESTINATION_PITCH)); + conn.addSource(new ModelSource(new ModelIdentifier("midi_rpn", + "5"))); + conn.setScale(conn.getScale() * 256.0); + performer_connections.add(conn); + + } + + // Let Aftertouch to behave just like modulation wheel (cc#1) + boolean channel_pressure_set = false; + boolean poly_pressure = false; + ModelConnectionBlock mod_cc_1_connection = null; + int mod_cc_1_connection_src_ix = 0; + + for (ModelConnectionBlock connection : performer_connections) { + ModelSource[] sources = connection.getSources(); + ModelDestination dest = connection.getDestination(); + // if(dest != null && sources != null) + if (dest != null && sources != null) + for (int i = 0; i < sources.length; i++) { + ModelIdentifier srcid = sources[i].getIdentifier(); + // check if connection block has the source "modulation + // wheel cc#1" + if (srcid.getObject().equals("midi_cc")) + if (srcid.getVariable().equals("1")) { + mod_cc_1_connection = connection; + mod_cc_1_connection_src_ix = i; + } + // check if channel or poly pressure are already + // connected + if (srcid.getObject().equals("midi")) { + if (srcid.getVariable().equals("channel_pressure")) + channel_pressure_set = true; + if (srcid.getVariable().equals("poly_pressure")) + poly_pressure = true; + } + } + + } + + if (mod_cc_1_connection != null) { + if (!channel_pressure_set) { + ModelConnectionBlock mc = new ModelConnectionBlock(); + mc.setDestination(mod_cc_1_connection.getDestination()); + mc.setScale(mod_cc_1_connection.getScale()); + ModelSource[] src_list = mod_cc_1_connection.getSources(); + ModelSource[] src_list_new = new ModelSource[src_list.length]; + for (int i = 0; i < src_list_new.length; i++) + src_list_new[i] = src_list[i]; + src_list_new[mod_cc_1_connection_src_ix] = new ModelSource( + new ModelIdentifier("midi", "channel_pressure")); + mc.setSources(src_list_new); + connmap.put(extractKeys(mc), mc); + } + if (!poly_pressure) { + ModelConnectionBlock mc = new ModelConnectionBlock(); + mc.setDestination(mod_cc_1_connection.getDestination()); + mc.setScale(mod_cc_1_connection.getScale()); + ModelSource[] src_list = mod_cc_1_connection.getSources(); + ModelSource[] src_list_new = new ModelSource[src_list.length]; + for (int i = 0; i < src_list_new.length; i++) + src_list_new[i] = src_list[i]; + src_list_new[mod_cc_1_connection_src_ix] = new ModelSource( + new ModelIdentifier("midi", "poly_pressure")); + mc.setSources(src_list_new); + connmap.put(extractKeys(mc), mc); + } + } + + // Enable Vibration Sound Controllers : 76, 77, 78 + ModelConnectionBlock found_vib_connection = null; + for (ModelConnectionBlock connection : performer_connections) { + ModelSource[] sources = connection.getSources(); + if (sources.length != 0 + && sources[0].getIdentifier().getObject().equals("lfo")) + if (connection.getDestination().getIdentifier().equals( + ModelDestination.DESTINATION_PITCH)) { + if (found_vib_connection == null) + found_vib_connection = connection; + else { + if (found_vib_connection.getSources().length > sources.length) + found_vib_connection = connection; + else if (found_vib_connection.getSources()[0] + .getIdentifier().getInstance() < 1) + if (found_vib_connection.getSources()[0] + .getIdentifier().getInstance() > sources[0] + .getIdentifier().getInstance()) + found_vib_connection = connection; + } + + } + } + + int instance = 1; + + if (found_vib_connection != null) + instance = found_vib_connection.getSources()[0].getIdentifier() + .getInstance(); + ModelConnectionBlock connection; + + connection = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "78"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 2000, + new ModelDestination(new ModelIdentifier("lfo", "delay2", + instance))); + connmap.put(extractKeys(connection), connection); + + final double scale = found_vib_connection == null ? 0 + : found_vib_connection.getScale(); + connection = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("lfo", instance)), new ModelSource( + new ModelIdentifier("midi_cc", "77"), new ModelTransform() { + double s = scale; + + public double transform(double value) { + value = value * 2 - 1; + value *= 600; + if (s == 0) { + return value; + } else if (s > 0) { + if (value < -s) + value = -s; + return value; + } else { + if (value < s) + value = -s; + return -value; + } + } + }), + new ModelDestination(ModelDestination.DESTINATION_PITCH)); + connmap.put(extractKeys(connection), connection); + + connection = new ModelConnectionBlock(new ModelSource( + new ModelIdentifier("midi_cc", "76"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), 2400, + new ModelDestination(new ModelIdentifier("lfo", "freq", + instance))); + connmap.put(extractKeys(connection), connection); + + } + + // Add default connection blocks + if (performer.isDefaultConnectionsEnabled()) + for (ModelConnectionBlock connection : defaultconnections) + connmap.put(extractKeys(connection), connection); + // Add connection blocks from modelperformer + for (ModelConnectionBlock connection : performer_connections) + connmap.put(extractKeys(connection), connection); + // seperate connection blocks : Init time, Midi Time, Midi/Control Time, + // Control Time + List connections = new ArrayList(); + + midi_ctrl_connections = new int[128][]; + for (int i = 0; i < midi_ctrl_connections.length; i++) { + midi_ctrl_connections[i] = null; + } + midi_connections = new int[5][]; + for (int i = 0; i < midi_connections.length; i++) { + midi_connections[i] = null; + } + + int ix = 0; + boolean mustBeOnTop = false; + + for (ModelConnectionBlock connection : connmap.values()) { + if (connection.getDestination() != null) { + ModelDestination dest = connection.getDestination(); + ModelIdentifier id = dest.getIdentifier(); + if (id.getObject().equals("noteon")) { + mustBeOnTop = true; + if (id.getVariable().equals("keynumber")) + forcedKeynumber = true; + if (id.getVariable().equals("velocity")) + forcedVelocity = true; + } + } + if (mustBeOnTop) { + connections.add(0, connection); + mustBeOnTop = false; + } else + connections.add(connection); + } + + for (ModelConnectionBlock connection : connections) { + if (connection.getSources() != null) { + ModelSource[] srcs = connection.getSources(); + for (int i = 0; i < srcs.length; i++) { + processSource(srcs[i], ix); + } + } + ix++; + } + + this.connections = new ModelConnectionBlock[connections.size()]; + connections.toArray(this.connections); + + this.ctrl_connections = new int[ctrl_connections_list.size()]; + + for (int i = 0; i < this.ctrl_connections.length; i++) + this.ctrl_connections[i] = ctrl_connections_list.get(i); + + oscillators = new ModelOscillator[performer.getOscillators().size()]; + performer.getOscillators().toArray(oscillators); + + for(ModelConnectionBlock conn : connections) + { + if(conn.getDestination() != null) + { + if(isUnnecessaryTransform(conn.getDestination().getTransform())) + { + conn.getDestination().setTransform(null); + } + } + if(conn.getSources() != null) + { + for(ModelSource src : conn.getSources()) + { + if(isUnnecessaryTransform(src.getTransform())) + { + src.setTransform(null); + } + } + } + } + + } + + private static boolean isUnnecessaryTransform(ModelTransform transform) + { + if(transform == null) return false; + if(!(transform instanceof ModelStandardTransform)) return false; + ModelStandardTransform stransform = (ModelStandardTransform)transform; + if(stransform.getDirection() != ModelStandardTransform.DIRECTION_MIN2MAX) return false; + if(stransform.getPolarity() != ModelStandardTransform.POLARITY_UNIPOLAR) return false; + if(stransform.getTransform() != ModelStandardTransform.TRANSFORM_LINEAR) return false; + return false; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftPointResampler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftPointResampler.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * A resampler that uses 0-order (nearest-neighbor) interpolation. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftPointResampler extends SoftAbstractResampler { + + public int getPadding() { + return 100; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + float ox_end = out_end; + if (pitchstep == 0) { + while (ix < ix_end && ox < ox_end) { + out[ox++] = in[(int) ix]; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + out[ox++] = in[(int) ix]; + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftProcess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftProcess.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * Control signal processor interface + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface SoftProcess extends SoftControl { + public void init(SoftSynthesizer synth); + + public double[] get(int instance, String name); + + public void processControlLogic(); + + public void reset(); +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftProvider.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiDevice.Info; +import javax.sound.midi.spi.MidiDeviceProvider; + +/** + * + * Software synthesizer provider class. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftProvider extends MidiDeviceProvider { + + protected static Info softinfo = SoftSynthesizer.info; + + private static Info[] softinfos = { softinfo }; + + public MidiDevice.Info[] getDeviceInfo() { + return softinfos; + } + + public MidiDevice getDevice(MidiDevice.Info info) { + if (info == softinfo) { + return new SoftSynthesizer(); + } + return null; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReceiver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReceiver.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.TreeMap; + +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Receiver; +import javax.sound.midi.ShortMessage; + +/** + * + * Software synthesizer MIDI receiver class. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftReceiver implements Receiver { + + protected boolean open = true; + + private Object control_mutex; + + private SoftSynthesizer synth; + + protected TreeMap midimessages ; + + protected SoftMainMixer mainmixer; + + public SoftReceiver(SoftSynthesizer synth) { + this.control_mutex = synth.control_mutex; + this.synth = synth; + this.mainmixer = synth.getMainMixer(); + if(mainmixer != null) + this.midimessages = mainmixer.midimessages; + } + + public void send(MidiMessage message, long timeStamp) { + + synchronized (control_mutex) { + if(!open) + throw new IllegalStateException("Receiver is not open"); + } + + if (timeStamp != -1) { + synchronized (control_mutex) { + + while (midimessages.get(timeStamp) != null) + timeStamp++; + if(message instanceof ShortMessage + && (((ShortMessage)message).getChannel() > 0xF)) + midimessages.put(timeStamp, message.clone()); + else + midimessages.put(timeStamp, message.getMessage()); + + } + } + else + { + mainmixer.processMessage(message); + } + } + + public void close() { + synchronized (control_mutex) { + open = false; + } + synth.removeReceiver(this); + } +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftResampler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftResampler.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * + * Basic resampler interface. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface SoftResampler { + + public SoftResamplerStreamer openStreamer(); + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftResamplerStreamer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftResamplerStreamer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; + +/** + * + * Resampler stream interface. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public interface SoftResamplerStreamer extends ModelOscillatorStream { + public void open(ModelWavetable osc, float outputsamplerate) + throws IOException; + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,500 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.util.Arrays; + +/** + * + * Reverb effect based on allpass/comb filters. First audio is send to 8 + * parelled comb filters and then mixed together and then finally send thru 3 + * different allpass filters. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class SoftReverb implements SoftAudioProcessor { + + private class Delay { + private float[] delaybuffer; + + private int rovepos = 0; + + public Delay() { + delaybuffer = null; + } + + public void setDelay(int delay) { + if (delay == 0) + delaybuffer = null; + else + delaybuffer = new float[delay]; + rovepos = 0; + } + + public void processReplace(float[] in, float[] out) { + float[] delaybuffer = this.delaybuffer; + if (delaybuffer == null) + return; + int len = in.length; + int rnlen = delaybuffer.length; + int rovepos = this.rovepos; + + for (int i = 0; i < len; i++) { + float x = in[i]; + out[i] = delaybuffer[rovepos]; + delaybuffer[rovepos] = x; + rovepos = rovepos + 1; + if(rovepos == rnlen) rovepos = 0; + //rovepos = (rovepos + 1) % rnlen; + } + this.rovepos = rovepos; + } + + } + + private class AllPass { + + private float[] delaybuffer; + + private int delaybuffersize; + + private int rovepos = 0; + + private float feedback; + + public AllPass(int size) { + delaybuffer = new float[size]; + delaybuffersize = size; + } + + public void setFeedBack(float feedback) { + this.feedback = feedback; + } + + int ucount = 0; + + public void processReplace(float in[], float out[]) { + int len = in.length; + for (int i = 0; i < len; i++) { + + float delayout = delaybuffer[rovepos]; + + // undenormalise(delayout) + /* + if (((delayout > 0.0) && (delayout < 1.0E-10)) + || ((delayout < 0.0) && (delayout > -1.0E-10))) + delayout = 0;*/ + + float input = in[i]; + out[i] = -input + delayout; + delaybuffer[rovepos] = input + delayout * feedback; + if (++rovepos == delaybuffersize) + rovepos = 0; + } + + ucount++; + if(ucount == 10) + { + ucount = 0; + for (int i = 0; i < delaybuffer.length; i++) { + double v = delaybuffer[i]; + if (((v > 0.0) && (v < 1.0E-10)) + || ((v < 0.0) && (v > -1.0E-10))) + delaybuffer[i] = 0; + } + } + + } + + } + + private class Comb { + + private float[] delaybuffer; + + private int delaybuffersize; + + private int rovepos = 0; + + private float feedback; + + private float filtertemp = 0; + + private float filtercoeff1 = 0; + + private float filtercoeff2 = 1; + + public Comb(int size) { + delaybuffer = new float[size]; + delaybuffersize = size; + } + + public void setFeedBack(float feedback) { + this.feedback = feedback; + } + + int ucount = 0; + public void processMix(float in[], float out[]) { + int len = in.length; + + float filtercoeff2 = this.filtercoeff2*feedback; + + for (int i = 0; i < len; i++) { + float delayout = delaybuffer[rovepos]; + + // One Pole Lowpass Filter + filtertemp = (delayout * filtercoeff2) + + (filtertemp * filtercoeff1); + + // undenormalise(filtertemp) + /* + if (((filtertemp > 0.0) && (filtertemp < 1.0E-10)) + || ((filtertemp < 0.0) && (filtertemp > -1.0E-10))) + filtertemp = 0; + */ + out[i] += delayout; + delaybuffer[rovepos] = in[i] + (filtertemp);// * feedback); + + if (++rovepos == delaybuffersize) + rovepos = 0; + + } + ucount++; + if(ucount == 10) + { + ucount = 0; + if (((filtertemp > 0.0) && (filtertemp < 1.0E-10)) + || ((filtertemp < 0.0) && (filtertemp > -1.0E-10))) + filtertemp = 0; + for (int i = 0; i < delaybuffer.length; i++) { + double v = delaybuffer[i]; + if (((v > 0.0) && (v < 1.0E-10)) + || ((v < 0.0) && (v > -1.0E-10))) + delaybuffer[i] = 0; + } + } + + + } + + public void setDamp(float val) { + filtercoeff1 = val; + filtercoeff2 = 1 - filtercoeff1; + } + } + + private float roomsize; + + private float damp; + + private float gain = 1; + + private Delay delay; + + private Comb[] combL; + + private Comb[] combR; + + private AllPass[] allpassL; + + private AllPass[] allpassR; + + private float[] input; + + private float[] outR; + + private float[] outL; + + private boolean mix = true; + + private SoftAudioBuffer inputA; + + private SoftAudioBuffer left; + + private SoftAudioBuffer right; + + private SoftSynthesizer synth; + + private boolean dirty = true; + + private float dirty_roomsize; + + private float dirty_damp; + + private float dirty_predelay; + + private float dirty_gain; + + public void init(SoftSynthesizer synth) { + this.synth = synth; + double samplerate = synth.getFormat().getSampleRate(); + + double freqscale = ((double) samplerate) / 44100.0; + // freqscale = 1.0/ freqscale; + + int stereospread = 23; + + delay = new Delay(); + + combL = new Comb[8]; + combR = new Comb[8]; + combL[0] = new Comb((int) (freqscale * (1116))); + combR[0] = new Comb((int) (freqscale * (1116 + stereospread))); + combL[1] = new Comb((int) (freqscale * (1188))); + combR[1] = new Comb((int) (freqscale * (1188 + stereospread))); + combL[2] = new Comb((int) (freqscale * (1277))); + combR[2] = new Comb((int) (freqscale * (1277 + stereospread))); + combL[3] = new Comb((int) (freqscale * (1356))); + combR[3] = new Comb((int) (freqscale * (1356 + stereospread))); + combL[4] = new Comb((int) (freqscale * (1422))); + combR[4] = new Comb((int) (freqscale * (1422 + stereospread))); + combL[5] = new Comb((int) (freqscale * (1491))); + combR[5] = new Comb((int) (freqscale * (1491 + stereospread))); + combL[6] = new Comb((int) (freqscale * (1557))); + combR[6] = new Comb((int) (freqscale * (1557 + stereospread))); + combL[7] = new Comb((int) (freqscale * (1617))); + combR[7] = new Comb((int) (freqscale * (1617 + stereospread))); + + allpassL = new AllPass[4]; + allpassR = new AllPass[4]; + allpassL[0] = new AllPass((int) (freqscale * (556))); + allpassR[0] = new AllPass((int) (freqscale * (556 + stereospread))); + allpassL[1] = new AllPass((int) (freqscale * (441))); + allpassR[1] = new AllPass((int) (freqscale * (441 + stereospread))); + allpassL[2] = new AllPass((int) (freqscale * (341))); + allpassR[2] = new AllPass((int) (freqscale * (341 + stereospread))); + allpassL[3] = new AllPass((int) (freqscale * (225))); + allpassR[3] = new AllPass((int) (freqscale * (225 + stereospread))); + + for (int i = 0; i < allpassL.length; i++) { + allpassL[i].setFeedBack(0.5f); + allpassR[i].setFeedBack(0.5f); + } + + /* Init other settings */ + globalParameterControlChange(new int[] { 0x01 * 128 + 0x01 }, 0, 4); + + } + + public void setInput(int pin, SoftAudioBuffer input) { + if (pin == 0) + inputA = input; + } + + public void setOutput(int pin, SoftAudioBuffer output) { + if (pin == 0) + left = output; + if (pin == 1) + right = output; + } + + public void setMixMode(boolean mix) { + this.mix = mix; + } + + private double silentcounter = 1000; + + public void processAudio() { + if (this.inputA.isSilent()) { + silentcounter += 1 / synth.getControlRate(); + + if (silentcounter > 60) { + if (!mix) { + left.clear(); + right.clear(); + } + return; + } + } else + silentcounter = 0; + + float[] inputA = this.inputA.array(); + float[] left = this.left.array(); + float[] right = this.right == null ? null : this.right.array(); + + int numsamples = inputA.length; + if (input == null || input.length < numsamples) + input = new float[numsamples]; + + float again = gain * 0.018f / 2; + + for (int i = 0; i < numsamples; i++) + input[i] = inputA[i] * again; + + delay.processReplace(input, input); + + + + if (right != null) + { + if (outR == null || outR.length < numsamples) + outR = new float[numsamples]; + Arrays.fill(outR, 0); + for (int i = 0; i < combR.length; i++) + combR[i].processMix(input, outR); + for (int i = 0; i < allpassL.length; i++) + allpassR[i].processReplace(outR, outR); + + if (mix) + for (int i = 0; i < numsamples; i++) + right[i] += outR[i]; + else + for (int i = 0; i < numsamples; i++) + right[i] = outR[i]; + } + + + if (outL == null || outL.length < numsamples) + outL = new float[numsamples]; + Arrays.fill(outL, 0); + for (int i = 0; i < combL.length; i++) + combL[i].processMix(input, outL); + for (int i = 0; i < allpassL.length; i++) + allpassL[i].processReplace(outL, outL); + + if (mix) + for (int i = 0; i < numsamples; i++) + left[i] += outL[i]; + else + for (int i = 0; i < numsamples; i++) + left[i] = outL[i]; + + + } + + public void globalParameterControlChange(int[] slothpath, long param, + long value) { + if (slothpath.length == 1) + if (slothpath[0] == 0x01 * 128 + 0x01) { + + if (param == 0) { + if (value == 0) // Small Room A small size room with a + // length of 5m or so. + { + dirty_roomsize = (1.1f); + dirty_damp = (5000); + dirty_predelay = (0); + dirty_gain = (4); + dirty = true; + } + if (value == 1) // Medium Room A medium size room with a + // length of 10m or so. + { + dirty_roomsize = (1.3f); + dirty_damp = (5000); + dirty_predelay = (0); + dirty_gain = (3); + dirty = true; + } + if (value == 2) // Large Room A large size room suitable for + // live performances. + { + dirty_roomsize = (1.5f); + dirty_damp = (5000); + dirty_predelay = (0); + dirty_gain = (2); + dirty = true; + } + if (value == 3) // Medium Hall A medium size concert hall. + { + dirty_roomsize = (1.8f); + dirty_damp = (24000); + dirty_predelay = (0.02f); + dirty_gain = (1.5f); + dirty = true; + } + if (value == 4) // Large Hall A large size concert hall + // suitable for a full orchestra. + { + dirty_roomsize = (1.8f); + dirty_damp = (24000); + dirty_predelay = (0.03f); + dirty_gain = (1.5f); + dirty = true; + } + if (value == 8) // Plate A plate reverb simulation. + { + dirty_roomsize = (1.3f); + dirty_damp = (2500); + dirty_predelay = (0); + dirty_gain = (6); + dirty = true; + } + } else if (param == 1) { + dirty_roomsize = ((float) (Math.exp((value - 40) * 0.025))); + dirty = true; + } + + } + } + + public void processControlLogic() { + if (dirty) { + dirty = false; + setRoomSize(dirty_roomsize); + setDamp(dirty_damp); + setPreDelay(dirty_predelay); + setGain(dirty_gain); + } + } + + public void setRoomSize(float value) { + roomsize = 1 - (0.17f / value); + + for (int i = 0; i < 8; i++) { + combL[i].feedback = roomsize; + combR[i].feedback = roomsize; + } + } + + public void setPreDelay(float value) { + delay.setDelay((int) (value * synth.getFormat().getSampleRate())); + } + + public void setGain(float gain) { + this.gain = gain; + } + + public void setDamp(float value) { + double x = (value / synth.getFormat().getSampleRate()) * (2 * Math.PI); + double cx = 2 - Math.cos(x); + damp = (float) (cx - Math.sqrt(cx * cx - 1)); + if (damp > 1) + damp = 1; + if (damp < 0) + damp = 0; + + // damp = value * 0.4f; + for (int i = 0; i < 8; i++) { + combL[i].setDamp(damp); + combR[i].setDamp(damp); + } + + } + +} \ No newline at end of file diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftShortMessage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftShortMessage.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.ShortMessage; + +/** + * + * A short message class that support for than 16 midi channels. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftShortMessage extends ShortMessage { + + int channel = 0; + + public int getChannel() { + return channel; + } + + public void setMessage(int command, int channel, int data1, int data2) throws InvalidMidiDataException { + this.channel = channel; + super.setMessage(command, channel & 0xF, data1, data2); + } + + public Object clone() { + SoftShortMessage clone = new SoftShortMessage(); + try { + clone.setMessage(getCommand(), getChannel(), getData1(), getData2()); + } catch (InvalidMidiDataException e) { + throw new IllegalArgumentException(e.getMessage()); + } + return clone; + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSincResampler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSincResampler.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,144 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +/** + * Hann windowed sinc interpolation resampler with anti-alias filtering. + * + * Using 30 points for the interpolation. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftSincResampler extends SoftAbstractResampler { + + double[] din; + + float[][][] sinc_table; + + int sinc_scale_size = 100; + + int sinc_table_fsize = 800; + + int sinc_table_size = 30; + + int sinc_table_center = sinc_table_size / 2; + + public SoftSincResampler() { + super(); + sinc_table = new float[sinc_scale_size][sinc_table_fsize][]; + for (int s = 0; s < sinc_scale_size; s++) { + float scale = (float) (1.0 / (1.0 + Math.pow(s, 1.1) / 10.0)); + for (int i = 0; i < sinc_table_fsize; i++) + sinc_table[s][i] = sincTable(sinc_table_size, -i + / ((float) sinc_table_fsize), scale); + } + } + + // Normalized sinc function + public static double sinc(double x) { + return (x == 0.0) ? 1.0 : Math.sin(Math.PI * x) / (Math.PI * x); + } + + // Generate hann window suitable for windowing sinc + public static float[] wHanning(int size, float offset) { + float[] window_table = new float[size]; + for (int k = 0; k < size; k++) + window_table[k] = (float) (-0.5 + * Math.cos(2.0 * Math.PI * (double) (k + offset) + / (double) size) + 0.5); + return window_table; + } + + // Generate sinc table + public static float[] sincTable(int size, float offset, float scale) { + int center = size / 2; + float[] w = wHanning(size, offset); + for (int k = 0; k < size; k++) + w[k] *= sinc((-center + k + offset) * scale) * scale; + return w; + } + + public int getPadding() // must be at least half of sinc_table_size + { + return sinc_table_size / 2 + 2; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + int max_p = sinc_scale_size - 1; + if (pitchstep == 0) { + + int p = (int) ((pitch - 1) * 10.0f); + if (p < 0) + p = 0; + else if (p > max_p) + p = max_p; + float[][] sinc_table_f = this.sinc_table[p]; + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float[] sinc_table = sinc_table_f[(int) ((ix - iix) * sinc_table_fsize)]; + int xx = iix - sinc_table_center; + float y = 0; + for (int i = 0; i < sinc_table_size; i++, xx++) + y += in[xx] * sinc_table[i]; + out[ox++] = y; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + int p = (int) ((pitch - 1) * 10.0f); + if (p < 0) + p = 0; + else if (p > max_p) + p = max_p; + float[][] sinc_table_f = this.sinc_table[p]; + + float[] sinc_table = sinc_table_f[(int) ((ix - iix) * sinc_table_fsize)]; + int xx = iix - sinc_table_center; + float y = 0; + for (int i = 0; i < sinc_table_size; i++, xx++) + y += in[xx] * sinc_table[i]; + out[ox++] = y; + + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,1006 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.File; +import java.io.IOException; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Receiver; +import javax.sound.midi.Soundbank; +import javax.sound.midi.Transmitter; +import javax.sound.midi.VoiceStatus; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; + +/** + * + * The software synthesizer class. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftSynthesizer implements AudioSynthesizer, ReferenceCountingDevice { + + private static class Info extends MidiDevice.Info { + public Info() { + super(INFO_NAME, INFO_VENDOR, INFO_DESCRIPTION, INFO_VERSION); + } + } + + protected static final String INFO_NAME = "Gervill"; + + protected static final String INFO_VENDOR = "OpenJDK Proposal"; + + protected static final String INFO_DESCRIPTION = "Software MIDI Synthesizer"; + + protected static final String INFO_VERSION = "0.9"; + + protected static MidiDevice.Info info = new Info(); + + private static Soundbank defaultSoundBank = null; + + protected Object control_mutex = this; + + protected int voiceIDCounter = 0; + + protected int voice_allocation_mode = 0; // 0 (default) + // 1 (DLS Voice Allocation) + + protected boolean reverb_on = true; + + protected boolean chorus_on = true; + + protected boolean agc_on = true; + + protected SoftChannel[] channels; + + protected SoftChannelProxy[] external_channels = null; + + private boolean largemode = false; + + private int gmmode = 0; // 0:GM Mode off (default) + // 1:GM Level 1, 2:GM Level 2 + + private int deviceid = 0; + + private AudioFormat format = new AudioFormat(44100, 16, 2, true, false); + + private SourceDataLine sourceDataLine = null; + + private SoftAudioPusher pusher = null; + + private AudioInputStream pusher_stream = null; + + private float controlrate = 147f; + + private boolean open = false; + + private boolean implicitOpen = false; + + private SoftResampler resampler = new SoftLinearResampler(); + + private int number_of_midi_channels = 16; + + private int maxpoly = 64; + + private long latency = 200000; // 200 msec + + private boolean jitter_correction = false; + + private SoftMainMixer mainmixer; + + private SoftVoice[] voices; + + private Map tunings = new HashMap(); + + private Map inslist = new HashMap(); + + private Map availlist = new HashMap(); + + private Map loadedlist = new HashMap(); + + private ArrayList recvslist = new ArrayList(); + + private void getBuffers(ModelInstrument instrument, Listbuffers) + { + for(ModelPerformer performer : instrument.getPerformers()) + { + if(performer.getOscillators() != null) + for(ModelOscillator osc : performer.getOscillators()) + if(osc instanceof ModelByteBufferWavetable) + { + ModelByteBufferWavetable w = (ModelByteBufferWavetable)osc; + ModelByteBuffer buff = w.getBuffer(); + if(buff != null) buffers.add(buff); + buff = w.get8BitExtensionBuffer(); + if(buff != null) buffers.add(buff); + } + } + } + + private boolean loadSamples(List instruments) + { + if(largemode) return true; + Listbuffers = new ArrayList(); + for(ModelInstrument instrument : instruments) + getBuffers(instrument, buffers); + try { + ModelByteBuffer.loadAll(buffers); + } catch (IOException e) { + return false; + } + return true; + } + + private boolean loadInstruments(List instruments) + { + if(!isOpen()) + return false; + if(!loadSamples(instruments)) return false; + + synchronized (control_mutex) { + if (channels != null) + for (SoftChannel c : channels) + c.current_instrument = null; + for (Instrument instrument : instruments) { + String pat = patchToString(instrument.getPatch()); + availlist.remove(pat); + SoftInstrument softins = new SoftInstrument((ModelInstrument) instrument); + inslist.put(pat, softins); + loadedlist.put(pat, (ModelInstrument) instrument); + } + } + + return true; + } + + private void processPropertyInfo(Map info) + { + AudioSynthesizerPropertyInfo[] items = getPropertyInfo(info); + + String resamplerType = (String)items[0].value; + if(resamplerType.equalsIgnoreCase("point")) this.resampler = new SoftPointResampler(); + if(resamplerType.equalsIgnoreCase("linear")) this.resampler = new SoftLinearResampler2(); + if(resamplerType.equalsIgnoreCase("linear1")) this.resampler = new SoftLinearResampler(); + if(resamplerType.equalsIgnoreCase("linear2")) this.resampler = new SoftLinearResampler2(); + if(resamplerType.equalsIgnoreCase("cubic")) this.resampler = new SoftCubicResampler(); + if(resamplerType.equalsIgnoreCase("lanczos")) this.resampler = new SoftLanczosResampler(); + if(resamplerType.equalsIgnoreCase("sinc")) this.resampler = new SoftSincResampler(); + + setFormat((AudioFormat)items[2].value); + controlrate = (Float)items[1].value; + latency = (Long)items[3].value; + deviceid = (Integer)items[4].value; + maxpoly = (Integer)items[5].value; + reverb_on = (Boolean)items[6].value; + chorus_on = (Boolean)items[7].value; + agc_on = (Boolean)items[8].value; + largemode = (Boolean)items[9].value; + number_of_midi_channels = (Integer)items[10].value; + jitter_correction = (Boolean)items[11].value; + } + + private String patchToString(Patch patch) { + if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) + return "p." + patch.getProgram() + "." + patch.getBank(); + else + return patch.getProgram() + "." + patch.getBank(); + } + + private void setFormat(AudioFormat format) { + if (format.getChannels() > 2) + throw new IllegalArgumentException( + "Only mono and stereo audio supported."); + if (AudioFloatConverter.getConverter(format) == null) + throw new IllegalArgumentException("Audio format not supported."); + this.format = format; + } + + protected void removeReceiver(Receiver recv) + { + boolean perform_close = false; + synchronized (control_mutex) { + if(recvslist.remove(recv)) + if(implicitOpen && recvslist.isEmpty()) + { + perform_close = true; + } + } + if(perform_close) + close(); + } + + protected SoftMainMixer getMainMixer() { + if (!isOpen()) + return null; + return mainmixer; + } + + protected SoftInstrument findInstrument(int program, int bank, int channel) { + + // Add support for GM2 banks 0x78 and 0x79 + // as specified in DLS 2.2 in Section 1.4.6 + // which allows using percussion and melodic instruments + // on all channels + if (bank >> 7 == 0x78 || bank >> 7 == 0x79) { + SoftInstrument current_instrument = inslist.get(program + "." + + bank); + if (current_instrument != null) + return current_instrument; + + String p_plaf; + if (bank >> 7 == 0x78) + p_plaf = "p."; + else + p_plaf = ""; + + // Instrument not found fallback to MSB:bank, LSB:0 + current_instrument = inslist.get(p_plaf + program + "." + + ((bank & 128) << 7)); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:bank + current_instrument = inslist.get(p_plaf + program + "." + + (bank & 128)); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:0 + current_instrument = inslist.get(p_plaf + program + ".0"); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:0, program=0 + current_instrument = inslist.get(p_plaf + program + "0.0"); + if (current_instrument != null) + return current_instrument; + return null; + } + + // Channel 10 uses percussion instruments + String p_plaf; + if (channel == 9) + p_plaf = "p."; + else + p_plaf = ""; + + SoftInstrument current_instrument = inslist.get(p_plaf + program + "." + + bank); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:0 + current_instrument = inslist.get(p_plaf + program + ".0"); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:0, program=0 + current_instrument = inslist.get(p_plaf + "0.0"); + if (current_instrument != null) + return current_instrument; + return null; + } + + protected int getVoiceAllocationMode() { + return voice_allocation_mode; + } + + protected int getGeneralMidiMode() { + return gmmode; + } + + protected void setGeneralMidiMode(int gmmode) { + this.gmmode = gmmode; + } + + protected int getDeviceID() { + return deviceid; + } + + protected float getControlRate() { + return controlrate; + } + + protected SoftVoice[] getVoices() { + return voices; + } + + protected SoftTuning getTuning(Patch patch) { + String t_id = patchToString(patch); + SoftTuning tuning = tunings.get(t_id); + if (tuning == null) { + tuning = new SoftTuning(patch); + tunings.put(t_id, tuning); + } + return tuning; + } + + public long getLatency() { + synchronized (control_mutex) { + return latency; + } + } + + public AudioFormat getFormat() { + synchronized (control_mutex) { + return format; + } + } + + public int getMaxPolyphony() { + synchronized (control_mutex) { + return maxpoly; + } + } + + public MidiChannel[] getChannels() { + + synchronized (control_mutex) { + + if(external_channels == null) + { + external_channels = new SoftChannelProxy[16]; + for (int i = 0; i < external_channels.length; i++) + external_channels[i] = new SoftChannelProxy(); + } + MidiChannel[] ret; + if(isOpen()) + ret = new MidiChannel[channels.length]; + else + ret = new MidiChannel[16]; + for (int i = 0; i < ret.length; i++) + ret[i] = external_channels[i]; + return ret; + } + } + + public VoiceStatus[] getVoiceStatus() { + + if(!isOpen()) + { + VoiceStatus[] tempVoiceStatusArray = new VoiceStatus[getMaxPolyphony()]; + for (int i = 0; i < tempVoiceStatusArray.length; i++) { + VoiceStatus b = new VoiceStatus(); + b.active = false; + b.bank = 0; + b.channel = 0; + b.note = 0; + b.program = 0; + b.volume = 0; + tempVoiceStatusArray[i] = b; + } + return tempVoiceStatusArray; + } + + synchronized (control_mutex) + { + VoiceStatus[] tempVoiceStatusArray = new VoiceStatus[voices.length]; + for (int i = 0; i < voices.length; i++) { + VoiceStatus a = voices[i]; + VoiceStatus b = new VoiceStatus(); + b.active = a.active; + b.bank = a.bank; + b.channel = a.channel; + b.note = a.note; + b.program = a.program; + b.volume = a.volume; + tempVoiceStatusArray[i] = b; + } + return tempVoiceStatusArray; + } + } + + public boolean isSoundbankSupported(Soundbank soundbank) { + + for (Instrument ins : soundbank.getInstruments()) + if (!(ins instanceof ModelInstrument)) + return false; + return true; + } + + public boolean loadInstrument(Instrument instrument) { + + if (instrument == null || (!(instrument instanceof ModelInstrument))) + throw new IllegalArgumentException("Unsupported instrument: " + instrument.toString()); + List instruments = new ArrayList(); + instruments.add((ModelInstrument)instrument); + return loadInstruments(instruments); + } + + public void unloadInstrument(Instrument instrument) { + + if (instrument == null || (!(instrument instanceof ModelInstrument))) + throw new IllegalArgumentException("Unsupported instrument: " + instrument.toString()); + if(!isOpen()) + return; + + String pat = patchToString(instrument.getPatch()); + synchronized (control_mutex) { + for (SoftChannel c : channels) + c.current_instrument = null; + inslist.remove(pat); + loadedlist.remove(pat); + availlist.remove(pat); + } + } + + public boolean remapInstrument(Instrument from, Instrument to) { + + if (from == null) + throw new NullPointerException(); + if (to == null) + throw new NullPointerException(); + if (!(from instanceof ModelInstrument)) + throw new IllegalArgumentException("Unsupported instrument: " + from.toString()); + if (!(to instanceof ModelInstrument)) + throw new IllegalArgumentException("Unsupported instrument: " + to.toString()); + if(!isOpen()) + return false; + + synchronized (control_mutex) { + if (!loadedlist.containsValue(to) && !availlist.containsValue(to)) + throw new IllegalArgumentException("Instrument to is not loaded."); + unloadInstrument(from); + ModelMappedInstrument mfrom = new ModelMappedInstrument( + (ModelInstrument) to, from.getPatch()); + return loadInstrument(mfrom); + } + } + + public synchronized Soundbank getDefaultSoundbank() { + if (defaultSoundBank == null) { + try { + + File javahome = new File(System.getProperties().getProperty( + "java.home")); + File libaudio = new File(new File(javahome, "lib"), "audio"); + + if (libaudio.exists()) { + File foundfile = null; + File[] files = libaudio.listFiles(); + if (files != null) { + for (int i = 0; i < files.length; i++) { + File file = files[i]; + if (file.isFile()) { + String lname = file.getName().toLowerCase(); + if (lname.endsWith(".sf2") + || lname.endsWith(".dls")) { + if (foundfile == null + || (file.length() > foundfile + .length())) + foundfile = file; + + } + } + } + } + if (foundfile != null) { + try { + Soundbank sbk = MidiSystem.getSoundbank(foundfile); + defaultSoundBank = sbk; + return defaultSoundBank; + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + if (System.getProperties().getProperty("os.name").startsWith( + "Windows")) { + File gm_dls = new File(System.getenv("SystemRoot") + + "\\system32\\drivers\\gm.dls"); + if (gm_dls.exists()) { + try { + Soundbank sbk = MidiSystem.getSoundbank(gm_dls); + defaultSoundBank = sbk; + return defaultSoundBank; + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + } catch (AccessControlException e) { + } catch (Exception e) { + e.printStackTrace(); + } + + try { + defaultSoundBank = EmergencySoundbank.createSoundbank(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + return defaultSoundBank; + } + + public Instrument[] getAvailableInstruments() { + + if(!isOpen()) + { + Soundbank defsbk = getDefaultSoundbank(); + if(defsbk == null) return new Instrument[0]; + return defsbk.getInstruments(); + } + + synchronized (control_mutex) { + ModelInstrument[] inslist_array = new ModelInstrument[availlist + .values().size()]; + availlist.values().toArray(inslist_array); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + } + + public Instrument[] getLoadedInstruments() { + + if(!isOpen()) + return new Instrument[0]; + + synchronized (control_mutex) { + ModelInstrument[] inslist_array = new ModelInstrument[loadedlist + .values().size()]; + loadedlist.values().toArray(inslist_array); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + } + + public boolean loadAllInstruments(Soundbank soundbank) { + + List instruments = new ArrayList(); + for (Instrument ins : soundbank.getInstruments()) { + if (ins == null || !(ins instanceof ModelInstrument)) + throw new IllegalArgumentException("Unsupported instrument: " + ins); + instruments.add((ModelInstrument)ins); + } + return loadInstruments(instruments); + } + + public void unloadAllInstruments(Soundbank soundbank) { + + if(!isOpen()) + return; + + for (Instrument ins : soundbank.getInstruments()) { + if (ins instanceof ModelInstrument) { + unloadInstrument(ins); + } + } + } + + public boolean loadInstruments(Soundbank soundbank, Patch[] patchList) { + + List instruments = new ArrayList(); + for (Patch patch : patchList) { + Instrument ins = soundbank.getInstrument(patch); + if (ins == null || !(ins instanceof ModelInstrument)) + throw new IllegalArgumentException("Unsupported instrument: " + ins); + instruments.add((ModelInstrument)ins); + } + return loadInstruments(instruments); + + } + + public void unloadInstruments(Soundbank soundbank, Patch[] patchList) { + + if(!isOpen()) + return; + + for (Patch pat : patchList) { + Instrument ins = soundbank.getInstrument(pat); + if (ins instanceof ModelInstrument) { + unloadInstrument(ins); + } + } + } + + public MidiDevice.Info getDeviceInfo() { + return info; + } + + + public AudioSynthesizerPropertyInfo[] getPropertyInfo(Map info) + { + List list = new ArrayList(); + + AudioSynthesizerPropertyInfo item; + + item = new AudioSynthesizerPropertyInfo("interpolation", "linear"); + item.choices = new String[] {"linear", "linear1", "linear2", "cubic", "lanczos", "sinc", "point"}; + item.description = "Interpolation method"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("control rate", 147f); + item.description = "Control rate"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("format", new AudioFormat(44100, 16, 2, true, false)); + item.description = "Default audio format"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("latency", 120000L); + item.description = "Default latency"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("device id", 0); + item.description = "Device ID for SysEx Messages"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("max polyphony", 64); + item.description = "Maximum polyphony"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("reverb", true); + item.description = "Turn reverb effect on or off"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("chorus", true); + item.description = "Turn chorus effect on or off"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("auto gain control", true); + item.description = "Turn auto gain control on or off"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("large mode", false); + item.description = "Turn large mode on or off."; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("midi channels", 16); + item.description = "Number of midi channels."; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("jitter correction", true); + item.description = "Turn jitter correction on or off."; + list.add(item); + + AudioSynthesizerPropertyInfo[] items; + items = list.toArray(new AudioSynthesizerPropertyInfo[list.size()]); + + if(info != null) + for(AudioSynthesizerPropertyInfo item2 : items) + { + Object v = info.get(item2.name); + Class c = (item2.valueClass); + if(v != null) + if(c.isInstance(v)) + item2.value = v; + } + + return items; + } + + public void open() throws MidiUnavailableException { + if(isOpen()) + { + synchronized (control_mutex) { + implicitOpen = false; + } + return; + } + open(null, null); + } + + public void open(SourceDataLine line, Map info) throws MidiUnavailableException { + if(isOpen()) + { + synchronized (control_mutex) { + implicitOpen = false; + } + return; + } + synchronized (control_mutex) { + + try + { + + if(line != null) + setFormat(line.getFormat()); + + AudioInputStream ais = openStream(getFormat(), info); + + if(line == null) + line = AudioSystem.getSourceDataLine(getFormat()); + + double latency = this.latency; + + if(!line.isOpen()) + { + int bufferSize = getFormat().getFrameSize() * (int)(getFormat().getFrameRate() * (latency / 1000000f)); + line.open(getFormat(), bufferSize); + + // Remember that we opened that line + // so we can close again in SoftSynthesizer.close() + sourceDataLine = line; + } + if(!line.isActive()) + line.start(); + + int controlbuffersize = 512; + try { + controlbuffersize = ais.available(); + } catch (IOException e) {} + + // Tell mixer not fill read buffers fully. + // This lowers latency, and tells DataPusher + // to read in smaller amounts. + //mainmixer.readfully = false; + //pusher = new DataPusher(line, ais); + + int buffersize = line.getBufferSize(); + buffersize -= buffersize % controlbuffersize; + + if(buffersize < 3*controlbuffersize) + buffersize = 3*controlbuffersize; + + if(jitter_correction) + { + ais = new SoftJitterCorrector(ais, buffersize, controlbuffersize); + } + pusher = new SoftAudioPusher(line, ais, controlbuffersize); + pusher_stream = ais; + pusher.start(); + + + } + catch(LineUnavailableException e) + { + if(isOpen()) close(); + throw new MidiUnavailableException(e.toString()); + } + + } + } + + public AudioInputStream openStream(AudioFormat targetFormat, Map info) throws MidiUnavailableException { + + if(isOpen()) + throw new MidiUnavailableException("Synthesizer is already open"); + + synchronized (control_mutex) { + + open = true; + implicitOpen = false; + + gmmode = 0; + voice_allocation_mode = 0; + + processPropertyInfo(info); + if(targetFormat != null) + setFormat(targetFormat); + + Soundbank defbank = getDefaultSoundbank(); + if (defbank != null) { + loadAllInstruments(defbank); + availlist.putAll(loadedlist); + loadedlist.clear(); + } + + voices = new SoftVoice[maxpoly]; + for (int i = 0; i < maxpoly; i++) + voices[i] = new SoftVoice(this); + + mainmixer = new SoftMainMixer(this); + + channels = new SoftChannel[number_of_midi_channels]; + for (int i = 0; i < channels.length; i++) + channels[i] = new SoftChannel(this, i); + + if(external_channels == null) + { + // Always create external_channels array + // with 16 or more channels + // so getChannels works correctly + // when the synhtesizer is closed. + if(channels.length < 16) + external_channels = new SoftChannelProxy[16]; + else + external_channels = new SoftChannelProxy[channels.length]; + for (int i = 0; i < external_channels.length; i++) + external_channels[i] = new SoftChannelProxy(); + } + else + { + // We must resize external_channels array + // but we must also copy the old SoftChannelProxy + // into the new one + if(channels.length > external_channels.length) + { + SoftChannelProxy[] new_external_channels = new SoftChannelProxy[channels.length]; + for (int i = 0; i < external_channels.length; i++) + new_external_channels[i] = external_channels[i]; + for (int i = external_channels.length; i < new_external_channels.length; i++) + new_external_channels[i] = new SoftChannelProxy(); + } + } + + for (int i = 0; i < channels.length; i++) + external_channels[i].setChannel(channels[i]); + + + for (SoftVoice voice : getVoices()) + voice.resampler = resampler.openStreamer(); + + for (Receiver recv : getReceivers()) + { + SoftReceiver srecv = ((SoftReceiver)recv); + srecv.open = open; + srecv.mainmixer = mainmixer; + srecv.midimessages = mainmixer.midimessages; + } + + return mainmixer.getInputStream(); + + } + + } + + public void close() { + + if(!isOpen()) + return; + + SoftAudioPusher pusher_to_be_closed = null; + AudioInputStream pusher_stream_to_be_closed = null; + synchronized (control_mutex) { + if(pusher != null) + { + pusher_to_be_closed = pusher; + pusher_stream_to_be_closed = pusher_stream; + pusher = null; + pusher_stream = null; + } + } + + if(pusher_to_be_closed != null) + { + // Pusher must not be closed synchronized against control_mutex + // this may result in synchronized conflict between pusher and current thread. + pusher_to_be_closed.stop(); + + try { + pusher_stream_to_be_closed.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + synchronized (control_mutex) { + + if(mainmixer != null) mainmixer.close(); + open = false; + implicitOpen = false; + mainmixer = null; + voices = null; + channels = null; + + if(external_channels != null) + for (int i = 0; i < external_channels.length; i++) + external_channels[i].setChannel(null); + + if(sourceDataLine != null) + { + sourceDataLine.drain(); + sourceDataLine.close(); + sourceDataLine = null; + } + + inslist.clear(); + availlist.clear(); + loadedlist.clear(); + tunings.clear(); + + while(recvslist.size() != 0) + recvslist.get(recvslist.size()-1).close(); + + } + } + + public boolean isOpen() { + synchronized (control_mutex) { + return open; + } + } + + public long getMicrosecondPosition() { + + if(!isOpen()) + return 0; + + synchronized (control_mutex) { + return mainmixer.getMicrosecondPosition(); + } + } + + public int getMaxReceivers() { + return -1; + } + + public int getMaxTransmitters() { + return 0; + } + + public Receiver getReceiver() throws MidiUnavailableException { + + synchronized (control_mutex) { + SoftReceiver receiver = new SoftReceiver(this); + receiver.open = open; + recvslist.add(receiver); + return receiver; + } + } + + public List getReceivers() { + + synchronized (control_mutex) { + ArrayList recvs = new ArrayList(); + recvs.addAll(recvslist); + return recvs; + } + } + + public Transmitter getTransmitter() throws MidiUnavailableException { + + throw new MidiUnavailableException("No transmitter available"); + } + + public List getTransmitters() { + + return new ArrayList(); + } + + public Receiver getReceiverReferenceCounting() throws MidiUnavailableException { + + if(!isOpen()) + { + open(); + synchronized (control_mutex) { + implicitOpen = true; + } + } + + return getReceiver(); + } + + public Transmitter getTransmitterReferenceCounting() throws MidiUnavailableException { + + throw new MidiUnavailableException("No transmitter available"); + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftTuning.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftTuning.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,259 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.UnsupportedEncodingException; + +import javax.sound.midi.Patch; + +/** + * + * A tuning program container, for use with MIDI Tuning. see: + * http://www.midi.org + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftTuning { + + private String name = null; + + private double[] tuning = new double[128]; + + private Patch patch = null; + + public SoftTuning() { + name = "12-TET"; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100; + } + + public SoftTuning(byte[] data) { + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100; + load(data); + } + + public SoftTuning(Patch patch) { + this.patch = patch; + name = "12-TET"; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100; + } + + public SoftTuning(Patch patch, byte[] data) { + this.patch = patch; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100; + load(data); + } + + private boolean checksumOK(byte[] data) { + int x = data[1] & 0xFF; + for (int i = 2; i < data.length - 2; i++) + x = x ^ (data[i] & 0xFF); + return (data[data.length - 2] & 0xFF) == (x & 127); + } + + /* + private boolean checksumOK2(byte[] data) { + int x = data[1] & 0xFF; // 7E + x = x ^ (data[2] & 0xFF); // + x = x ^ (data[4] & 0xFF); // nn + x = x ^ (data[5] & 0xFF); // tt + for (int i = 22; i < data.length - 2; i++) + x = x ^ (data[i] & 0xFF); + return (data[data.length - 2] & 0xFF) == (x & 127); + }*/ + + public void load(byte[] data) { + // Universal Non-Real-Time / Real-Time SysEx + if ((data[1] & 0xFF) == 0x7E || (data[1] & 0xFF) == 0x7F) { + int subid1 = data[3] & 0xFF; + switch (subid1) { + case 0x08: // MIDI Tuning Standard + int subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // BULK TUNING DUMP (NON-REAL-TIME) + { + // http://www.midi.org/about-midi/tuning.shtml + //if (!checksumOK2(data)) + // break; + try { + name = new String(data, 6, 16, "ascii"); + } catch (UnsupportedEncodingException e) { + name = null; + } + int r = 22; + for (int i = 0; i < 128; i++) { + int xx = data[r++] & 0xFF; + int yy = data[r++] & 0xFF; + int zz = data[r++] & 0xFF; + if (!(xx == 127 && yy == 127 && zz == 127)) + tuning[i] = 100.0 * (((xx * 16384) + (yy * 128) + zz) / 16384.0); + } + break; + } + case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME) + { + // http://www.midi.org/about-midi/tuning.shtml + int ll = data[6] & 0xFF; + int r = 7; + for (int i = 0; i < ll; i++) { + int kk = data[r++] & 0xFF; + int xx = data[r++] & 0xFF; + int yy = data[r++] & 0xFF; + int zz = data[r++] & 0xFF; + if (!(xx == 127 && yy == 127 && zz == 127)) + tuning[kk] = 100.0 * (((xx * 16384) + (yy * 128) + zz) / 16384.0); + } + break; + } + case 0x04: // KEY-BASED TUNING DUMP (NON-REAL-TIME) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + if (!checksumOK(data)) + break; + try { + name = new String(data, 7, 16, "ascii"); + } catch (UnsupportedEncodingException e) { + name = null; + } + int r = 23; + for (int i = 0; i < 128; i++) { + int xx = data[r++] & 0xFF; + int yy = data[r++] & 0xFF; + int zz = data[r++] & 0xFF; + if (!(xx == 127 && yy == 127 && zz == 127)) + tuning[i] = 100.0 * (((xx * 16384) + (yy * 128) + zz) / 16384.0); + } + break; + } + case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format + // (NON-REAL-TIME) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + if (!checksumOK(data)) + break; + try { + name = new String(data, 7, 16, "ascii"); + } catch (UnsupportedEncodingException e) { + name = null; + } + int[] octave_tuning = new int[12]; + for (int i = 0; i < 12; i++) + octave_tuning[i] = (data[i + 23] & 0xFF) - 64; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100 + octave_tuning[i % 12]; + break; + } + case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format + // (NON-REAL-TIME) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + if (!checksumOK(data)) + break; + try { + name = new String(data, 7, 16, "ascii"); + } catch (UnsupportedEncodingException e) { + name = null; + } + double[] octave_tuning = new double[12]; + for (int i = 0; i < 12; i++) { + int v = (data[i * 2 + 23] & 0xFF) * 128 + + (data[i * 2 + 24] & 0xFF); + octave_tuning[i] = (v / 8192.0 - 1) * 100.0; + } + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100 + octave_tuning[i % 12]; + break; + } + case 0x07: // SINGLE NOTE TUNING CHANGE (NON + // REAL-TIME/REAL-TIME) (BANK) + // http://www.midi.org/about-midi/tuning_extens.shtml + int ll = data[7] & 0xFF; + int r = 8; + for (int i = 0; i < ll; i++) { + int kk = data[r++] & 0xFF; + int xx = data[r++] & 0xFF; + int yy = data[r++] & 0xFF; + int zz = data[r++] & 0xFF; + if (!(xx == 127 && yy == 127 && zz == 127)) + tuning[kk] = 100.0 * (((xx * 16384) + (yy * 128) + zz) / 16384.0); + } + break; + case 0x08: // scale/octave tuning 1-byte form (Non + // Real-Time/REAL-TIME) + { + // http://www.midi.org/about-midi/tuning-scale.shtml + int[] octave_tuning = new int[12]; + for (int i = 0; i < 12; i++) + octave_tuning[i] = (data[i + 8] & 0xFF) - 64; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100 + octave_tuning[i % 12]; + break; + } + case 0x09: // scale/octave tuning 2-byte form (Non + // Real-Time/REAL-TIME) + { + // http://www.midi.org/about-midi/tuning-scale.shtml + double[] octave_tuning = new double[12]; + for (int i = 0; i < 12; i++) { + int v = (data[i * 2 + 8] & 0xFF) * 128 + + (data[i * 2 + 9] & 0xFF); + octave_tuning[i] = (v / 8192.0 - 1) * 100.0; + } + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100 + octave_tuning[i % 12]; + break; + } + default: + break; + } + } + } + } + + public double[] getTuning() { + return tuning; + } + + public double getTuning(int noteNumber) { + return tuning[noteNumber]; + } + + public Patch getPatch() { + return patch; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,959 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.sound.midi.VoiceStatus; + +/** + * + * Software synthesizer voice class. + * + * @version %I%, %E% + * @author Karl Helgason + */ +public class SoftVoice extends VoiceStatus { + + public int exclusiveClass = 0; + + public boolean releaseTriggered = false; + + private int noteOn_noteNumber = 0; + + private int noteOn_velocity = 0; + + private int noteOff_velocity = 0; + + protected ModelChannelMixer channelmixer = null; + + protected double tunedKey = 0; + + protected SoftTuning tuning = null; + + protected SoftChannel stealer_channel = null; + + protected ModelConnectionBlock[] stealer_extendedConnectionBlocks = null; + + protected SoftPerformer stealer_performer = null; + + protected ModelChannelMixer stealer_channelmixer = null; + + protected int stealer_voiceID = -1; + + protected int stealer_noteNumber = 0; + + protected int stealer_velocity = 0; + + protected boolean stealer_releaseTriggered = false; + + protected int voiceID = -1; + + protected boolean sustain = false; + + protected boolean sostenuto = false; + + protected boolean portamento = false; + + private SoftFilter filter_left; + + private SoftFilter filter_right; + + private SoftProcess eg = new SoftEnvelopeGenerator(); + + private SoftProcess lfo = new SoftLowFrequencyOscillator(); + + protected Map objects = new HashMap(); + + protected SoftSynthesizer synthesizer; + + protected SoftInstrument instrument; + + protected SoftPerformer performer; + + protected SoftChannel softchannel = null; + + protected boolean on = false; + + private boolean audiostarted = false; + + private boolean started = false; + + private boolean stopping = false; + + private float osc_attenuation = 0.0f; + + private ModelOscillatorStream osc_stream;; + + private int osc_stream_nrofchannels; + + private float[][] osc_buff = new float[2][]; + + private boolean osc_stream_off_transmitted = false; + + private boolean out_mixer_end = false; + + private float out_mixer_left = 0; + + private float out_mixer_right = 0; + + private float out_mixer_effect1 = 0; + + private float out_mixer_effect2 = 0; + + private float last_out_mixer_left = 0; + + private float last_out_mixer_right = 0; + + private float last_out_mixer_effect1 = 0; + + private float last_out_mixer_effect2 = 0; + + protected ModelConnectionBlock[] extendedConnectionBlocks = null; + + private ModelConnectionBlock[] connections; + + private double[] connections_last = new double[50]; // Last value added to + // destination + + private double[][][] connections_src = new double[50][3][]; // Pointer to + // source value + + private int[][] connections_src_kc = new int[50][3]; // Key-based + // override (if any) + + private double[][] connections_dst = new double[50][]; // Pointer to + // destination value + + private boolean soundoff = false; + + private float lastMuteValue = 0; + + private float lastSoloMuteValue = 0; + + protected double[] co_noteon_keynumber = new double[1]; + + protected double[] co_noteon_velocity = new double[1]; + + protected double[] co_noteon_on = new double[1]; + + private SoftControl co_noteon = new SoftControl() { + double[] keynumber = co_noteon_keynumber; + + double[] velocity = co_noteon_velocity; + + double[] on = co_noteon_on; + + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("keynumber")) + return keynumber; + if (name.equals("velocity")) + return velocity; + if (name.equals("on")) + return on; + return null; + } + }; + + private double[] co_mixer_active = new double[1]; + + private double[] co_mixer_gain = new double[1]; + + private double[] co_mixer_pan = new double[1]; + + private double[] co_mixer_balance = new double[1]; + + private double[] co_mixer_reverb = new double[1]; + + private double[] co_mixer_chorus = new double[1]; + + private SoftControl co_mixer = new SoftControl() { + double[] active = co_mixer_active; + + double[] gain = co_mixer_gain; + + double[] pan = co_mixer_pan; + + double[] balance = co_mixer_balance; + + double[] reverb = co_mixer_reverb; + + double[] chorus = co_mixer_chorus; + + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("active")) + return active; + if (name.equals("gain")) + return gain; + if (name.equals("pan")) + return pan; + if (name.equals("balance")) + return balance; + if (name.equals("reverb")) + return reverb; + if (name.equals("chorus")) + return chorus; + return null; + } + }; + + private double[] co_osc_pitch = new double[1]; + + private SoftControl co_osc = new SoftControl() { + double[] pitch = co_osc_pitch; + + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("pitch")) + return pitch; + return null; + } + }; + + private double[] co_filter_freq = new double[1]; + + private double[] co_filter_type = new double[1]; + + private double[] co_filter_q = new double[1]; + + private SoftControl co_filter = new SoftControl() { + double[] freq = co_filter_freq; + + double[] ftype = co_filter_type; + + double[] q = co_filter_q; + + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("freq")) + return freq; + if (name.equals("type")) + return ftype; + if (name.equals("q")) + return q; + return null; + } + }; + + protected SoftResamplerStreamer resampler; + + private int nrofchannels; + + public SoftVoice(SoftSynthesizer synth) { + synthesizer = synth; + filter_left = new SoftFilter(synth.getFormat().getSampleRate()); + filter_right = new SoftFilter(synth.getFormat().getSampleRate()); + nrofchannels = synth.getFormat().getChannels(); + } + + private int getValueKC(ModelIdentifier id) { + if (id.getObject().equals("midi_cc")) { + int ic = Integer.parseInt(id.getVariable()); + if (ic != 0 && ic != 32) + if (ic < 120) { + return ic; + } + } else if (id.getObject().equals("midi_rpn")) { + if (id.getVariable().equals("1")) + return 120; // Fine tuning + if (id.getVariable().equals("2")) + return 121; // Coarse tuning + } + return -1; + } + + private double[] getValue(ModelIdentifier id) { + SoftControl o = objects.get(id.getObject()); + if (o == null) + return null; + return o.get(id.getInstance(), id.getVariable()); + } + + private double transformValue(double value, ModelSource src) { + if (src.getTransform() != null) + return src.getTransform().transform(value); + else + return value; + } + + private double transformValue(double value, ModelDestination dst) { + if (dst.getTransform() != null) + return dst.getTransform().transform(value); + else + return value; + } + + private double processKeyBasedController(double value, int keycontrol) { + if (keycontrol == -1) + return value; + if (softchannel.keybasedcontroller_active != null) + if (softchannel.keybasedcontroller_active[note] != null) + if (softchannel.keybasedcontroller_active[note][keycontrol]) { + double key_controlvalue = softchannel.keybasedcontroller_value[note][keycontrol]; + if (keycontrol == 10 || keycontrol == 91 + || keycontrol == 93) + return key_controlvalue; + value += key_controlvalue * 2.0 - 1.0; + if (value > 1) + value = 1; + else if (value < 0) + value = 0; + } + return value; + } + + private void processConnection(int ix) { + ModelConnectionBlock conn = connections[ix]; + double[][] src = connections_src[ix]; + double[] dst = connections_dst[ix]; + if (dst == null || Double.isInfinite(dst[0])) + return; + + double value = conn.getScale(); + if(softchannel.keybasedcontroller_active == null) + { + ModelSource[] srcs = conn.getSources(); + for (int i = 0; i < srcs.length; i++) { + value *= transformValue(src[i][0], srcs[i]); + if(value == 0) break; + } + } + else + { + ModelSource[] srcs = conn.getSources(); + int[] src_kc = connections_src_kc[ix]; + for (int i = 0; i < srcs.length; i++) { + value *= transformValue(processKeyBasedController(src[i][0], + src_kc[i]), srcs[i]); + if(value == 0) break; + } + } + + value = transformValue(value, conn.getDestination()); + dst[0] = dst[0] - connections_last[ix] + value; + connections_last[ix] = value; + // co_mixer_gain[0] = 0; + + + } + + protected void updateTuning(SoftTuning newtuning) { + tunedKey = tuning.getTuning(note) / 100.0; + if (!portamento) { + co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0); + ; + int[] c = performer.midi_connections[4]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + } + + protected void setNote(int noteNumber) { + note = noteNumber; + tunedKey = tuning.getTuning(noteNumber) / 100.0; + } + + protected void noteOn(int noteNumber, int velocity) { + + sustain = false; + sostenuto = false; + portamento = false; + + soundoff = false; + on = true; + active = true; + started = true; + // volume = velocity; + + noteOn_noteNumber = noteNumber; + noteOn_velocity = velocity; + + lastMuteValue = 0; + lastSoloMuteValue = 0; + + setNote(noteNumber); + + if (performer.forcedKeynumber) + co_noteon_keynumber[0] = 0; + else + co_noteon_keynumber[0] = tunedKey * (1f / 128f); + if (performer.forcedVelocity) + co_noteon_velocity[0] = 0; + else + co_noteon_velocity[0] = velocity * (1f / 128f); + co_mixer_active[0] = 0; + co_mixer_gain[0] = 0; + co_mixer_pan[0] = 0; + co_mixer_balance[0] = 0; + co_mixer_reverb[0] = 0; + co_mixer_chorus[0] = 0; + co_osc_pitch[0] = 0; + co_filter_freq[0] = 0; + co_filter_q[0] = 0; + co_filter_type[0] = 0; + co_noteon_on[0] = 1; + + eg.reset(); + lfo.reset(); + filter_left.reset(); + filter_right.reset(); + + objects.put("master", synthesizer.getMainMixer().co_master); + objects.put("eg", eg); + objects.put("lfo", lfo); + objects.put("noteon", co_noteon); + objects.put("osc", co_osc); + objects.put("mixer", co_mixer); + objects.put("filter", co_filter); + + connections = performer.connections; + + if (connections_last == null + || connections_last.length < connections.length) + connections_last = new double[connections.length]; + if (connections_src == null + || connections_src.length < connections.length) { + connections_src = new double[connections.length][][]; + connections_src_kc = new int[connections.length][]; + } + if (connections_dst == null + || connections_dst.length < connections.length) + connections_dst = new double[connections.length][]; + for (int i = 0; i < connections.length; i++) { + ModelConnectionBlock conn = connections[i]; + connections_last[i] = 0; + if (conn.getSources() != null) { + ModelSource[] srcs = conn.getSources(); + if (connections_src[i] == null + || connections_src[i].length < srcs.length) { + connections_src[i] = new double[srcs.length][]; + connections_src_kc[i] = new int[srcs.length]; + } + double[][] src = connections_src[i]; + int[] src_kc = connections_src_kc[i]; + connections_src[i] = src; + for (int j = 0; j < srcs.length; j++) { + src_kc[j] = getValueKC(srcs[j].getIdentifier()); + src[j] = getValue(srcs[j].getIdentifier()); + } + } + + if (conn.getDestination() != null) + connections_dst[i] = getValue(conn.getDestination() + .getIdentifier()); + else + connections_dst[i] = null; + } + + for (int i = 0; i < connections.length; i++) + processConnection(i); + + + if(extendedConnectionBlocks != null) + { + for (ModelConnectionBlock connection : extendedConnectionBlocks) { + + double value = 0; + + if(softchannel.keybasedcontroller_active == null) + { + for(ModelSource src : connection.getSources()) + { + double x = getValue(src.getIdentifier())[0]; + ModelTransform t = src.getTransform(); + if(t == null) + value += x; + else + value += t.transform(x); + } + } + else + { + for(ModelSource src : connection.getSources()) + { + double x = getValue(src.getIdentifier())[0]; + x = processKeyBasedController(x, getValueKC(src.getIdentifier())); + ModelTransform t = src.getTransform(); + if(t == null) + value += x; + else + value += t.transform(x); + } + } + + ModelDestination dest = connection.getDestination(); + ModelTransform t = dest.getTransform(); + if(t != null) + value = t.transform(value); + getValue(dest.getIdentifier())[0] += value; + + } + } + + eg.init(synthesizer); + lfo.init(synthesizer); + + } + + protected void setPolyPressure(int pressure) { + int[] c = performer.midi_connections[2]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void setChannelPressure(int pressure) { + int[] c = performer.midi_connections[1]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void controlChange(int controller, int value) { + int[] c = performer.midi_ctrl_connections[controller]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void nrpnChange(int controller, int value) { + int[] c = performer.midi_nrpn_connections.get(controller); + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + + } + + protected void rpnChange(int controller, int value) { + int[] c = performer.midi_rpn_connections.get(controller); + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void setPitchBend(int bend) { + int[] c = performer.midi_connections[0]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + + } + + protected void setMute(boolean mute) { + co_mixer_gain[0] -= lastMuteValue; + lastMuteValue = mute ? -960 : 0; + co_mixer_gain[0] += lastMuteValue; + } + + protected void setSoloMute(boolean mute) { + co_mixer_gain[0] -= lastSoloMuteValue; + lastSoloMuteValue = mute ? -960 : 0; + co_mixer_gain[0] += lastSoloMuteValue; + } + + protected void shutdown() { + if (co_noteon_on[0] < -0.5) + return; + on = false; + + co_noteon_on[0] = -1; + + int[] c = performer.midi_connections[3]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + + } + + protected void soundOff() { + on = false; + soundoff = true; + } + + protected void noteOff(int velocity) { + if (!on) + return; + on = false; + + noteOff_velocity = velocity; + + if (softchannel.sustain) { + sustain = true; + return; + } + if (sostenuto) + return; + + co_noteon_on[0] = 0; + + int[] c = performer.midi_connections[3]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + + } + + protected void redamp() { + if (co_noteon_on[0] > 0.5) + return; + if (co_noteon_on[0] < -0.5) + return; // don't redamp notes in shutdown stage + + sustain = true; + co_noteon_on[0] = 1; + + int[] c = performer.midi_connections[3]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + + } + + protected void processControlLogic() { + + + + if (stopping) { + active = false; + stopping = false; + audiostarted = false; + if (osc_stream != null) + try { + osc_stream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + if (stealer_channel != null) { + stealer_channel.initVoice(this, stealer_performer, + stealer_voiceID, stealer_noteNumber, stealer_velocity, stealer_extendedConnectionBlocks, stealer_channelmixer, stealer_releaseTriggered); + stealer_releaseTriggered = false; + stealer_channel = null; + stealer_performer = null; + stealer_voiceID = -1; + stealer_noteNumber = 0; + stealer_velocity = 0; + stealer_extendedConnectionBlocks = null; + stealer_channelmixer = null; + } + } + if (started) { + audiostarted = true; + + ModelOscillator osc = performer.oscillators[0]; + + osc_stream_off_transmitted = false; + if (osc instanceof ModelWavetable) { + try { + resampler.open((ModelWavetable) osc, synthesizer + .getFormat().getSampleRate()); + osc_stream = resampler; + } catch (IOException e) { + e.printStackTrace(); + } + } else { + osc_stream = osc.open(synthesizer.getFormat().getSampleRate()); + } + osc_attenuation = osc.getAttenuation(); + osc_stream_nrofchannels = osc.getChannels(); + if (osc_buff == null || osc_buff.length < osc_stream_nrofchannels) + osc_buff = new float[osc_stream_nrofchannels][]; + + if (osc_stream != null) + osc_stream.noteOn(softchannel, this, noteOn_noteNumber, + noteOn_velocity); + + + } + if (audiostarted) { + + if (portamento) { + + double note_delta = tunedKey - (co_noteon_keynumber[0] * 128); + double note_delta_a = Math.abs(note_delta); + if (note_delta_a < 0.0000000001) { + co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0); + ; + portamento = false; + + } else { + if (note_delta_a > softchannel.portamento_time) + note_delta = Math.signum(note_delta) + * softchannel.portamento_time; + co_noteon_keynumber[0] += note_delta * (1.0 / 128.0); + } + + int[] c = performer.midi_connections[4]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + + } + + eg.processControlLogic(); + lfo.processControlLogic(); + + for (int i = 0; i < performer.ctrl_connections.length; i++) + processConnection(performer.ctrl_connections[i]); + + osc_stream.setPitch((float) co_osc_pitch[0]); + + int filter_type = (int) co_filter_type[0]; + double filter_freq; + + if(co_filter_freq[0] == 13500.0) + filter_freq = 19912.126958213175; + else + filter_freq = 440.0 * Math.exp( + ((co_filter_freq[0]) - 6900.0) * (Math.log(2.0)/ 1200.0)); + /* + filter_freq = 440.0 * Math.pow(2.0, + ((co_filter_freq[0]) - 6900.0) / 1200.0);*/ + /* + * double velocity = co_noteon_velocity[0]; if(velocity < 0.5) + * filter_freq *= ((velocity * 2)*0.75 + 0.25); + */ + + double q = co_filter_q[0] / 10.0; + filter_left.setFilterType(filter_type); + filter_left.setFrequency(filter_freq); + filter_left.setResonance(q); + filter_right.setFilterType(filter_type); + filter_right.setFrequency(filter_freq); + filter_right.setResonance(q); + /* + float gain = (float) Math.pow(10, + (-osc_attenuation + co_mixer_gain[0]) / 200.0); + */ + float gain = (float) Math.exp(( + (-osc_attenuation + co_mixer_gain[0]) * ( Math.log(10)/ 200.0))); + + if (co_mixer_gain[0] <= -960) + gain = 0; + + if (soundoff) { + stopping = true; + gain = 0; + /* + * if(co_mixer_gain[0] > -960) co_mixer_gain[0] -= 960; + */ + } + + volume = (int) (Math.sqrt(gain) * 128); + + // gain *= 0.2; + + double pan = co_mixer_pan[0] * (1.0 / 1000.0); + // System.out.println("pan = " + pan); + if (pan < 0) + pan = 0; + else if (pan > 1) + pan = 1; + + if(pan == 0.5) + { + out_mixer_left = gain * 0.7071067811865476f; + out_mixer_right = out_mixer_left; + } + else + { + out_mixer_left = gain * (float) Math.cos(pan * Math.PI * 0.5); + out_mixer_right = gain * (float) Math.sin(pan * Math.PI * 0.5); + } + + double balance = co_mixer_balance[0] * (1.0 / 1000.0); + if(balance != 0.5) + { + if (balance > 0.5) + out_mixer_left *= (1 - balance) * 2; + else + out_mixer_right *= balance * 2; + } + + if(synthesizer.reverb_on) + { + out_mixer_effect1 = (float) (co_mixer_reverb[0] * (1.0 / 1000.0)); + out_mixer_effect1 *= gain; + } + else + out_mixer_effect1 = 0; + if(synthesizer.chorus_on) + { + out_mixer_effect2 = (float) (co_mixer_chorus[0] * (1.0 / 1000.0)); + out_mixer_effect2 *= gain; + } + else + out_mixer_effect2 = 0; + out_mixer_end = co_mixer_active[0] < 0.5; + + if (!on) + if (!osc_stream_off_transmitted) { + osc_stream_off_transmitted = true; + if (osc_stream != null) + osc_stream.noteOff(noteOff_velocity); + } + + } + if (started) { + last_out_mixer_left = out_mixer_left; + last_out_mixer_right = out_mixer_right; + last_out_mixer_effect1 = out_mixer_effect1; + last_out_mixer_effect2 = out_mixer_effect2; + started = false; + } + + } + + protected void mixAudioStream(SoftAudioBuffer in, SoftAudioBuffer out, + float amp_from, float amp_to) { + int bufferlen = in.getSize(); + if (amp_from < 0.000000001 && amp_to < 0.000000001) + return; + if (amp_from == amp_to) { + float[] fout = out.array(); + float[] fin = in.array(); + for (int i = 0; i < bufferlen; i++) + fout[i] += fin[i] * amp_to; + } else { + float amp = amp_from; + float amp_delta = (amp_to - amp_from) / bufferlen; + float[] fout = out.array(); + float[] fin = in.array(); + for (int i = 0; i < bufferlen; i++) { + amp += amp_delta; + fout[i] += fin[i] * amp; + } + } + + } + + protected void processAudioLogic(SoftAudioBuffer[] buffer) { + if (!audiostarted) + return; + + int bufferlen = buffer[0].getSize(); + + try { + osc_buff[0] = buffer[SoftMainMixer.CHANNEL_LEFT_DRY].array(); + if(nrofchannels != 1) + osc_buff[1] = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY].array(); + int ret = osc_stream.read(osc_buff, 0, bufferlen); + if (ret == -1) { + stopping = true; + return; + } + if (ret != bufferlen) { + Arrays.fill(osc_buff[0], ret, bufferlen, 0f); + if(nrofchannels != 1) + Arrays.fill(osc_buff[1], ret, bufferlen, 0f); + } + + } catch (IOException e) { + e.printStackTrace(); + } + + SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT]; + SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT]; + SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1]; + SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2]; + SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY]; + SoftAudioBuffer rightdry = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY]; + + if (osc_stream_nrofchannels == 1) + rightdry = null; + + if (!Double.isInfinite(co_filter_freq[0])) { + filter_left.processAudio(leftdry); + if (rightdry != null) + filter_right.processAudio(rightdry); + } + + if (nrofchannels == 1) { + out_mixer_left = (out_mixer_left + out_mixer_right) / 2; + mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left); + if (rightdry != null) + mixAudioStream(rightdry, left, last_out_mixer_left, + out_mixer_left); + } else { + mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left); + if (rightdry != null) + mixAudioStream(rightdry, right, last_out_mixer_right, + out_mixer_right); + else + mixAudioStream(leftdry, right, last_out_mixer_right, + out_mixer_right); + } + + if (rightdry == null) { + mixAudioStream(leftdry, eff1, last_out_mixer_effect1, + out_mixer_effect1); + mixAudioStream(leftdry, eff2, last_out_mixer_effect2, + out_mixer_effect2); + } else { + mixAudioStream(leftdry, eff1, last_out_mixer_effect1 * 0.5f, + out_mixer_effect1 * 0.5f); + mixAudioStream(leftdry, eff2, last_out_mixer_effect2 * 0.5f, + out_mixer_effect2 * 0.5f); + mixAudioStream(rightdry, eff1, last_out_mixer_effect1 * 0.5f, + out_mixer_effect1 * 0.5f); + mixAudioStream(rightdry, eff2, last_out_mixer_effect2 * 0.5f, + out_mixer_effect2 * 0.5f); + } + + last_out_mixer_left = out_mixer_left; + last_out_mixer_right = out_mixer_right; + last_out_mixer_effect1 = out_mixer_effect1; + last_out_mixer_effect2 = out_mixer_effect2; + + if (out_mixer_end) { + stopping = true; + } + + + } + +} diff -r 1b845dd20b86 -r bcba163568ac overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,173 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileReader; + +/** + * Floating-point encoded (format 3) WAVE file loader. + * + * @version %I%, %E% + * @author Karl Helgason + */ + +public class WaveFloatFileReader extends AudioFileReader { + + public AudioFileFormat getAudioFileFormat(InputStream stream) + throws UnsupportedAudioFileException, IOException { + + stream.mark(200); + AudioFileFormat format; + try { + format = internal_getAudioFileFormat(stream); + } finally { + stream.reset(); + } + return format; + } + + private AudioFileFormat internal_getAudioFileFormat(InputStream stream) + throws UnsupportedAudioFileException, IOException { + + RIFFReader riffiterator = new RIFFReader(stream); + if (!riffiterator.getFormat().equals("RIFF")) + throw new UnsupportedAudioFileException(); + if (!riffiterator.getType().equals("WAVE")) + throw new UnsupportedAudioFileException(); + + boolean fmt_found = false; + boolean data_found = false; + + int channels = 1; + long samplerate = 1; + long framerate = 1; + int framesize = 1; + int bits = 1; + + while (riffiterator.hasNextChunk()) { + RIFFReader chunk = riffiterator.nextChunk(); + + if (chunk.getFormat().equals("fmt ")) { + fmt_found = true; + + int format = chunk.readUnsignedShort(); + if (format != 3) + throw new UnsupportedAudioFileException(); // WAVE_FORMAT_IEEE_FLOAT + // only + channels = chunk.readUnsignedShort(); + samplerate = chunk.readUnsignedInt(); + framerate = chunk.readUnsignedInt(); + framesize = chunk.readUnsignedShort(); + bits = chunk.readUnsignedShort(); + + } + if (chunk.getFormat().equals("data")) { + data_found = true; + break; + } + } + + if (!fmt_found) + throw new UnsupportedAudioFileException(); + if (!data_found) + throw new UnsupportedAudioFileException(); + + AudioFormat audioformat = new AudioFormat( + AudioFloatConverter.PCM_FLOAT, samplerate, bits, channels, + framesize, framerate, false); + AudioFileFormat fileformat = new AudioFileFormat( + AudioFileFormat.Type.WAVE, audioformat, + AudioSystem.NOT_SPECIFIED); + return fileformat; + } + + public AudioInputStream getAudioInputStream(InputStream stream) + throws UnsupportedAudioFileException, IOException { + + AudioFileFormat format = getAudioFileFormat(stream); + RIFFReader riffiterator = new RIFFReader(stream); + if (!riffiterator.getFormat().equals("RIFF")) + throw new UnsupportedAudioFileException(); + if (!riffiterator.getType().equals("WAVE")) + throw new UnsupportedAudioFileException(); + while (riffiterator.hasNextChunk()) { + RIFFReader chunk = riffiterator.nextChunk(); + if (chunk.getFormat().equals("data")) { + return new AudioInputStream(chunk, format.getFormat(), chunk + .getSize()); + } + } + throw new UnsupportedAudioFileException(); + } + + public AudioFileFormat getAudioFileFormat(URL url) + throws UnsupportedAudioFileException, IOException { + InputStream stream = url.openStream(); + AudioFileFormat format; + try { + format = getAudioFileFormat(new BufferedInputStream(stream)); + } finally { + stream.close(); + } + return format; + } + + public AudioFileFormat getAudioFileFormat(File file) + throws UnsupportedAudioFileException, IOException { + InputStream stream = new FileInputStream(file); + AudioFileFormat format; + try { + format = getAudioFileFormat(new BufferedInputStream(stream)); + } finally { + stream.close(); + } + return format; + } + + public AudioInputStream getAudioInputStream(URL url) + throws UnsupportedAudioFileException, IOException { + return getAudioInputStream(new BufferedInputStream(url.openStream())); + } + + public AudioInputStream getAudioInputStream(File file) + throws UnsupportedAudioFileException, IOException { + return getAudioInputStream(new BufferedInputStream(new FileInputStream( + file))); + } + +} diff -r 1b845dd20b86 -r bcba163568ac patches/icedtea-gervill.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/icedtea-gervill.patch Wed Apr 30 22:09:08 2008 +0200 @@ -0,0 +1,30 @@ +# Adds the provides defined by gervill (and removes non-existing ones). +# Gervill can be found in the overlays under +# openjdk/jdk/src/share/classes/com/sun/media/sound +--- openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider.orig 2008-04-30 16:12:37.000000000 +0200 ++++ openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider 2008-04-30 16:06:18.000000000 +0200 +@@ -1,5 +1,5 @@ + # Providers for midi devices +-com.sun.media.sound.MixerSynthProvider + com.sun.media.sound.RealTimeSequencerProvider + com.sun.media.sound.MidiOutDeviceProvider + com.sun.media.sound.MidiInDeviceProvider ++com.sun.media.sound.SoftProvider +--- openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader.orig 2008-04-30 16:13:18.000000000 +0200 ++++ openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader 2008-04-30 16:07:16.000000000 +0200 +@@ -1,2 +1,6 @@ + # Providers for Soundbanks +-com.sun.media.sound.HsbParser ++com.sun.media.sound.PATSoundbankReader ++com.sun.media.sound.DLSSoundbankReader ++com.sun.media.sound.JARSoundbankReader ++com.sun.media.sound.AudioFileSoundbankReader ++com.sun.media.sound.SF2SoundbankReader +--- openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader.orig 2008-04-30 16:13:58.000000000 +0200 ++++ openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader 2008-04-30 16:01:27.000000000 +0200 +@@ -2,3 +2,5 @@ + com.sun.media.sound.AuFileReader + com.sun.media.sound.AiffFileReader + com.sun.media.sound.WaveFileReader ++com.sun.media.sound.WaveFloatFileReader ++com.sun.media.sound.SoftMidiAudioFileReader