001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io.audio;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.GraphicsEnvironment;
007import java.io.File;
008import java.io.IOException;
009import java.net.URL;
010
011import javax.sound.sampled.AudioFormat;
012import javax.sound.sampled.AudioInputStream;
013import javax.sound.sampled.AudioSystem;
014import javax.sound.sampled.UnsupportedAudioFileException;
015import javax.swing.JOptionPane;
016
017import org.openstreetmap.josm.Main;
018import org.openstreetmap.josm.spi.preferences.Config;
019import org.openstreetmap.josm.tools.Logging;
020
021/**
022 * Utils functions for audio.
023 *
024 * @author David Earl <david@frankieandshadow.com>
025 * @since 12326 (move to new package)
026 * @since 1462
027 */
028public final class AudioUtil {
029
030    private AudioUtil() {
031        // Hide default constructor for utils classes
032    }
033
034    /**
035     * Returns calibrated length of recording in seconds.
036     * @param wavFile the recording file (WAV format)
037     * @return the calibrated length of recording in seconds.
038     */
039    public static double getCalibratedDuration(File wavFile) {
040        try (AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(
041                new URL("file:".concat(wavFile.getAbsolutePath())))) {
042            AudioFormat audioFormat = audioInputStream.getFormat();
043            long filesize = wavFile.length();
044            double bytesPerSecond = audioFormat.getFrameRate() /* frames per second */
045                * audioFormat.getFrameSize() /* bytes per frame */;
046            double naturalLength = filesize / bytesPerSecond;
047            double calibration = Config.getPref().getDouble("audio.calibration", 1.0 /* default, ratio */);
048            return naturalLength / calibration;
049        } catch (UnsupportedAudioFileException | IOException e) {
050            Logging.debug(e);
051            return 0.0;
052        }
053    }
054
055    /**
056     * Shows a popup audio error message for the given exception.
057     * @param ex The exception used as error reason. Cannot be {@code null}.
058     * @since 12328
059     */
060    public static void audioMalfunction(Exception ex) {
061        String msg = ex.getMessage();
062        if (msg == null)
063            msg = tr("unspecified reason");
064        else
065            msg = tr(msg);
066        Logging.error(msg);
067        if (!GraphicsEnvironment.isHeadless()) {
068            JOptionPane.showMessageDialog(Main.parent,
069                    "<html><p>" + msg + "</p></html>",
070                    tr("Error playing sound"), JOptionPane.ERROR_MESSAGE);
071        }
072    }
073}