Mercurial > hg > release > icedtea6-1.2
view overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAbstractResampler.java @ 843:bcba163568ac
Integrate Gervill.
2008-04-30 Mark Wielaard <mark@klomp.org>
* 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.
author | Mark Wielaard <mark@klomp.org> |
---|---|
date | Wed, 30 Apr 2008 22:09:08 +0200 |
parents | |
children |
line wrap: on
line source
/* * 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(); } }