Safely and Quickly Trim a Byte Array of Audio in Java

Posted on

Problem

I’m trying to take a raw byte array of audio and trim it.

The user selects a start and end value using a range slider.

// args are doubles from 0.0 - 1.0
// audio is uncompressed, 16-bit, 44,100hz, MONO
public static byte[] trimBytes(byte[] fullLength, double from, double to) {

    int startingByteIndex = (int) ((double) fullLength.length * from);

    // samples/frames are two bytes long, so...
    // we make sure we don't include half a sample (corrupt audio)
    if (startingByteIndex %2 != 0) {
        startingByteIndex ++; // use plus, because minus could overflow
    }

    int endingByteIndex = (int) ((double) fullLength.length * to);
    int finalByteArrayLength = endingByteIndex - startingByteIndex;

    // make sure we don't include half a sample (corrupt audio)
    if (finalByteArrayLength %2 != 0) {
        finalByteArrayLength --; // use minus because plus could overflow
    }

    byte[] result = new byte[finalByteArrayLength];

    for (int i=0; i<finalByteArrayLength; i++) {
        int indexToCopy = startingByteIndex + i;
        result[i] = fullLength[indexToCopy];
    }
    return result;
}

Is this going to crash for any reason or is there a better way to do this?

Note: I cannot use Java.nio.

Solution

0.0 – 1.0, Is this going to crash for any reason?

As you don’t check, there’s an ArrayIndexOutOfBoundsException that could be turned into an IllegalArgumentException.

is there a better way to do this?

  • Avoid copying altogether:
    Use java.nio.ByteBuffer.slice()
  • Don’t open code what the JRE provides:
    Use java.util.Arrays.copyOfRange(byte[] original, int from, int to)

    final double halfLength = fullLength.length / 2.0;
    Arrays.copyOfRange(fullLength,
        (int)Math.ceil(halfLength * from) * 2,
        (int)Math.floor(halfLength * to) * 2);
    
  • Don’t write, never commit/publish uncommented/undocumented code, minimal:
    /** Returns a new Byte[] containing samples from fullLength
    *  starting at from (rounded up), ending at to (rounded down). */
    

Leave a Reply

Your email address will not be published. Required fields are marked *