Package org.javatari.pc.speaker

Source Code of org.javatari.pc.speaker.Speaker

// Copyright 2011-2012 Paulo Augusto Peccin. See licence.txt distributed with this file.

package org.javatari.pc.speaker;

import java.nio.ByteBuffer;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.SourceDataLine;

import org.javatari.general.av.audio.AudioMonitor;
import org.javatari.general.av.audio.AudioSignal;
import org.javatari.general.board.Clock;
import org.javatari.general.board.ClockDriven;
import org.javatari.parameters.Parameters;


public final class Speaker implements ClockDriven, AudioMonitor  {

  public void connect(AudioSignal signal) {  // Must be powered off to connect a signal
    this.signal = signal;
    signal.connectMonitor(this);
  }

  public void powerOn(){
    if (!triedToGetLine) getLine();
    if (dataLine == null) return;
    dataLine.start();
    clock.go();
  }

  public void powerOff(){
    if (dataLine == null) return;
    clock.pause();
    dataLine.flush();
    dataLine.stop();
  }

  public void destroy() {
    if (dataLine == null) return;
    clock.terminate();
    dataLine.close();
    dataLine = null;
  }

  @Override
  public synchronized int nextSamples(byte[] buffer, int quant) {
    if (dataLine == null) return -1;
    if (buffer == null) {    // Signal is off
      dataLine.flush();
      return -1;
    }
    // Drop samples that don't fit the input buffer available capacity
    int ava = inputBuffer.remaining();
    if (ava > quant)
      ava = quant;
    // else
      // if (ava < quant) System.out.println(">>>> DROPPED: " + quant + " - " + ava + " = " + (quant - ava));
    inputBuffer.put(buffer, 0, ava);

    // System.out.println(">>>> Available: " + inputBuffer.position());
    return inputBuffer.position();
  }
 
  @Override
  public void synchOutput() {
    refresh();
  }

  @Override
  public void clockPulse() {
    synchOutput();
  }

  private void getLine() {
    if (signal == null) return;
    try {
      triedToGetLine = true;
      dataLine = AudioSystem.getSourceDataLine(AUDIO_FORMAT);
      dataLine.open(AUDIO_FORMAT, OUTPUT_BUFFER_SIZE);
      inputBuffer = ByteBuffer.allocateDirect(INPUT_BUFFER_SIZE);
      tempBuffer = new byte[inputBuffer.capacity()];
      if (ADDED_THREAD_PRIORITY != 0) clock.setPriority(Thread.NORM_PRIORITY + ADDED_THREAD_PRIORITY);
      System.out.println("Sound Mixer Line: " + dataLine.getClass().getSimpleName());
      clock = new Clock("Speaker", this, FPS);
    } catch (Exception ex) {
      System.out.println("Unable to acquire audio line:\n" + ex);
      dataLine = null;
    }
  }

  private synchronized int getFromInputBuffer(byte[] buffer, int quant) {
    inputBuffer.flip();
    int ava = inputBuffer.remaining();
    if (ava > quant)
      ava = quant;
    inputBuffer.get(buffer, 0, ava);
    inputBuffer.compact();
    return ava;
  }

  private void refresh() {
    if (dataLine == null) return;
    int ava = dataLine.available();    // this is a little expensive... :-(
   
    // System.out.println(">> Out: " + (OUTPUT_BUFFER_SIZE - ava) + "\tIn: " + inputBuffer.position());
   
    if (ava == 0) {
      // System.out.println("+ OutputBuffer FULL, InputBuffer: " + inputBuffer.position());
      if (OUTPUT_BUFFER_FULL_SLEEP_TIME > 0 && FPS < 0)
        try { Thread.sleep(OUTPUT_BUFFER_FULL_SLEEP_TIME, 0); } catch (InterruptedException e) { }
      return;
    }
    int data = getFromInputBuffer(tempBuffer, ava);
    if (data == 0) {
      // System.out.println("- InputBuffer EMPTY, OutputBuffer: " + (OUTPUT_BUFFER_SIZE - ava));
      if (NO_DATA_SLEEP_TIME > 0 && FPS < 0)
        try { Thread.sleep(NO_DATA_SLEEP_TIME, 0); } catch (InterruptedException e) { }
      return;
    }

    dataLine.write(tempBuffer, 0, data);
    if (FPS < 0)
      try { Thread.sleep(OUTPUT_BUFFER_FULL_SLEEP_TIME, 0); } catch (InterruptedException e) { }
  }


  public Clock clock;
  private AudioSignal signal;
  private SourceDataLine dataLine;
  private ByteBuffer inputBuffer;
  private byte[] tempBuffer;   
  private boolean triedToGetLine = false;
 
  private final AudioFormat AUDIO_FORMAT = new AudioFormat(SAMPLE_RATE, 8, 1, true, false);

  private static final double FPS = Parameters.SPEAKER_DEFAULT_FPS; 
  private static final int SAMPLE_RATE = Parameters.TIA_AUDIO_SAMPLE_RATE;
  private static final int INPUT_BUFFER_SIZE = Parameters.SPEAKER_INPUT_BUFFER_SIZE;              // In frames (samples)
  private static final int OUTPUT_BUFFER_SIZE = Parameters.SPEAKER_OUTPUT_BUFFER_SIZE;            // In frames (samples)
  private static final int OUTPUT_BUFFER_FULL_SLEEP_TIME = Parameters.SPEAKER_OUTPUT_BUFFER_FULL_SLEEP_TIME;  // In milliseconds
  private static final int NO_DATA_SLEEP_TIME = Parameters.SPEAKER_NO_DATA_SLEEP_TIME;            // In milliseconds
  private static final int ADDED_THREAD_PRIORITY = Parameters.SPEAKER_ADDED_THREAD_PRIORITY;

}
TOP

Related Classes of org.javatari.pc.speaker.Speaker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.