Record Class WaveFormat

java.lang.Object
java.lang.Record
com.tino1b2be.dtmf.io.wav.internal.WaveFormat
Record Components:
sampleRate - sample rate in Hertz; must be strictly positive
channelCount - number of interleaved channels in each frame; must be strictly positive
bitDepth - bits per sample; must be one of {16, 24, 32, 64}
bytesPerFrame - size of one complete frame in bytes; must equal (bitDepth / 8) * channelCount
encoding - PCM integer or IEEE float; must be non-null and, when WaveFormat.Encoding.IEEE_FLOAT, must be paired with a bit depth in {32, 64}
dataStartByteOffset - absolute byte offset of the data chunk payload within the enclosing RIFF form; must be non-negative
dataSizeBytes - length of the data chunk payload in bytes; must be non-negative
totalFrames - number of complete frames in the payload (dataSizeBytes / bytesPerFrame); must be non-negative

public record WaveFormat(int sampleRate, int channelCount, int bitDepth, int bytesPerFrame, WaveFormat.Encoding encoding, long dataStartByteOffset, long dataSizeBytes, long totalFrames) extends Record
Parsed metadata from a WAV file's fmt chunk together with the byte-range coordinates of its data payload. Populated by the RIFF parser in this package and handed to com.tino1b2be.dtmf.io.wav.WavAudioSource and WavSampleReader so they can decode frames without re-reading the header.

This record is the shared description of a validated, supported WAV stream. By the time one is constructed, the parser has already rejected compressed encodings (µ-law, A-law, ADPCM; Requirement 9.10), unsupported bit depths, and unsupported channel counts (Requirements 9.7, 9.8, 9.9). Every field below is therefore guaranteed to be internally consistent and in range.

Field-level contract:

  • sampleRate — in Hertz, the value of the fmt chunk's nSamplesPerSec field. Must be strictly positive. The downstream DtmfFileDecoder enforces the module-wide [4000, 192000] window; this record itself does not impose that upper bound because the parser needs to carry any positive rate through to WavAudioSource.sampleRate() before the higher-level guard runs.
  • channelCount — from nChannels. Must be strictly positive. In practice the parser restricts the set of decoded channel counts to 1 or 2 (Requirements 9.7, 9.8, 9.9); this record accepts any positive value so unit tests can exercise the underlying container format without threading the channel guard all the way down.
  • bitDepth — from wBitsPerSample, or from wValidBitsPerSample for WAVEFORMATEXTENSIBLE. Must be one of 16, 24, 32, or 64. The dtmf-io module does not support 8-bit PCM (Requirement 3.4).
  • bytesPerFrame — from the fmt chunk's nBlockAlign field, validated by the parser to equal (bitDepth / 8) * channelCount. This record re-validates the relationship so a bug in the parser cannot silently propagate a mismatch downstream.
  • encoding — either WaveFormat.Encoding.PCM_SIGNED (from wFormatTag = 0x0001 or the KSDATAFORMAT_SUBTYPE_PCM GUID) or WaveFormat.Encoding.IEEE_FLOAT (from wFormatTag = 0x0003 or KSDATAFORMAT_SUBTYPE_IEEE_FLOAT). IEEE_FLOAT is only valid at 32 or 64 bits — a constraint enforced by this record's compact constructor as a belt-and-braces check on top of the parser's own validation.
  • dataStartByteOffset — absolute byte offset within the input stream or file where the payload of the data chunk begins (i.e. immediately after its 8-byte "data" | size header). Must be non-negative. WavAudioSource uses this value as the seek anchor when canSeek() returns true: a seek to frame f sets the channel position to dataStartByteOffset + f * bytesPerFrame.
  • dataSizeBytes — length of the data chunk payload in bytes, taken either from the chunk's 32-bit size field (standard RIFF/WAVE) or from the ds64 chunk's 64-bit dataSize field (RF64). Must be non-negative.
  • totalFramesdataSizeBytes / bytesPerFrame, i.e. the number of complete frames the file is declared to contain. Must be non-negative. Stored eagerly (rather than derived on every call) because AudioSource.totalFrames() is on the hot metadata path for DtmfFileDecoder's block sizing.

This record is not part of the published API. It lives in com.tino1b2be.dtmf.io.wav.internal, whose stability contract (see the package Javadoc) explicitly allows breakage between any two releases. It is public at the type level purely so WavAudioSource and WavAudioSourceProvider — which live in the parent package and cannot otherwise see a package-private type here — can reach it; external callers MUST NOT depend on it.

Since:
2.1.0
  • Constructor Details

    • WaveFormat

      public WaveFormat(int sampleRate, int channelCount, int bitDepth, int bytesPerFrame, WaveFormat.Encoding encoding, long dataStartByteOffset, long dataSizeBytes, long totalFrames)
      Compact constructor validating every field against the class-level contract. This is the single source of truth for what constitutes a "supported WAV stream" inside dtmf-io-wav; the parser runs its own pre-flight checks against the raw header bytes, but the final, authoritative guard lives here so a test fixture that constructs WaveFormat directly is held to the same invariants as a real file.
      Throws:
      NullPointerException - if encoding is null
      IllegalArgumentException - if any numeric field is out of range, if bytesPerFrame does not equal (bitDepth / 8) * channelCount, or if encoding is WaveFormat.Encoding.IEEE_FLOAT with a bit depth outside {32, 64}
  • Method Details

    • toString

      public final String toString()
      Returns a string representation of this record class. The representation contains the name of the class, followed by the name and value of each of the record components.
      Specified by:
      toString in class Record
      Returns:
      a string representation of this object
    • hashCode

      public final int hashCode()
      Returns a hash code value for this object. The value is derived from the hash code of each of the record components.
      Specified by:
      hashCode in class Record
      Returns:
      a hash code value for this object
    • equals

      public final boolean equals(Object o)
      Indicates whether some other object is "equal to" this one. The objects are equal if the other object is of the same class and if all the record components are equal. Reference components are compared with Objects::equals(Object,Object); primitive components are compared with '=='.
      Specified by:
      equals in class Record
      Parameters:
      o - the object with which to compare
      Returns:
      true if this object is the same as the o argument; false otherwise.
    • sampleRate

      public int sampleRate()
      Returns the value of the sampleRate record component.
      Returns:
      the value of the sampleRate record component
    • channelCount

      public int channelCount()
      Returns the value of the channelCount record component.
      Returns:
      the value of the channelCount record component
    • bitDepth

      public int bitDepth()
      Returns the value of the bitDepth record component.
      Returns:
      the value of the bitDepth record component
    • bytesPerFrame

      public int bytesPerFrame()
      Returns the value of the bytesPerFrame record component.
      Returns:
      the value of the bytesPerFrame record component
    • encoding

      public WaveFormat.Encoding encoding()
      Returns the value of the encoding record component.
      Returns:
      the value of the encoding record component
    • dataStartByteOffset

      public long dataStartByteOffset()
      Returns the value of the dataStartByteOffset record component.
      Returns:
      the value of the dataStartByteOffset record component
    • dataSizeBytes

      public long dataSizeBytes()
      Returns the value of the dataSizeBytes record component.
      Returns:
      the value of the dataSizeBytes record component
    • totalFrames

      public long totalFrames()
      Returns the value of the totalFrames record component.
      Returns:
      the value of the totalFrames record component