content: /**
   * Copyright 2000-2006 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.util.data.audio;
  
  import java.io.File;
  import java.io.IOException;
  import java.util.Vector;
  
  import lib.sound.sampled.AudioFileFormat;
  import lib.sound.sampled.AudioFormat;
  import lib.sound.sampled.AudioInputStream;
  import lib.sound.sampled.AudioSystem;
  import lib.sound.sampled.Clip;
  import lib.sound.sampled.DataLine;
  import lib.sound.sampled.LineUnavailableException;
  import lib.sound.sampled.TargetDataLine;
  import marytts.util.data.BufferedDoubleDataSource;
  
  
  /**
   * @author Marc Schr&ouml;der
   */
  public class MaryAudioUtils {
  
      /**
       * Play back and stop a given wav file.
       */
      static Clip m_clip;
  
      /**
       * Create a single AudioInputStream from a vector of AudioInputStreams.
       * The AudioInputStreams are expected to have the same AudioFormat.
       *
       * @param audioInputStreams a vector containing one or more AudioInputStreams.
       * @return a single AudioInputStream
       * @throws NullPointerException     if any of the arguments are null
       * @throws IllegalArgumentException if the vector contains no elements,
       *                                  any element is not an AudioInputStream.
       */
      public static AudioInputStream createSingleAudioInputStream(Vector<AudioInputStream> audioInputStreams) {
          if (audioInputStreams == null)
              throw new NullPointerException("Received null vector of AudioInputStreams");
          if (audioInputStreams.isEmpty())
              throw new IllegalArgumentException("Received empty vector of AudioInputStreams");
          AudioInputStream singleStream;
          if (audioInputStreams.size() == 1)
              singleStream = audioInputStreams.get(0);
          else {
              AudioFormat audioFormat =
                      audioInputStreams.get(0).getFormat();
              singleStream =
                      new SequenceAudioInputStream(audioFormat, audioInputStreams);
          }
          return singleStream;
      }
  
      /*
       * Return an audio file format type for the given string.
       * In addition to the built-in types, this can deal with MP3
       * supported by tritonus.
       * @return the audio file format type if it is known, or null.
       * @see MaryServerUtils#canCreateMP3()
       * @see MaryServerUtils#canCreateOgg()
       */
      public static AudioFileFormat.Type getAudioFileFormatType(String name) {
          AudioFileFormat.Type at;
          if (name.equals("MP3")) {
              // Supported by tritonus plugin
              at = new AudioFileFormat.Type("MP3", "mp3");
          } else if (name.equals("Vorbis")) {
              // supported by tritonus plugin
              at = new AudioFileFormat.Type("Vorbis", "ogg");
          } else {
              try {
                  at = (AudioFileFormat.Type) AudioFileFormat.Type.class.getField(name).get(null);
              } catch (Exception e) {
                  return null;
              }
          }
  
          return at;
      }
  
      /**
       * Record a sound file with the recording being limited to a given amount of time
       *
       * @param filename    name of the sound file
       * @param millis      the given amount of time in milliseconds
       * @param audioFormat the audio format for the actual sound file
       * @return void
       * @throws LineUnavailableException if no recording line can be found
       * @throws InterruptedException     if the recording is stopped
       */
      public static void timedRecord(String filename, long millis, AudioFormat audioFormat) {
          /*
           * Our first parameter tells us the file name that the recording
      	 * should be saved into.
      	 */
          File outputFile = new File(filename);
          timedRecord(outputFile, millis, audioFormat);
      }
  
      /*
       * Record a sound file with the recording being limited to a given amount of time
       * @param filename name of the sound file
       * @param millis the given amount of time in milliseconds
       * @param audioFormat the audio format for the actual sound file
       * @throws LineUnavailableException if no recording line can be found
       * @throws InterruptedException if the recording is stopped
       *
       */
      public static void timedRecord(File targetFile, long millis, AudioFormat audioFormat) {
          /*
           * Now, we are trying to get a TargetDataLine. The TargetDataLine is
      	 * used later to read audio data from it. If requesting the line was
      	 * successful, we are opening it (important!).
      	 */
          DataLine.Info info = new DataLine.Info(TargetDataLine.class,
                  audioFormat);
          TargetDataLine targetDataLine = null;
          try {
              targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
              targetDataLine.open(audioFormat);
          } catch (LineUnavailableException e) {
              System.err.println("unable to get a recording line");
              e.printStackTrace();
              //System.exit(1);
          }
  
      	/*
           * Again for simplicity, we've hardcoded the audio file type, too.
      	 */
          AudioFileFormat.Type targetType = AudioFileFormat.Type.WAVE;
  
          AudioRecorder.BufferingRecorder recorder = new AudioRecorder.BufferingRecorder(targetDataLine, targetType, targetFile, (int) millis);
  
      	/*
           * Here, the recording is actually started.
      	 */
          recorder.start();
          System.out.println("Recording...");
  
          try {
              recorder.join();
          } catch (InterruptedException ie) {
          }
          System.out.println("Recording stopped.");
  
      	/*
      	 * Here, our recording should actually be done and all wrapped up.
      	 *
      	 */
  
      }
  
      /**
       * Play back a file loop times (0 = only once). Play in the background, non-blocking.
       *
       * @param filename name of the wav file
       * @param loop     number of times the file should be repeated (0 = play only once).
       * @throws IOException,LineUnavailableException
       */
      public static void playWavFile(String filename, int loop) {
          playWavFile(filename, loop, false);
      }
  
      /**
       * Play back a file loop times (0 = only once). Play in the background, non-blocking.
       *
       * @param filename           name of the wav file
       * @param loop               number of times the file should be repeated (0 = play only once).
       * @param waitUntilCompleted whether or not to wait until the file has finished playing before returning.
       * @throws IOException,LineUnavailableException
       */
      public static void playWavFile(String filename, int loop, boolean waitUntilCompleted) {
          AudioInputStream audioInputStream = null;
          File clipFile = new File(filename);
  
          try {
              audioInputStream = AudioSystem.getAudioInputStream(clipFile);
          } catch (Exception e) {
              e.printStackTrace();
          }
          if (audioInputStream != null) {
              AudioFormat format = audioInputStream.getFormat();
              DataLine.Info info = new DataLine.Info(Clip.class, format);
              try {
                  m_clip = (Clip) AudioSystem.getLine(info);
                  m_clip.open(audioInputStream);
              } catch (LineUnavailableException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
              m_clip.loop(loop);
              if (waitUntilCompleted)
                  m_clip.drain();
          } else {
              System.out.println("playWavFile<init>(): can't get data from file " + clipFile.getName());
          }
  
      }
  
      /**
       * Stop wav play back
       */
      public static void stopWavFile() {
          m_clip.stop();
          m_clip.flush();
          m_clip.close();
      }
  
      public static double[] getSamplesAsDoubleArray(AudioInputStream ais) {
          return new AudioDoubleDataSource(ais).getAllData();
      }
  
      public static void writeWavFile(double[] x, String outputFile, AudioFormat format) throws IOException {
          DDSAudioInputStream outputAudio = new DDSAudioInputStream(new BufferedDoubleDataSource(x), format);
  
          AudioSystem.write(outputAudio, AudioFileFormat.Type.WAVE, new File(outputFile));
      }
  }
  
  