lib/matchers/audio.ex

defmodule Infer.Audio do
  @moduledoc """
  Audio type matchers based on the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming))
  """

  @doc """
  Takes the binary file contents as arguments. Returns `true` if it's a midi.
  """
  @spec midi?(binary()) :: boolean()
  def midi?(<<0x4D, 0x54, 0x68, 0x64, _rest::binary>>), do: true
  def midi?(_binary), do: false

  @doc """
  Takes the binary file contents as arguments. Returns `true` if it's a mp3.

  ## Examples

      iex> binary = File.read!("test/audio/sample.mp3")
      iex> Infer.Audio.mp3?(binary)
      true

  """
  @spec mp3?(binary()) :: boolean()
  def mp3?(<<0x49, 0x44, 0x33, _rest::binary>>), do: true
  def mp3?(<<0xFF, 0xFB, _rest::binary>>), do: true
  def mp3?(_binary), do: false

  @doc """
  Takes the binary file contents as arguments. Returns `true` if it's a m4a.
  """
  @spec m4a?(binary()) :: boolean()
  def m4a?(<<_data::binary-size(4), 0x66, 0x74, 0x79, 0x70, 0x4D, 0x3F, 0x41, _rest::binary>>), do: true
  def m4a?(<<0x4D, 0x34, 0x41, 0x20, _rest::binary>>), do: true
  def m4a?(_binary), do: false

  @doc """
  Takes the binary file contents as arguments. Returns `true` if it's a ogg.
  """
  @spec ogg?(binary()) :: boolean()
  def ogg?(<<0x4F, 0x67, 0x67, 0x53, _rest::binary>>), do: true
  def ogg?(_binary), do: false

  @doc """
  Takes the binary file contents as arguments. Returns `true` if it's a flac.
  """
  @spec flac?(binary()) :: boolean()
  def flac?(<<0x66, 0x4C, 0x61, 0x43, _rest::binary>>), do: true
  def flac?(_binary), do: false

  @doc """
  Takes the binary file contents as arguments. Returns `true` if it's a wav.
  """
  @spec wav?(binary()) :: boolean()
  def wav?(<<0x52, 0x49, 0x46, 0x46, _data::binary-size(4), 0x57, 0x41, 0x56, 0x45, _rest::binary>>), do: true
  def wav?(_binary), do: false

  @doc """
  Takes the binary file contents as arguments. Returns `true` if it's a amr.
  """
  @spec amr?(binary()) :: boolean()
  def amr?(<<0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A, _rest::binary>>), do: true
  def amr?(_binary), do: false

  @doc """
  Takes the binary file contents as arguments. Returns `true` if it's a aac.
  """
  @spec aac?(binary()) :: boolean()
  def aac?(<<0xFF, 0xF1, 0xF9, _rest::binary>>), do: true
  def aac?(_binary), do: false

  @doc """
  Takes the binary file contents as arguments. Returns `true` if it's an aiff.
  """
  @spec aiff?(binary()) :: boolean()
  def aiff?(<<0x46, 0x4F, 0x52, 0x4D, _data::binary-size(4), 0x41, 0x49, 0x46, 0x46, _rest::binary>>), do: true
  def aiff?(_binary), do: false
end