/** * Checks whether the playback and notification configuration share the same device. * * @return are audio out and notifications using the same device. */ public boolean audioOutAndNotificationsShareSameDevice() { AudioSystem audioSystem = getDeviceConfiguration().getAudioSystem(); CaptureDeviceInfo notify = audioSystem.getSelectedDevice(AudioSystem.DataFlow.NOTIFY); CaptureDeviceInfo playback = audioSystem.getSelectedDevice(AudioSystem.DataFlow.PLAYBACK); if (notify == null) return (playback == null); else { if (playback == null) return false; else return notify.getLocator().equals(playback.getLocator()); } }
public boolean load(File file) { this.file = file; if (file != null && file.isFile()) { try { errStr = null; audioInputStream = AudioSystem.getAudioInputStream(file); fileName = file.getName(); format = audioInputStream.getFormat(); } catch (Exception ex) { reportStatus(ex.toString()); return false; } } else { reportStatus("Audio file required."); return false; } numChannels = format.getChannels(); sampleRate = (double) format.getSampleRate(); sampleBitSize = format.getSampleSizeInBits(); long frameLength = audioInputStream.getFrameLength(); long milliseconds = (long) ((frameLength * 1000) / audioInputStream.getFormat().getFrameRate()); double audioFileDuration = milliseconds / 1000.0; if (audioFileDuration > MAX_AUDIO_DURATION) duration = MAX_AUDIO_DURATION; else duration = audioFileDuration; frameLength = (int) Math.floor((duration / audioFileDuration) * (double) frameLength); try { audioBytes = new byte[(int) frameLength * format.getFrameSize()]; audioInputStream.read(audioBytes); } catch (Exception ex) { reportStatus(ex.toString()); return false; } getAudioData(); return true; }
public boolean play() { try { if (playState != STOPPED) playStop(); if (audioBytes == null) return false; DataLine.Info info = new DataLine.Info(Clip.class, format); clip = (Clip) AudioSystem.getLine(info); clip.addLineListener(new ClipListener()); long clipStart = (long) (audioBytes.length * getStartTime() / (getDuration() * 1000.0)); long clipEnd = (long) (audioBytes.length * getEndTime() / (getDuration() * 1000.0)); if ((clipEnd - clipStart) > MAX_CLIP_LENGTH) clipEnd = clipStart + MAX_CLIP_LENGTH; byte[] clipBytes = new byte[(int) (clipEnd - clipStart)]; System.arraycopy(audioBytes, (int) clipStart, clipBytes, 0, clipBytes.length); clip.open(format, clipBytes, 0, clipBytes.length); FloatControl panControl = (FloatControl) clip.getControl(FloatControl.Type.PAN); panControl.setValue((float) panSetting / 100.0f); double value = (double) gainSetting; FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); float dB = (float) (Math.log(value == 0.0 ? 0.0001 : value) / Math.log(10.0) * 20.0); gainControl.setValue(dB); double playStartTime = (player.getSeekTime() / 100) * (playGetLength()); clip.setMicrosecondPosition((long) playStartTime); clip.start(); playState = PLAYING; return true; } catch (Exception ex) { ex.printStackTrace(); playState = STOPPED; clip = null; return false; } }
/** * Creates an SCAudioClip from the given URI and adds it to the list of available audio-s. * * @param uri the path where the audio file could be found * @param playback use or not the playback device. * @return a newly created <tt>SCAudioClip</tt> from <tt>uri</tt> */ public SCAudioClip createAudio(String uri, boolean playback) { SCAudioClip audio; synchronized (audiosSyncRoot) { final AudioKey key = new AudioKey(uri, playback); /* * While we want to reuse the SCAudioClip instances, they may be * used by a single user at a time. That's why we'll forget about * them while they are in use and we'll reclaim them when they are * no longer in use. */ audio = (audios == null) ? null : audios.remove(key); if (audio == null) { try { AudioSystem audioSystem = getDeviceConfiguration().getAudioSystem(); if (audioSystem == null) { audio = new JavaSoundClipImpl(uri, this); } else if (NoneAudioSystem.LOCATOR_PROTOCOL.equalsIgnoreCase( audioSystem.getLocatorProtocol())) { audio = null; } else { audio = new AudioSystemClipImpl(uri, this, audioSystem, playback); } } catch (Throwable t) { if (t instanceof ThreadDeath) throw (ThreadDeath) t; else { /* * Could not initialize a new SCAudioClip instance to be * played. */ return null; } } } /* * Make sure that the SCAudioClip will be reclaimed for reuse when * it is no longer in use. */ if (audio != null) { if (audios == null) audios = new HashMap<AudioKey, SCAudioClip>(); /* * We have to return in the Map which was active at the time the * SCAudioClip was initialized because it may have become * invalid if the playback or notify audio device changed. */ final Map<AudioKey, SCAudioClip> finalAudios = audios; final SCAudioClip finalAudio = audio; audio = new SCAudioClip() { /** * Evaluates a specific <tt>loopCondition</tt> as defined by {@link * SCAudioClip#play(int,Callable)}. * * @param loopCondition the <tt>Callable<Boolean></tt> which represents the * <tt>loopCondition</tt> to be evaluated * @return {@link Boolean#FALSE} if <tt>loopCondition</tt> is <tt>null</tt>; * otherwise, the value returned by invoking {@link Callable#call()} on the * specified <tt>loopCondition</tt> * @throws Exception if the specified <tt>loopCondition</tt> throws an * <tt>Exception</tt> */ private Boolean evaluateLoopCondition(Callable<Boolean> loopCondition) throws Exception { /* * SCAudioClip.play(int,Callable<Boolean>) is * documented to play the SCAudioClip once only if * the loopCondition is null. The same will be * accomplished by returning Boolean.FALSE. */ return (loopCondition == null) ? Boolean.FALSE : loopCondition.call(); } /** * {@inheritDoc} * * <p>Returns the wrapped <tt>SCAudioClip</tt> into the cache from it has earlier been * retrieved in order to allow its reuse. */ @Override protected void finalize() throws Throwable { try { synchronized (audios) { finalAudios.put(key, finalAudio); } } finally { super.finalize(); } } public void play() { /* * SCAudioClip.play() is documented to behave as if * loopInterval is negative and/or loopCondition is * null. We have to take care that this instance * does not get garbage collected until the * finalAudio finishes playing so we will delegate * to this instance's implementation of * SCAudioClip.play(int,Callable<Boolean>) instead * of to the finalAudio's. */ play(-1, null); } public void play(int loopInterval, final Callable<Boolean> finalLoopCondition) { /* * We have to make sure that this instance does not * get garbage collected before the finalAudio * finishes playing. The argument loopCondition of * the method * SCAudioClip.play(int,Callable<Boolean>) will * live/be referenced during that time so we will * use it to hold on to this instance. */ Callable<Boolean> loopCondition = new Callable<Boolean>() { public Boolean call() throws Exception { return evaluateLoopCondition(finalLoopCondition); } }; finalAudio.play(loopInterval, loopCondition); } public void stop() { finalAudio.stop(); } /** * Determines whether this audio is started i.e. a <tt>play</tt> method was invoked * and no subsequent <tt>stop</tt> has been invoked yet. * * @return <tt>true</tt> if this audio is started; otherwise, <tt>false</tt> */ public boolean isStarted() { return finalAudio.isStarted(); } }; } } return audio; }