Class SampleConversion

java.lang.Object
com.tino1b2be.dtmf.io.internal.SampleConversion

public final class SampleConversion extends Object
Shared PCM sample normalisation helper for the dtmf-io family of modules. Bytes-to-double decoding for every (bitDepth, byteOrder, encoding) tuple this project supports lives here in a single place, so the normalisation formulas cannot drift between RawPcmAudioSource, the clean-room WAV reader in dtmf-io-wav, and the mp3spi-backed decoder in dtmf-io-mp3.

This class is not part of the published API. It lives in com.tino1b2be.dtmf.io.internal, whose stability contract (see the package Javadoc) explicitly allows breakage between any two releases. It is public at the type level purely so the WAV and MP3 provider modules — which live in sibling Java packages — can reach it; external callers MUST NOT depend on it.

Conversion formulas (Requirements 3.6, 7.12, 9.14)

The normalisation matches dtmf-core's com.tino1b2be.dtmf.internal.SampleConverter contract exactly:
  • Signed integer PCM: decoded as a two's-complement signed integer in the requested byte order, then divided by 2^(bitDepth - 1). Short.MIN_VALUE maps exactly to -1.0; Short.MAX_VALUE maps to 32767/32768 ≈ 0.99996948. The analogous exact-and-near mapping holds at 24, 32, and 64 bits.
  • Unsigned integer PCM: decoded as an unsigned integer in the requested byte order, then the midpoint 2^(bitDepth - 1) is subtracted and the result is divided by 2^(bitDepth - 1). An unsigned sample whose value is the midpoint therefore maps to exactly 0.0; an unsigned sample of 0 maps to -1.0; the maximum unsigned value maps just below +1.0.
  • IEEE float: the raw bit pattern is assembled in the requested byte order and reinterpreted via Float.intBitsToFloat(int) (32-bit) or Double.longBitsToDouble(long) (64-bit). No scaling is applied — float PCM samples are already in [-1.0, 1.0] by convention. The 32-bit variant widens to double by direct cast.

Supported tuples

Every (bitDepth, byteOrder, encoding) combination that appears in the PCM sample-formats table of design.md is supported:
  • SIGNED_INT: bitDepth ∈ {16, 24, 32, 64} × byteOrder ∈ {LITTLE_ENDIAN, BIG_ENDIAN}.
  • UNSIGNED_INT: bitDepth ∈ {16, 24, 32, 64} × byteOrder ∈ {LITTLE_ENDIAN, BIG_ENDIAN}.
  • IEEE_FLOAT: bitDepth ∈ {32, 64} × byteOrder ∈ {LITTLE_ENDIAN, BIG_ENDIAN}.
