package envoy.client.data.audio; import java.io.IOException; import java.nio.file.*; import javax.sound.sampled.*; import envoy.exception.EnvoyException; /** * Records audio and exports it as a byte array. * * @author Kai S. K. Engelbart * @since Envoy Client v0.1-beta */ public final class AudioRecorder { /** * The default audio format used for recording and play back. * * @since Envoy Client v0.1-beta */ public static final AudioFormat DEFAULT_AUDIO_FORMAT = new AudioFormat(16000, 16, 1, true, false); /** * The format in which audio files will be saved. */ public static final String FILE_FORMAT = "wav"; private final AudioFormat format; private final DataLine.Info info; private TargetDataLine line; private Path tempFile; /** * Initializes the recorder with the default audio format. * * @since Envoy Client v0.1-beta */ public AudioRecorder() { this(DEFAULT_AUDIO_FORMAT); } /** * Initializes the recorder with a given audio format. * * @param format the audio format to use * @since Envoy Client v0.1-beta */ public AudioRecorder(AudioFormat format) { this.format = format; info = new DataLine.Info(TargetDataLine.class, format); } /** * @return {@code true} if audio recording is supported * @since Envoy Client v0.1-beta */ public boolean isSupported() { return AudioSystem.isLineSupported(info); } /** * @return {@code true} if the recorder is active * @since Envoy Client v0.1-beta */ public boolean isRecording() { return line != null && line.isActive(); } /** * Starts the audio recording. * * @throws EnvoyException if starting the recording failed * @since Envoy Client v0.1-beta */ public void start() throws EnvoyException { try { // Open the line line = (TargetDataLine) AudioSystem.getLine(info); line.open(format); line.start(); // Prepare temp file tempFile = Files.createTempFile("recording", FILE_FORMAT); // Start the recording final var ais = new AudioInputStream(line); AudioSystem.write(ais, AudioFileFormat.Type.WAVE, tempFile.toFile()); } catch (IOException | LineUnavailableException e) { throw new EnvoyException("Cannot record voice", e); } } /** * Stops the recording. * * @return the finished recording * @throws EnvoyException if finishing the recording failed * @since Envoy Client v0.1-beta */ public byte[] finish() throws EnvoyException { try { line.stop(); line.close(); final byte[] data = Files.readAllBytes(tempFile); Files.delete(tempFile); return data; } catch (final IOException e) { throw new EnvoyException("Cannot save voice recording", e); } } /** * Cancels the active recording. * * @since Envoy Client v0.1-beta */ public void cancel() { line.stop(); line.close(); try { Files.deleteIfExists(tempFile); } catch (final IOException e) {} } }