Save This Page
Home » openjdk-7 » com.sun.media » sound » [javadoc | source]
    1   /*
    2    * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  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;
   45           boolean loopdirection = true; // true = forward
   46           float loopstart;
   47           float looplen;
   48           float target_pitch;
   49           float[] current_pitch = new float[1];
   50           boolean started;
   51           boolean eof;
   52           int sector_pos = 0;
   53           int sector_size = 400;
   54           int sector_loopstart = -1;
   55           boolean markset = false;
   56           int marklimit = 0;
   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           public 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   
  105               sector_pos = 0;
  106   
  107               if (sector_loopstart < 0)
  108                   sector_loopstart = 0;
  109               started = false;
  110               loopmode = osc.getLoopType();
  111   
  112               if (loopmode != 0) {
  113                   markset = false;
  114                   marklimit = nrofchannels * (int) (looplen + pad2 + 1);
  115               } else
  116                   markset = true;
  117               // loopmode = 0;
  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);
  158                       sector_pos = sector_loopstart;
  159                       streampos = sector_pos * sector_size;
  160   
  161                       // and go one sector backward
  162                       ix[0] += sector_size;
  163                       sector_pos -= 1;
  164                       streampos -= sector_size;
  165                       stream_eof = false;
  166                   }
  167               }
  168   
  169               if (ix[0] >= sector_size + pad) {
  170                   if (stream_eof) {
  171                       eof = true;
  172                       return;
  173                   }
  174               }
  175   
  176               if (ix[0] >= sector_size * 4 + pad) {
  177                   int skips = (int)((ix[0] - sector_size * 4 + pad) / sector_size);
  178                   ix[0] -= sector_size * skips;
  179                   sector_pos += skips;
  180                   streampos += sector_size * skips;
  181                   stream.skip(sector_size * skips);
  182               }
  183   
  184               while (ix[0] >= sector_size + pad) {
  185                   if (!markset) {
  186                       if (sector_pos + 1 == sector_loopstart) {
  187                           stream.mark(marklimit);
  188                           markset = true;
  189                       }
  190                   }
  191                   ix[0] -= sector_size;
  192                   sector_pos++;
  193                   streampos += sector_size;
  194   
  195                   for (int c = 0; c < nrofchannels; c++) {
  196                       float[] cbuffer = ibuffer[c];
  197                       for (int i = 0; i < pad2; i++)
  198                           cbuffer[i] = cbuffer[i + sector_size];
  199                   }
  200   
  201                   int ret;
  202                   if (nrofchannels == 1)
  203                       ret = stream.read(ibuffer[0], pad2, sector_size);
  204                   else {
  205                       int slen = sector_size * nrofchannels;
  206                       if (sbuffer == null || sbuffer.length < slen)
  207                           sbuffer = new float[slen];
  208                       int sret = stream.read(sbuffer, 0, slen);
  209                       if (sret == -1)
  210                           ret = -1;
  211                       else {
  212                           ret = sret / nrofchannels;
  213                           for (int i = 0; i < nrofchannels; i++) {
  214                               float[] buff = ibuffer[i];
  215                               int ix = i;
  216                               int ix_step = nrofchannels;
  217                               int ox = pad2;
  218                               for (int j = 0; j < ret; j++, ix += ix_step, ox++)
  219                                   buff[ox] = sbuffer[ix];
  220                           }
  221                       }
  222   
  223                   }
  224   
  225                   if (ret == -1) {
  226                       ret = 0;
  227                       stream_eof = true;
  228                       for (int i = 0; i < nrofchannels; i++)
  229                           Arrays.fill(ibuffer[i], pad2, pad2 + sector_size, 0f);
  230                       return;
  231                   }
  232                   if (ret != sector_size) {
  233                       for (int i = 0; i < nrofchannels; i++)
  234                           Arrays.fill(ibuffer[i], pad2 + ret, pad2 + sector_size, 0f);
  235                   }
  236   
  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   
  277               float ixend = sector_size + pad;
  278               if (!loopdirection)
  279                   ixend = pad;
  280               while (ox[0] != ox_end) {
  281                   nextBuffer();
  282                   if (!loopdirection) {
  283                       // If we are in backward playing part of pingpong
  284                       // or reverse loop
  285   
  286                       if (streampos < (loopstart + pad)) {
  287                           ixend = loopstart - streampos + pad2;
  288                           if (ix[0] <= ixend) {
  289                               if ((loopmode & 4) != 0) {
  290                                   // Ping pong loop, change loopdirection
  291                                   loopdirection = true;
  292                                   ixend = sector_size + pad;
  293                                   continue;
  294                               }
  295   
  296                               ix[0] += looplen;
  297                               ixend = pad;
  298                               continue;
  299                           }
  300                       }
  301   
  302                       if (ibuffer_order != loopdirection)
  303                           reverseBuffers();
  304   
  305                       ix[0] = (sector_size + pad2) - ix[0];
  306                       ixend = (sector_size + pad2) - ixend;
  307                       ixend++;
  308   
  309                       float bak_ix = ix[0];
  310                       int bak_ox = ox[0];
  311                       float bak_pitch = current_pitch[0];
  312                       for (int i = 0; i < nrofchannels; i++) {
  313                           if (buffer[i] != null) {
  314                               ix[0] = bak_ix;
  315                               ox[0] = bak_ox;
  316                               current_pitch[0] = bak_pitch;
  317                               interpolate(ibuffer[i], ix, ixend, current_pitch,
  318                                       pitchstep, buffer[i], ox, ox_end);
  319                           }
  320                       }
  321   
  322                       ix[0] = (sector_size + pad2) - ix[0];
  323                       ixend--;
  324                       ixend = (sector_size + pad2) - ixend;
  325   
  326                       if (eof) {
  327                           current_pitch[0] = this.target_pitch;
  328                           return ox[0] - offset;
  329                       }
  330   
  331                       continue;
  332                   }
  333                   if (loopmode != 0) {
  334                       if (streampos + sector_size > (looplen + loopstart + pad)) {
  335                           ixend = loopstart + looplen - streampos + pad2;
  336                           if (ix[0] >= ixend) {
  337                               if ((loopmode & 4) != 0 || (loopmode & 8) != 0) {
  338                                   // Ping pong or revese loop, change loopdirection
  339                                   loopdirection = false;
  340                                   ixend = pad;
  341                                   continue;
  342                               }
  343                               ixend = sector_size + pad;
  344                               ix[0] -= looplen;
  345                               continue;
  346                           }
  347                       }
  348                   }
  349   
  350                   if (ibuffer_order != loopdirection)
  351                       reverseBuffers();
  352   
  353                   float bak_ix = ix[0];
  354                   int bak_ox = ox[0];
  355                   float bak_pitch = current_pitch[0];
  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 SoftResamplerStreamer openStreamer() {
  388           return new ModelAbstractResamplerStream();
  389       }
  390   }

Save This Page
Home » openjdk-7 » com.sun.media » sound » [javadoc | source]