< prev index next >

src/java.desktop/share/classes/com/sun/media/sound/SoftAbstractResampler.java

Print this page




   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */

  25 package com.sun.media.sound;
  26 
  27 import java.io.IOException;
  28 import java.util.Arrays;
  29 
  30 import javax.sound.midi.MidiChannel;
  31 import javax.sound.midi.VoiceStatus;
  32 
  33 /**
  34  * Abstract resampler class.
  35  *
  36  * @author Karl Helgason
  37  */
  38 public abstract class SoftAbstractResampler implements SoftResampler {
  39 
  40     private class ModelAbstractResamplerStream implements SoftResamplerStreamer {
  41 
  42         AudioFloatInputStream stream;
  43         boolean stream_eof = false;
  44         int loopmode;


  57         int streampos = 0;
  58         int nrofchannels = 2;
  59         boolean noteOff_flag = false;
  60         float[][] ibuffer;
  61         boolean ibuffer_order = true;
  62         float[] sbuffer;
  63         int pad;
  64         int pad2;
  65         float[] ix = new float[1];
  66         int[] ox = new int[1];
  67         float samplerateconv = 1;
  68         float pitchcorrection = 0;
  69 
  70         ModelAbstractResamplerStream() {
  71             pad = getPadding();
  72             pad2 = getPadding() * 2;
  73             ibuffer = new float[2][sector_size + pad2];
  74             ibuffer_order = true;
  75         }
  76 

  77         public void noteOn(MidiChannel channel, VoiceStatus voice,
  78                 int noteNumber, int velocity) {
  79         }
  80 

  81         public void noteOff(int velocity) {
  82             noteOff_flag = true;
  83         }
  84 

  85         public void open(ModelWavetable osc, float outputsamplerate)
  86                 throws IOException {
  87 
  88             eof = false;
  89             nrofchannels = osc.getChannels();
  90             if (ibuffer.length < nrofchannels) {
  91                 ibuffer = new float[nrofchannels][sector_size + pad2];
  92             }
  93 
  94             stream = osc.openStream();
  95             streampos = 0;
  96             stream_eof = false;
  97             pitchcorrection = osc.getPitchcorrection();
  98             samplerateconv
  99                     = stream.getFormat().getSampleRate() / outputsamplerate;
 100             looplen = osc.getLoopLength();
 101             loopstart = osc.getLoopStart();
 102             sector_loopstart = (int) (loopstart / sector_size);
 103             sector_loopstart = sector_loopstart - 1;
 104 


 118 
 119             target_pitch = samplerateconv;
 120             current_pitch[0] = samplerateconv;
 121 
 122             ibuffer_order = true;
 123             loopdirection = true;
 124             noteOff_flag = false;
 125 
 126             for (int i = 0; i < nrofchannels; i++)
 127                 Arrays.fill(ibuffer[i], sector_size, sector_size + pad2, 0);
 128             ix[0] = pad;
 129             eof = false;
 130 
 131             ix[0] = sector_size + pad;
 132             sector_pos = -1;
 133             streampos = -sector_size;
 134 
 135             nextBuffer();
 136         }
 137 

 138         public void setPitch(float pitch) {
 139             /*
 140             this.pitch = (float) Math.pow(2f,
 141             (pitchcorrection + pitch) / 1200.0f)
 142              * samplerateconv;
 143              */
 144             this.target_pitch = (float)Math.exp(
 145                     (pitchcorrection + pitch) * (Math.log(2.0) / 1200.0))
 146                 * samplerateconv;
 147 
 148             if (!started)
 149                 current_pitch[0] = this.target_pitch;
 150         }
 151 
 152         public void nextBuffer() throws IOException {
 153             if (ix[0] < pad) {
 154                 if (markset) {
 155                     // reset to target sector
 156                     stream.reset();
 157                     ix[0] += streampos - (sector_loopstart * sector_size);


 237                 ibuffer_order = true;
 238 
 239             }
 240 
 241         }
 242 
 243         public void reverseBuffers() {
 244             ibuffer_order = !ibuffer_order;
 245             for (int c = 0; c < nrofchannels; c++) {
 246                 float[] cbuff = ibuffer[c];
 247                 int len = cbuff.length - 1;
 248                 int len2 = cbuff.length / 2;
 249                 for (int i = 0; i < len2; i++) {
 250                     float x = cbuff[i];
 251                     cbuff[i] = cbuff[len - i];
 252                     cbuff[len - i] = x;
 253                 }
 254             }
 255         }
 256 

 257         public int read(float[][] buffer, int offset, int len)
 258                 throws IOException {
 259 
 260             if (eof)
 261                 return -1;
 262 
 263             if (noteOff_flag)
 264                 if ((loopmode & 2) != 0)
 265                     if (loopdirection)
 266                         loopmode = 0;
 267 
 268 
 269             float pitchstep = (target_pitch - current_pitch[0]) / len;
 270             float[] current_pitch = this.current_pitch;
 271             started = true;
 272 
 273             int[] ox = this.ox;
 274             ox[0] = offset;
 275             int ox_end = len + offset;
 276 


 356                 for (int i = 0; i < nrofchannels; i++) {
 357                     if (buffer[i] != null) {
 358                         ix[0] = bak_ix;
 359                         ox[0] = bak_ox;
 360                         current_pitch[0] = bak_pitch;
 361                         interpolate(ibuffer[i], ix, ixend, current_pitch,
 362                                 pitchstep, buffer[i], ox, ox_end);
 363                     }
 364                 }
 365 
 366                 if (eof) {
 367                     current_pitch[0] = this.target_pitch;
 368                     return ox[0] - offset;
 369                 }
 370             }
 371 
 372             current_pitch[0] = this.target_pitch;
 373             return len;
 374         }
 375 

 376         public void close() throws IOException {
 377             stream.close();
 378         }
 379     }
 380 
 381     public abstract int getPadding();
 382 
 383     public abstract void interpolate(float[] in, float[] in_offset,
 384             float in_end, float[] pitch, float pitchstep, float[] out,
 385             int[] out_offset, int out_end);
 386 

 387     public final SoftResamplerStreamer openStreamer() {
 388         return new ModelAbstractResamplerStream();
 389     }
 390 }


   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.media.sound;
  27 
  28 import java.io.IOException;
  29 import java.util.Arrays;
  30 
  31 import javax.sound.midi.MidiChannel;
  32 import javax.sound.midi.VoiceStatus;
  33 
  34 /**
  35  * Abstract resampler class.
  36  *
  37  * @author Karl Helgason
  38  */
  39 public abstract class SoftAbstractResampler implements SoftResampler {
  40 
  41     private class ModelAbstractResamplerStream implements SoftResamplerStreamer {
  42 
  43         AudioFloatInputStream stream;
  44         boolean stream_eof = false;
  45         int loopmode;


  58         int streampos = 0;
  59         int nrofchannels = 2;
  60         boolean noteOff_flag = false;
  61         float[][] ibuffer;
  62         boolean ibuffer_order = true;
  63         float[] sbuffer;
  64         int pad;
  65         int pad2;
  66         float[] ix = new float[1];
  67         int[] ox = new int[1];
  68         float samplerateconv = 1;
  69         float pitchcorrection = 0;
  70 
  71         ModelAbstractResamplerStream() {
  72             pad = getPadding();
  73             pad2 = getPadding() * 2;
  74             ibuffer = new float[2][sector_size + pad2];
  75             ibuffer_order = true;
  76         }
  77 
  78         @Override
  79         public void noteOn(MidiChannel channel, VoiceStatus voice,
  80                            int noteNumber, int velocity) {
  81         }
  82 
  83         @Override
  84         public void noteOff(int velocity) {
  85             noteOff_flag = true;
  86         }
  87 
  88         @Override
  89         public void open(ModelWavetable osc, float outputsamplerate)
  90                 throws IOException {
  91 
  92             eof = false;
  93             nrofchannels = osc.getChannels();
  94             if (ibuffer.length < nrofchannels) {
  95                 ibuffer = new float[nrofchannels][sector_size + pad2];
  96             }
  97 
  98             stream = osc.openStream();
  99             streampos = 0;
 100             stream_eof = false;
 101             pitchcorrection = osc.getPitchcorrection();
 102             samplerateconv
 103                     = stream.getFormat().getSampleRate() / outputsamplerate;
 104             looplen = osc.getLoopLength();
 105             loopstart = osc.getLoopStart();
 106             sector_loopstart = (int) (loopstart / sector_size);
 107             sector_loopstart = sector_loopstart - 1;
 108 


 122 
 123             target_pitch = samplerateconv;
 124             current_pitch[0] = samplerateconv;
 125 
 126             ibuffer_order = true;
 127             loopdirection = true;
 128             noteOff_flag = false;
 129 
 130             for (int i = 0; i < nrofchannels; i++)
 131                 Arrays.fill(ibuffer[i], sector_size, sector_size + pad2, 0);
 132             ix[0] = pad;
 133             eof = false;
 134 
 135             ix[0] = sector_size + pad;
 136             sector_pos = -1;
 137             streampos = -sector_size;
 138 
 139             nextBuffer();
 140         }
 141 
 142         @Override
 143         public void setPitch(float pitch) {
 144             /*
 145             this.pitch = (float) Math.pow(2f,
 146             (pitchcorrection + pitch) / 1200.0f)
 147              * samplerateconv;
 148              */
 149             this.target_pitch = (float)Math.exp(
 150                     (pitchcorrection + pitch) * (Math.log(2.0) / 1200.0))
 151                 * samplerateconv;
 152 
 153             if (!started)
 154                 current_pitch[0] = this.target_pitch;
 155         }
 156 
 157         public void nextBuffer() throws IOException {
 158             if (ix[0] < pad) {
 159                 if (markset) {
 160                     // reset to target sector
 161                     stream.reset();
 162                     ix[0] += streampos - (sector_loopstart * sector_size);


 242                 ibuffer_order = true;
 243 
 244             }
 245 
 246         }
 247 
 248         public void reverseBuffers() {
 249             ibuffer_order = !ibuffer_order;
 250             for (int c = 0; c < nrofchannels; c++) {
 251                 float[] cbuff = ibuffer[c];
 252                 int len = cbuff.length - 1;
 253                 int len2 = cbuff.length / 2;
 254                 for (int i = 0; i < len2; i++) {
 255                     float x = cbuff[i];
 256                     cbuff[i] = cbuff[len - i];
 257                     cbuff[len - i] = x;
 258                 }
 259             }
 260         }
 261 
 262         @Override
 263         public int read(float[][] buffer, int offset, int len)
 264                 throws IOException {
 265 
 266             if (eof)
 267                 return -1;
 268 
 269             if (noteOff_flag)
 270                 if ((loopmode & 2) != 0)
 271                     if (loopdirection)
 272                         loopmode = 0;
 273 
 274 
 275             float pitchstep = (target_pitch - current_pitch[0]) / len;
 276             float[] current_pitch = this.current_pitch;
 277             started = true;
 278 
 279             int[] ox = this.ox;
 280             ox[0] = offset;
 281             int ox_end = len + offset;
 282 


 362                 for (int i = 0; i < nrofchannels; i++) {
 363                     if (buffer[i] != null) {
 364                         ix[0] = bak_ix;
 365                         ox[0] = bak_ox;
 366                         current_pitch[0] = bak_pitch;
 367                         interpolate(ibuffer[i], ix, ixend, current_pitch,
 368                                 pitchstep, buffer[i], ox, ox_end);
 369                     }
 370                 }
 371 
 372                 if (eof) {
 373                     current_pitch[0] = this.target_pitch;
 374                     return ox[0] - offset;
 375                 }
 376             }
 377 
 378             current_pitch[0] = this.target_pitch;
 379             return len;
 380         }
 381 
 382         @Override
 383         public void close() throws IOException {
 384             stream.close();
 385         }
 386     }
 387 
 388     public abstract int getPadding();
 389 
 390     public abstract void interpolate(float[] in, float[] in_offset,
 391             float in_end, float[] pitch, float pitchstep, float[] out,
 392             int[] out_offset, int out_end);
 393 
 394     @Override
 395     public final SoftResamplerStreamer openStreamer() {
 396         return new ModelAbstractResamplerStream();
 397     }
 398 }
< prev index next >