/** * Copyright 2000-2006 DFKI GmbH. * All Rights Reserved. Use is subject to license terms. * * This file is part of MARY TTS. * * 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. * * 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. * * 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 javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.TargetDataLine; import marytts.util.data.BufferedDoubleDataSource; /** * @author Marc Schröder * * */ public class MaryAudioUtils { /** * 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 = (AudioInputStream) audioInputStreams.get(0); else { AudioFormat audioFormat = ((AudioInputStream) 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. * * @param name * name * @return the audio file format type if it is known, or null. */ 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 */ 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 targetFile * name of the sound file * @param millis * the given amount of time in milliseconds * @param audioFormat * the audio format for the actual sound file */ 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 and stop a given wav file. * */ static Clip m_clip; /** * 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). */ 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. */ 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)); } }