Any other combination is rejected by decoderFor(int, ByteOrder, PcmEncoding) with an IllegalArgumentException; callers upstream (notably RawPcmAudioSource's constructor) are expected to have validated their inputs before asking for a decoder, so this dispatcher's rejection is the second line of defence.
Since:
2.1.0
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static interface 
    Primitive functional interface for a single-frame PCM decoder.
  • Method Summary

    Modifier and Type
    Method
    Description
    static double
    decodeFloat32BE(byte[] b, int offset)
    Decode a big-endian IEEE 754 32-bit float sample and widen to double without scaling.
    static double
    decodeFloat32LE(byte[] b, int offset)
    Decode a little-endian IEEE 754 32-bit float sample and widen to double without scaling.
    static double
    decodeFloat64BE(byte[] b, int offset)
    Decode a big-endian IEEE 754 64-bit double sample bit-exactly.
    static double
    decodeFloat64LE(byte[] b, int offset)
    Decode a little-endian IEEE 754 64-bit double sample bit-exactly.
    static double
    decodePcm16BE(byte[] b, int offset)
    Decode a big-endian signed PCM16 sample and normalise by 2^15.
    static double
    decodePcm16LE(byte[] b, int offset)
    Decode a little-endian signed PCM16 sample and normalise by 2^15.
    static double
    decodePcm24BE(byte[] b, int offset)
    Decode a big-endian signed PCM24 sample, sign-extend from bit 23, and normalise by 2^23.
    static double
    decodePcm24LE(byte[] b, int offset)
    Decode a little-endian signed PCM24 sample, sign-extend from bit 23, and normalise by 2^23.
    static double
    decodePcm32BE(byte[] b, int offset)
    Decode a big-endian signed PCM32 sample and normalise by 2^31.
    static double
    decodePcm32LE(byte[] b, int offset)
    Decode a little-endian signed PCM32 sample and normalise by 2^31.
    static double
    decodePcm64BE(byte[] b, int offset)
    Decode a big-endian signed PCM64 sample and normalise by 2^63.
    static double
    decodePcm64LE(byte[] b, int offset)
    Decode a little-endian signed PCM64 sample and normalise by 2^63.
    decoderFor(int bitDepth, ByteOrder order, PcmEncoding encoding)
    Return the SampleConversion.SampleDecoder for a given (bitDepth, byteOrder, encoding) tuple.
    static double
    decodeUnsignedPcm16BE(byte[] b, int offset)
    Decode a big-endian unsigned PCM16 sample, subtract the midpoint 2^15, and normalise by 2^15.
    static double
    decodeUnsignedPcm16LE(byte[] b, int offset)
    Decode a little-endian unsigned PCM16 sample, subtract the midpoint 2^15, and normalise by 2^15.
    static double
    decodeUnsignedPcm24BE(byte[] b, int offset)
    Decode a big-endian unsigned PCM24 sample, subtract the midpoint 2^23, and normalise by 2^23.
    static double
    decodeUnsignedPcm24LE(byte[] b, int offset)
    Decode a little-endian unsigned PCM24 sample, subtract the midpoint 2^23, and normalise by 2^23.
    static double
    decodeUnsignedPcm32BE(byte[] b, int offset)
    Decode a big-endian unsigned PCM32 sample, subtract the midpoint 2^31, and normalise by 2^31.
    static double
    decodeUnsignedPcm32LE(byte[] b, int offset)
    Decode a little-endian unsigned PCM32 sample, subtract the midpoint 2^31, and normalise by 2^31.
    static double
    decodeUnsignedPcm64BE(byte[] b, int offset)
    Decode a big-endian unsigned PCM64 sample, subtract the midpoint 2^63, and normalise by 2^63.
    static double
    decodeUnsignedPcm64LE(byte[] b, int offset)
    Decode a little-endian unsigned PCM64 sample, subtract the midpoint 2^63, and normalise by 2^63.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • decoderFor

      public static SampleConversion.SampleDecoder decoderFor(int bitDepth, ByteOrder order, PcmEncoding encoding)
      Return the SampleConversion.SampleDecoder for a given (bitDepth, byteOrder, encoding) tuple.
      Parameters:
      bitDepth - one of 16, 24, 32, 64
      order - ByteOrder.LITTLE_ENDIAN or ByteOrder.BIG_ENDIAN
      encoding - PCM numeric encoding
      Returns:
      decoder for the requested tuple
      Throws:
      NullPointerException - if order or encoding is null
      IllegalArgumentException - if the (bitDepth, encoding) pair is not supported (for example IEEE_FLOAT with bitDepth == 16)
    • decodePcm16LE

      public static double decodePcm16LE(byte[] b, int offset)
      Decode a little-endian signed PCM16 sample and normalise by 2^15.
      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodePcm16BE

      public static double decodePcm16BE(byte[] b, int offset)
      Decode a big-endian signed PCM16 sample and normalise by 2^15.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodePcm24LE

      public static double decodePcm24LE(byte[] b, int offset)
      Decode a little-endian signed PCM24 sample, sign-extend from bit 23, and normalise by 2^23.
      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodePcm24BE

      public static double decodePcm24BE(byte[] b, int offset)
      Decode a big-endian signed PCM24 sample, sign-extend from bit 23, and normalise by 2^23.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodePcm32LE

      public static double decodePcm32LE(byte[] b, int offset)
      Decode a little-endian signed PCM32 sample and normalise by 2^31.
      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodePcm32BE

      public static double decodePcm32BE(byte[] b, int offset)
      Decode a big-endian signed PCM32 sample and normalise by 2^31.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodePcm64LE

      public static double decodePcm64LE(byte[] b, int offset)
      Decode a little-endian signed PCM64 sample and normalise by 2^63.
      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodePcm64BE

      public static double decodePcm64BE(byte[] b, int offset)
      Decode a big-endian signed PCM64 sample and normalise by 2^63.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodeUnsignedPcm16LE

      public static double decodeUnsignedPcm16LE(byte[] b, int offset)
      Decode a little-endian unsigned PCM16 sample, subtract the midpoint 2^15, and normalise by 2^15.
      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodeUnsignedPcm16BE

      public static double decodeUnsignedPcm16BE(byte[] b, int offset)
      Decode a big-endian unsigned PCM16 sample, subtract the midpoint 2^15, and normalise by 2^15.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodeUnsignedPcm24LE

      public static double decodeUnsignedPcm24LE(byte[] b, int offset)
      Decode a little-endian unsigned PCM24 sample, subtract the midpoint 2^23, and normalise by 2^23.
      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodeUnsignedPcm24BE

      public static double decodeUnsignedPcm24BE(byte[] b, int offset)
      Decode a big-endian unsigned PCM24 sample, subtract the midpoint 2^23, and normalise by 2^23.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodeUnsignedPcm32LE

      public static double decodeUnsignedPcm32LE(byte[] b, int offset)
      Decode a little-endian unsigned PCM32 sample, subtract the midpoint 2^31, and normalise by 2^31.

      The unsigned value is read into a long (since 2^32 - 1 does not fit in int), so the subtraction is exact.

      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodeUnsignedPcm32BE

      public static double decodeUnsignedPcm32BE(byte[] b, int offset)
      Decode a big-endian unsigned PCM32 sample, subtract the midpoint 2^31, and normalise by 2^31.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodeUnsignedPcm64LE

      public static double decodeUnsignedPcm64LE(byte[] b, int offset)
      Decode a little-endian unsigned PCM64 sample, subtract the midpoint 2^63, and normalise by 2^63.

      2^63 is not representable as a signed long, so the raw 64-bit payload is widened to double via toUnsignedDouble(long) before the subtraction; the result is therefore approximate at the ULP level of double but exact for the telephony-scale magnitudes real callers have.

      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodeUnsignedPcm64BE

      public static double decodeUnsignedPcm64BE(byte[] b, int offset)
      Decode a big-endian unsigned PCM64 sample, subtract the midpoint 2^63, and normalise by 2^63.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      normalised sample in [-1.0, 1.0]
    • decodeFloat32LE

      public static double decodeFloat32LE(byte[] b, int offset)
      Decode a little-endian IEEE 754 32-bit float sample and widen to double without scaling.
      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      the widened float value
    • decodeFloat32BE

      public static double decodeFloat32BE(byte[] b, int offset)
      Decode a big-endian IEEE 754 32-bit float sample and widen to double without scaling.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      the widened float value
    • decodeFloat64LE

      public static double decodeFloat64LE(byte[] b, int offset)
      Decode a little-endian IEEE 754 64-bit double sample bit-exactly.
      Parameters:
      b - source bytes
      offset - index of the low byte of the sample
      Returns:
      the decoded double value
    • decodeFloat64BE

      public static double decodeFloat64BE(byte[] b, int offset)
      Decode a big-endian IEEE 754 64-bit double sample bit-exactly.
      Parameters:
      b - source bytes
      offset - index of the high byte of the sample
      Returns:
      the decoded double value