示例#1
0
  /**
   * Writes the given samples to the file.
   *
   * <p>Note: this function is non-blocking and can be called from within the process tread.
   *
   * @param startSample the file-position of the first sample. If the position larger than the
   *     number of samples written so far, the gap will be filled with null samples.
   * @param audioArray the data to be written to file.
   */
  public void putNext(int startSample, float[] audioArray) {
    synchronized (processingLock) {
      if (!started) {
        return;
      }
      if (startSample < samplesDelivered) {
        Arrays.fill(audioArray, 0.0F);
        logger.severe("\"startSample\" already delivered.");
        return;
      }
      samplesDelivered = startSample + audioArray.length;

      if (currentBufferProvider == null) {
        logger.severe("Current buffer is null.");
        return;
      }
      if (!currentBufferProvider.isDone()) {
        logger.warning("File buffer not ready.");
        overflowCount++;
        return;
      }
      SyncBuffer currentBuffer;
      try {
        FileWriteTaskResult result = currentBufferProvider.get();
        currentBuffer = result.getbuffer();
      } catch (InterruptedException | ExecutionException ex) {
        logger.log(Level.SEVERE, null, ex);
        return;
      }
      FloatBuffer currentFloatBuffer = currentBuffer.asFloatBuffer();

      int offset = startSample - samplesProcessed;
      int toBeWritten = offset + audioArray.length;

      // Do we need to write samples to the next buffer?
      int remainingSpace = currentFloatBuffer.remaining();
      if (remainingSpace < toBeWritten) {
        switchBuffers(offset, audioArray, currentBuffer);
        return;
      }

      // Now we have checked all special conditions... we can proceed to the normal work.
      // 1) Pad with null samples.
      for (int i = 0; i < offset; i++) {
        currentFloatBuffer.put(0F);
      }
      // 2) append the audioArray
      currentFloatBuffer.put(audioArray);
      samplesProcessed = startSample + audioArray.length;
    }
  }
示例#2
0
  /**
   * Stops writing and starts to close the output file.
   *
   * <p>Note: this function is non-blocking and can be called from within the process tread.
   */
  public WriterResult stop() {
    synchronized (processingLock) {
      if (!started) {
        throw new RuntimeException("Attempt to stop altough not started.");
      }
      startBuffer.flipFloats();

      Future<FileChannel> readerChannel = null;
      FileChannel channel = null;

      if (startBufferDone) {
        // wait for the bussyBufferProvider to terminate streaming.
        // ToDo: this ought to be done inside LastFileWriteTask (beware of possible deadlocks)
        if (bussyBufferProvider != null) {
          if (!bussyBufferProvider.isDone()) {
            logger.warning("Waiting for a previous buffer to be streamed.");
            overflowCount++;
          }
          try {
            channel = bussyBufferProvider.get().getChannel();
          } catch (InterruptedException | ExecutionException ex) {
            logger.log(Level.SEVERE, null, ex);
          }
        }
        FileWriteTaskResult result = null;
        try {
          result = currentBufferProvider.get();
        } catch (InterruptedException | ExecutionException ex) {
          logger.log(Level.SEVERE, null, ex);
        }
        if (result != null) {
          SyncBuffer buffer = result.getbuffer();
          LastFileWriteTask lastFileWriteTask = new LastFileWriteTask(outputFile, channel, buffer);
          readerChannel = executor.submit(lastFileWriteTask);
        }
      }

      WriterResult result = new WriterResult(startBuffer, readerChannel, samplesProcessed);
      currentBufferProvider = null;
      bussyBufferProvider = null;
      startBuffer = null;
      started = false;
      return result;
    }
  }
示例#3
0
  private void switchBuffers(int offset, float[] audioArray, SyncBuffer oldBuffer) {
    int toBePadded = offset;
    FloatBuffer oldFloatBuffer = oldBuffer.asFloatBuffer();
    // 1) use the remaining space in the current buffer
    // ...pad the current buffer as much as fits.
    while ((toBePadded > 0) && (oldFloatBuffer.hasRemaining())) {
      oldFloatBuffer.put(0F);
      toBePadded--;
      samplesProcessed++;
    }

    // ...put as much as fits from the audioArray
    int audioArrayWrittenToOld = 0;
    if (oldFloatBuffer.hasRemaining() && toBePadded == 0) {
      audioArrayWrittenToOld = oldFloatBuffer.remaining();
      oldFloatBuffer.put(audioArray, 0, audioArrayWrittenToOld);
      samplesProcessed += audioArrayWrittenToOld;
    }

    // 2) put the rest in a new buffer
    if (!startBufferDone) {
      // setup the first file buffer
      bussyBufferProvider = new AlwaysStreamedBuffer(new SyncBuffer(requestedFileBufferSizeFloat));
    } else {
      if (!firstFileBufferDone) {
        // setup the second file buffer
        bussyBufferProvider =
            new AlwaysStreamedBuffer(new SyncBuffer(requestedFileBufferSizeFloat));
      }
    }

    if (bussyBufferProvider == null) {
      logger.severe("Next buffer is null!!");
      return;
    }
    if (!bussyBufferProvider.isDone()) {
      logger.warning("Next buffer not ready.");
      overflowCount++;
      return;
    }
    SyncBuffer newBuffer;
    FileChannel channel;
    try {
      FileWriteTaskResult result = bussyBufferProvider.get();
      newBuffer = result.getbuffer();
      channel = result.getChannel();
    } catch (InterruptedException | ExecutionException ex) {
      logger.log(Level.SEVERE, null, ex);
      return;
    }
    FloatBuffer newFloatBuffer = newBuffer.asFloatBuffer();
    //

    int remainingInNewBuffer = newFloatBuffer.remaining();
    int toBeWrittenToNew = toBePadded + audioArray.length - audioArrayWrittenToOld;
    if (toBeWrittenToNew > remainingInNewBuffer) {
      logger.severe("File buffer too small for this offset.");
    } else {
      for (int i = 0; i < toBePadded; i++) {
        newFloatBuffer.put(0F);
        samplesProcessed++;
      }
      int restAudioArray = audioArray.length - audioArrayWrittenToOld;
      newFloatBuffer.put(audioArray, audioArrayWrittenToOld, restAudioArray);
      samplesProcessed += restAudioArray;
    }

    if (startBufferDone) {
      FileWriteTask fileWriteTask = new FileWriteTask(outputFile, channel, oldBuffer);
      currentBufferProvider = bussyBufferProvider;
      bussyBufferProvider = executor.submit(fileWriteTask);
      firstFileBufferDone = true;
    } else {
      // we just have processed the first buffer:
      currentBufferProvider = bussyBufferProvider;
      bussyBufferProvider = null;
      startBufferDone = true;
    }
  }