content: /**
   * Copyright 2007 DFKI GmbH.
   * All Rights Reserved.  Use is subject to license terms.
   * <p/>
   * This file is part of MARY TTS.
   * <p/>
   * MARY TTS is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as published by
   * the Free Software Foundation, version 3 of the License.
   * <p/>
   * 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 Lesser General Public License for more details.
   * <p/>
   * You should have received a copy of the GNU Lesser General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package marytts.signalproc.filter;
  
  import java.io.File;
  import java.io.IOException;
  import java.util.Arrays;
  
  import lib.sound.sampled.AudioFileFormat;
  import lib.sound.sampled.AudioFormat;
  import lib.sound.sampled.AudioInputStream;
  import lib.sound.sampled.AudioSystem;
  import lib.sound.sampled.UnsupportedAudioFileException;
  import marytts.util.data.BufferedDoubleDataSource;
  import marytts.util.data.audio.AudioDoubleDataSource;
  import marytts.util.data.audio.DDSAudioInputStream;
  import marytts.util.signal.SignalProcUtils;
  
  /**
   * @author Oytun T&uumlrk
   */
  public class FIRWaveletFilterBankAnalyser extends FilterBankAnalyserBase {
      public FIRFilter[][] filters;
      public double[][] normalizationFilterTransformedIRs;
      public int numLevels;
      double samplingRateInHz;
      double[] samplingRates;
  
      public FIRWaveletFilterBankAnalyser(int numLevelsIn, double samplingRateInHzIn) {
          numLevels = Math.max(0, numLevelsIn);
  
          samplingRateInHz = samplingRateInHzIn;
          int i, j;
  
          samplingRates = new double[numLevels + 1];
  
          samplingRates[0] = 0.5 * samplingRateInHz;
          for (i = 1; i < numLevels; i++)
              samplingRates[i] = 0.5 * samplingRates[i - 1];
          samplingRates[numLevels] = samplingRates[numLevels - 1];
  
          int filterOrder;
          int maxFreq;
          filters = new FIRFilter[numLevels][2];
          normalizationFilterTransformedIRs = new double[numLevels][];
          for (i = 0; i < numLevels; i++) {
              filterOrder = SignalProcUtils.getFIRFilterOrder((int) (samplingRates[i]));
              filters[i][0] = new LowPassFilter(0.25, filterOrder);
              filters[i][1] = new HighPassFilter(0.25, filterOrder);
  
              maxFreq = filters[i][0].transformedIR.length / 2 + 1;
              normalizationFilterTransformedIRs[i] = new double[maxFreq];
  
              Arrays.fill(normalizationFilterTransformedIRs[i], 0.0);
  
              normalizationFilterTransformedIRs[i][0] += Math.abs(filters[i][0].transformedIR[0]);
              normalizationFilterTransformedIRs[i][0] += Math.abs(filters[i][1].transformedIR[0]);
              normalizationFilterTransformedIRs[i][maxFreq - 1] += Math.abs(filters[i][0].transformedIR[1]);
              normalizationFilterTransformedIRs[i][maxFreq - 1] += Math.abs(filters[i][1].transformedIR[1]);
              for (j = 1; j < maxFreq - 1; j++) {
                  normalizationFilterTransformedIRs[i][j] += Math.sqrt(filters[i][0].transformedIR[2 * j] * filters[i][0].transformedIR[2 * j] + filters[i][0].transformedIR[2 * j + 1] * filters[i][0].transformedIR[2 * j + 1]);
                  normalizationFilterTransformedIRs[i][j] += Math.sqrt(filters[i][1].transformedIR[2 * j] * filters[i][1].transformedIR[2 * j] + filters[i][1].transformedIR[2 * j + 1] * filters[i][1].transformedIR[2 * j + 1]);
              }
  
              for (j = 0; j < maxFreq; j++)
                  normalizationFilterTransformedIRs[i][j] = 1.0 / normalizationFilterTransformedIRs[i][j];
          }
      }
  
      public static void main(String[] args) throws UnsupportedAudioFileException, IOException {
          AudioInputStream inputAudio = AudioSystem.getAudioInputStream(new File(args[0]));
          int samplingRate = (int) inputAudio.getFormat().getSampleRate();
          AudioDoubleDataSource signal = new AudioDoubleDataSource(inputAudio);
          double[] x = signal.getAllData();
  
          int i;
          int numLevels = 1;
  
          FIRWaveletFilterBankAnalyser analyser = new FIRWaveletFilterBankAnalyser(numLevels, samplingRate);
          Subband[] subbands = analyser.apply(x);
  
          DDSAudioInputStream outputAudio;
          AudioFormat outputFormat;
          String outFileName;
  
          //Write highpass components 0 to numLevels-1
          for (i = 0; i < subbands.length; i++) {
              outputFormat = new AudioFormat((int) (subbands[i].samplingRate), inputAudio.getFormat().getSampleSizeInBits(), inputAudio.getFormat().getChannels(), true, true);
              outputAudio = new DDSAudioInputStream(new BufferedDoubleDataSource(subbands[i].waveform), outputFormat);
              outFileName = args[0].substring(0, args[0].length() - 4) + "_band" + String.valueOf(i + 1) + ".wav";
              AudioSystem.write(outputAudio, AudioFileFormat.Type.WAVE, new File(outFileName));
          }
      }
  
      @Override
      public Subband[] apply(double[] x) {
          Subband[] subbands = null;
  
          if (filters != null && x != null && numLevels >= 0) {
              int i;
              subbands = new Subband[numLevels + 1];
              double[] lowBand = null;
              double[] highBand = null;
  
              int count = 0;
              for (i = 0; i < numLevels; i++) {
                  if (i == 0) {
                      lowBand = filters[i][0].apply(x);
                      lowBand = SignalProcUtils.decimate(lowBand, 2.0);
  
                      highBand = filters[i][1].apply(x);
                      highBand = SignalProcUtils.decimate(highBand, 2.0);
                  } else {
                      highBand = filters[i][1].apply(lowBand);
                      highBand = SignalProcUtils.decimate(highBand, 2.0);
  
                      lowBand = filters[i][0].apply(lowBand);
                      lowBand = SignalProcUtils.decimate(lowBand, 2.0);
                  }
  
                  subbands[i] = new Subband(highBand, samplingRates[i]);
              }
  
              subbands[numLevels] = new Subband(lowBand, samplingRates[numLevels]);
          }
          //
  
          return subbands;
      }
  }
  
  