Class DtmfFileDecoder

java.lang.Object
com.tino1b2be.dtmf.io.DtmfFileDecoder

public final class DtmfFileDecoder extends Object
One-call facade over AudioSources and DtmfDecoder.

DtmfFileDecoder is the glue between the file-I/O layer and the format-agnostic dtmf-core decoder. Every overload opens (or accepts) an AudioSource, reads the full stream into a normalised double[], and forwards the buffer to DtmfDecoder.decode(double[], DtmfConfig).

Auto-resolve

The file's declared sample rate — read from the opened AudioSource — takes precedence over the DtmfConfig the caller supplied (Requirement 17). When source.sampleRate() differs from config.sampleRate(), DtmfFileDecoder internally rebuilds the config with the source's rate substituted in. Every other field of the caller's config (tone/gap durations, detection threshold, channel mode, window function, twist tolerances, confirmation frames) is preserved verbatim. The analysis block size is not copied; it is re-derived from the new rate via BlockSizer.blockSizeFor(newRate) at build() time so the effective bin width lands in [40, 60] Hz for the rate actually on disk (Requirements 17.1, 17.2).

Because decoding runs at the source's rate, the DtmfTone values returned from decode(...) carry sampleRate = source.sampleRate() (Requirement 17.5). Callers who need a Duration for a detected tone should use the DtmfTone.startTime() / DtmfTone.endTime() helpers rather than dividing by the DtmfConfig's rate.

Channel handling

When source.channelCount() == 2 and config.channelMode() == MONO, the interleaved left and right samples are averaged into a mono buffer before invoking DtmfDecoder (Requirement 8.7). When config.channelMode() is STEREO_INDEPENDENT or STEREO_DOWNMIX, the interleaved buffer is forwarded to DtmfDecoder unchanged and DtmfDecoder applies the configured mode (Requirement 8.8).

Unsupported inputs

  • Channel counts greater than 2 throw UnsupportedAudioFormatException naming the count and stating that only 1 and 2 are supported (Requirement 8.10).
  • A mono source paired with a stereo channel mode throws UnsupportedAudioFormatException naming the mismatch and pointing the caller at ChannelMode.MONO (Requirement 8.9).
  • A sample rate outside the supported [4000, 192000] Hz range throws UnsupportedAudioFormatException naming the rate and the range (Requirement 17.3).

Resource ownership

The Path, InputStream, and URL overloads open the AudioSource internally inside a try-with-resources so the source is always closed before the method returns — on the normal path and on any exceptional path (Requirement 8.11). The decode(AudioSource, DtmfConfig) overload never closes the caller-supplied source; ownership stays with the caller (Requirement 8.12).

Null-safety

Every public overload null-checks every parameter via Objects.requireNonNull(Object, String) and throws NullPointerException identifying the parameter (Requirements 8.13, 12.1).

Thread safety

DtmfFileDecoder is stateless and every method is static; calls are safe to invoke concurrently from multiple threads on different inputs.
Since:
2.1.0
See Also:
  • Method Summary

    Modifier and Type
    Method
    Description
    static List<com.tino1b2be.dtmf.DtmfTone>
    decode(AudioSource source, com.tino1b2be.dtmf.DtmfConfig config)
    Decode the DTMF tones in an already-opened AudioSource.
    static List<com.tino1b2be.dtmf.DtmfTone>
    decode(InputStream stream, String hint, com.tino1b2be.dtmf.DtmfConfig config)
    Decode the DTMF tones in stream.
    static List<com.tino1b2be.dtmf.DtmfTone>
    decode(URL url, com.tino1b2be.dtmf.DtmfConfig config)
    Decode the DTMF tones in the audio resource at url.
    static List<com.tino1b2be.dtmf.DtmfTone>
    decode(Path path, com.tino1b2be.dtmf.DtmfConfig config)
    Decode the DTMF tones in the audio file at path.

    Methods inherited from class java.lang.Object

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

    • decode

      public static List<com.tino1b2be.dtmf.DtmfTone> decode(Path path, com.tino1b2be.dtmf.DtmfConfig config) throws IOException
      Decode the DTMF tones in the audio file at path.

      The file is opened via AudioSources.open(Path) — i.e. the registered AudioSourceProvider that scores highest on the file's header bytes handles the decode — and the resulting AudioSource is closed before this method returns, whether the call succeeds or throws (Requirement 8.11).

      Parameters:
      path - file system path to the audio file; non-null
      config - detection configuration; non-null. The file's declared sample rate takes precedence over config.sampleRate() (see the class-level auto-resolve notes).
      Returns:
      the detected tones, in non-decreasing startSample order
      Throws:
      NullPointerException - if any parameter is null
      UnsupportedAudioFormatException - if no provider can decode the file, the file declares an unsupported channel count or sample rate, or the channel mode is incompatible with the source
      IOException - if an underlying I/O error occurs
    • decode

      public static List<com.tino1b2be.dtmf.DtmfTone> decode(InputStream stream, String hint, com.tino1b2be.dtmf.DtmfConfig config) throws IOException
      Decode the DTMF tones in stream.

      The stream is passed to AudioSources.open(InputStream, String), which wraps non-markable streams in a BufferedInputStream before provider dispatch. The returned AudioSource is closed before this method returns (normal or exceptional); per AudioSources' contract, closing the source does not close the caller-supplied stream (Requirement 8.11 / 4.10).

      Parameters:
      stream - audio byte stream; non-null. Caller retains ownership.
      hint - optional file-name / URL-path-segment / MIME-type hint; may be null
      config - detection configuration; non-null. The stream's declared sample rate takes precedence over config.sampleRate().
      Returns:
      the detected tones, in non-decreasing startSample order
      Throws:
      NullPointerException - if stream or config is null
      UnsupportedAudioFormatException - see decode(Path, DtmfConfig)
      IOException - if an underlying I/O error occurs
    • decode

      public static List<com.tino1b2be.dtmf.DtmfTone> decode(URL url, com.tino1b2be.dtmf.DtmfConfig config) throws IOException
      Decode the DTMF tones in the audio resource at url.

      Opens url.openStream() via AudioSources.open(URL), which derives a provider hint from the URL's last path segment and closes the URL-backed stream when the returned AudioSource is closed. The AudioSource is closed before this method returns (Requirement 8.11).

      Parameters:
      url - URL of the audio resource; non-null
      config - detection configuration; non-null
      Returns:
      the detected tones, in non-decreasing startSample order
      Throws:
      NullPointerException - if any parameter is null
      UnsupportedAudioFormatException - see decode(Path, DtmfConfig)
      IOException - if an underlying I/O error occurs
    • decode

      public static List<com.tino1b2be.dtmf.DtmfTone> decode(AudioSource source, com.tino1b2be.dtmf.DtmfConfig config) throws IOException
      Decode the DTMF tones in an already-opened AudioSource.

      Useful when the caller obtained the source via AudioSources.open directly (e.g. to inspect sampleRate() or totalFrames() first) or via RawPcmAudioSource (caller has PCM bytes in memory).

      This overload never closes source; ownership stays with the caller (Requirement 8.12). Callers who want the typical open-decode-close lifecycle should use one of the Path/InputStream/URL overloads instead.

      Parameters:
      source - opened audio source; non-null. Not closed by this call.
      config - detection configuration; non-null
      Returns:
      the detected tones, in non-decreasing startSample order
      Throws:
      NullPointerException - if any parameter is null
      UnsupportedAudioFormatException - if the source declares an unsupported channel count or sample rate, or the channel mode is incompatible with the source
      IOException - if an underlying I/O error occurs