/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.googlecode.eckoit.audio; import com.googlecode.eckoit.events.RecordingSplitEvent; import com.googlecode.eckoit.util.Slugger; import java.io.IOException; import java.io.File; import java.util.Timer; import java.util.TimerTask; import javax.sound.sampled.DataLine; import javax.sound.sampled.TargetDataLine; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.Mixer; import org.bushe.swing.event.EventBus; /** * * @author ryan */ public class SplitAudioRecorder implements AudioRecorder { private static long splitTime = 10000L; // 10 seconds private static SplitAudioRecorder singletonObject; private boolean isRecording = false; private long recordingStart; private TargetDataLine m_line; private AudioFileFormat.Type m_targetType; private SplitableAudioInputStream m_audioInputStream; private File m_outputFile; private Timer timer; private int sectionCount; private static File root; private File recordingFolder; private File section; private static SplitAudioRecorderConfiguration config = new SplitAudioRecorderConfiguration(); private String recordingID; public static void setSplitTime(long splitTime) { SplitAudioRecorder.splitTime = splitTime; } public static long getSplitTime() { return splitTime; } public static void setConfig(SplitAudioRecorderConfiguration configSetup) { config = configSetup; } public static void setRoot(File dir) { root = dir; if (!root.isDirectory()) { throw new RuntimeException("A directory is expected"); } } @Override public synchronized void startRecording(String recordingID, final String mixer, float gain) throws LineUnavailableException { if (isRecording || m_line != null || (m_line != null && m_line.isOpen())) { throw new LineUnavailableException(); } String safeFileName = Slugger.generateSlug(recordingID); recordingFolder = new File(root, safeFileName); recordingFolder.mkdirs(); sectionCount = 0; isRecording = true; recordingStart = System.currentTimeMillis(); this.recordingID = recordingID; section = nextSectionFile(); AudioFormat audioFormat = new AudioFormat(config.getWavSampleRate(), config.getWavSampleSize(), 1, true, true); audioFormat = SimpleAudioRecorder.getBestAudioFormat(audioFormat, mixer); DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat); Mixer selectedMixer = SimpleAudioRecorder.getSelectedMixer(mixer); if (selectedMixer == null) { m_line = (TargetDataLine) AudioSystem.getLine(info); selectedMixer = AudioSystem.getMixer(null); } else { m_line = (TargetDataLine) selectedMixer.getLine(info); } m_line.open(audioFormat); //FloatControl fc = (FloatControl) selectedMixer.getControl(FloatControl.Type.MASTER_GAIN); //System.out.println("Master Gain min: " + fc.getMinimum()); //System.out.println("Master Gain min: " + fc.getMaximum()); //ystem.out.println("Master Gain cur: " + fc.getValue()); //fc.setValue(MIN_PRIORITY); AudioFileFormat.Type targetType = AudioFileFormat.Type.WAVE; m_audioInputStream = new SplitableAudioInputStream(new AudioInputStream(m_line)); m_targetType = targetType; m_outputFile = section; new Recorder().start(); timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { sectionCount++; File oldsection = section; section = nextSectionFile(); split(oldsection, section); } }, splitTime, splitTime); } private File nextSectionFile() { return new File(recordingFolder, sectionCount + ".wav"); } private void split(File oldsection, File newsectiom) { m_outputFile = newsectiom; m_audioInputStream = m_audioInputStream.clone(); new Recorder().start(); long splitStartTime = System.currentTimeMillis() - splitTime; EventBus.publish(new RecordingSplitEvent(oldsection, recordingID, splitStartTime)); } /** Stops the recording. */ @Override public synchronized long stopRecording() { if (isRecording) { m_line.stop(); m_line.close(); m_line = null; timer.cancel(); isRecording = false; long now = System.currentTimeMillis(); // final section long splitStartTime = now - splitTime; RecordingSplitEvent rse = new RecordingSplitEvent(section, recordingID, splitStartTime); rse.setIsFinal(true); EventBus.publish(rse); return (now - recordingStart)/1000; } return -1; } @Override public boolean isRecording() { return isRecording; } private SplitAudioRecorder() { } public static synchronized SplitAudioRecorder getSingletonObject() { if (singletonObject == null) { singletonObject = new SplitAudioRecorder(); } return singletonObject; } private class Recorder extends Thread { @Override public void run() { try { AudioSystem.write(m_audioInputStream, m_targetType, m_outputFile); } catch (IOException e) { e.printStackTrace(); } } /** Starts the recording. To accomplish this, (i) the line is started and (ii) the thread is started. */ @Override public void start() { m_line.start(); super.start(); } } @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } }