示例#1
0
  private void doPlay(AudioFormat decodedFormat, AudioInputStream audioIn) throws Exception {
    byte[] data = new byte[4096];
    SourceDataLine localLine = line;
    if (localLine != null) {
      // Start
      line.start();
      int nBytesRead = 0;
      while (nBytesRead != -1) {
        // if this line was stopped, return to caller who will do cleanup

        // no space to write - busy wait until available - no need to wait if play was stopped i.e.
        // line closed
        while (localLine.available() == 0 && localLine.isOpen()) ;
        if (!localLine.isOpen()) break;
        // how much space is available to write on the line
        // don't read more than that
        int available = localLine.available();

        int maxBytesToRead = (available < data.length) ? available : data.length;

        nBytesRead = audioIn.read(data, 0, maxBytesToRead);
        if (nBytesRead != -1) {
          localLine.write(data, 0, nBytesRead);
        }
      }
      // Stop
      //			stop();
    }
  }
示例#2
0
 SourceDataLine getSourceDataLine(AudioFormat format, int bufferSize) {
   SourceDataLine line = null;
   DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
   if (AudioSystem.isLineSupported(info)) {
     try {
       if (outputMixer == null) {
         line = (SourceDataLine) AudioSystem.getLine(info);
       } else {
         line = (SourceDataLine) outputMixer.getLine(info);
       }
       // remember that time you spent, like, an entire afternoon fussing
       // with this buffer size to try to get the latency decent on Linux?
       // Yah, don't fuss with this anymore, ok?
       line.open(format, bufferSize * format.getFrameSize() * 4);
       if (line.isOpen()) {
         debug(
             "SourceDataLine is "
                 + line.getClass().toString()
                 + "\n"
                 + "Buffer size is "
                 + line.getBufferSize()
                 + " bytes.\n"
                 + "Format is "
                 + line.getFormat().toString()
                 + ".");
         return line;
       }
     } catch (LineUnavailableException e) {
       error("Couldn't open the line: " + e.getMessage());
     }
   }
   error("Unable to return a SourceDataLine: unsupported format - " + format.toString());
   return line;
 }
示例#3
0
 public void updateVolume(int percent) {
   if (out != null && out.isOpen()) {
     try {
       FloatControl c = (FloatControl) out.getControl(FloatControl.Type.MASTER_GAIN);
       float min = c.getMinimum();
       float v = percent * (c.getMaximum() - min) / 100f + min;
       c.setValue(v);
     } catch (IllegalArgumentException e) {
     }
   }
   volume = percent;
 }
示例#4
0
 @Override
 public int onAudioData(byte[] data) {
   if (audioLine != null && audioLine.isOpen()) {
     if (!audioLine.isRunning()) {
       audioLine.start();
     }
     int toWrite = Math.min(audioLine.available(), data.length);
     if (toWrite == audioLine.available())
       log.trace("full! toWrite: " + toWrite + " instead of: " + data.length);
     return audioLine.write(data, 0, toWrite);
   } else {
     return 0;
   }
 }
 /** Inits Audio ressources from AudioSystem.<br> */
 protected void initLine() throws LineUnavailableException {
   log.info("initLine()");
   if (m_line == null) {
     createLine();
   }
   if (!m_line.isOpen()) {
     openLine();
   } else {
     AudioFormat lineAudioFormat = m_line.getFormat();
     AudioFormat audioInputStreamFormat =
         m_audioInputStream == null ? null : m_audioInputStream.getFormat();
     if (!lineAudioFormat.equals(audioInputStreamFormat)) {
       m_line.close();
       openLine();
     }
   }
 }
示例#6
0
 public boolean isOpen() {
   return dataLine.isOpen();
 }
  /** Write the buffer to the SourceDataLine. */
  public int process(Buffer buffer) {

    // if we need to convert the format, do so using the codec.
    if (codec != null) {
      final int codecResult = codec.process(buffer, codecBuffer);
      if (codecResult == BUFFER_PROCESSED_FAILED) return BUFFER_PROCESSED_FAILED;
      if (codecResult == OUTPUT_BUFFER_NOT_FILLED) return BUFFER_PROCESSED_OK;
      buffer = codecBuffer;
    }

    int length = buffer.getLength();
    int offset = buffer.getOffset();

    final Format format = buffer.getFormat();

    final Class type = format.getDataType();
    if (type != Format.byteArray) {
      return BUFFER_PROCESSED_FAILED;
    }

    final byte[] data = (byte[]) buffer.getData();

    final boolean bufferNotConsumed;
    final int newBufferLength; // only applicable if bufferNotConsumed
    final int newBufferOffset; // only applicable if bufferNotConsumed

    if (NON_BLOCKING) {
      // TODO: handle sourceLine.available().  This code currently causes choppy audio.

      if (length > sourceLine.available()) {
        // we should only write sourceLine.available() bytes, then return INPUT_BUFFER_NOT_CONSUMED.
        length = sourceLine.available(); // don't try to write more than available
        bufferNotConsumed = true;
        newBufferLength = buffer.getLength() - length;
        newBufferOffset = buffer.getOffset() + length;

      } else {
        bufferNotConsumed = false;
        newBufferLength = length;
        newBufferOffset = offset;
      }
    } else {
      bufferNotConsumed = false;
      newBufferLength = 0;
      newBufferOffset = 0;
    }

    if (length == 0) {
      logger.finer("Buffer has zero length, flags = " + buffer.getFlags());
    }

    // make sure all the bytes are written.
    while (length > 0) {

      // logger.fine("Available: " + sourceLine.available());
      // logger.fine("length: " + length);
      // logger.fine("sourceLine.getBufferSize(): " + sourceLine.getBufferSize());

      final int n =
          sourceLine.write(
              data, offset, length); // TODO: this can block for a very long time if it doesn't
      if (n >= length) break;
      else if (n == 0) {
        // TODO: we could choose to handle a write failure this way,
        // assuming that it is considered legal to call stop while process is being called.
        // however, that seems like a bad idea in general.
        //				if (!sourceLine.isRunning())
        //				{
        //					buffer.setLength(offset);
        //					buffer.setOffset(length);
        //					return INPUT_BUFFER_NOT_CONSUMED;	// our write was interrupted.
        //				}

        logger.warning(
            "sourceLine.write returned 0, offset="
                + offset
                + "; length="
                + length
                + "; available="
                + sourceLine.available()
                + "; frame size in bytes"
                + sourceLine.getFormat().getFrameSize()
                + "; sourceLine.isActive() = "
                + sourceLine.isActive()
                + "; "
                + sourceLine.isOpen()
                + "; sourceLine.isRunning()="
                + sourceLine.isRunning());
        return BUFFER_PROCESSED_FAILED; // sourceLine.write docs indicate that this will only happen
                                        // if there is an error.

      } else {
        offset += n;
        length -= n;
      }
    }

    if (bufferNotConsumed) {
      // return INPUT_BUFFER_NOT_CONSUMED if not all bytes were written

      buffer.setLength(newBufferLength);
      buffer.setOffset(newBufferOffset);
      return INPUT_BUFFER_NOT_CONSUMED;
    }

    if (buffer.isEOM()) {
      // TODO: the proper way to do this is to implement Drainable, and let the processor call our
      // drain method.
      sourceLine
          .drain(); // we need to ensure that the media finishes playing, otherwise the EOM event
                    // will
      // be posted before the media finishes playing.
    }

    return BUFFER_PROCESSED_OK;
  }