Packages
wavex
0.12.0
0.14.1
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.4
0.9.3
0.9.1
0.9.0
0.8.1
0.8.0
0.7.3
0.7.2
0.7.1
0.5.5
0.5.4
0.5.3
0.5.2
0.5.0
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.0
0.3.0
0.2.16
0.2.13
0.2.11
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.2
0.2.1
0.2.0
0.1.8
0.1.0
Read WAVE LPCM data
Current section
Files
Jump to
Current section
Files
lib/wavex/chunk/format.ex
defmodule Wavex.Chunk.Format do
@moduledoc """
Read a format chunk.
"""
alias Wavex.Error.{
BlockAlignMismatch,
ByteRateMismatch,
UnexpectedEOF,
UnexpectedFormatSize,
UnexpectedFourCC,
UnsupportedBitrate,
UnsupportedFormat,
ZeroChannels
}
alias Wavex.FourCC
@enforce_keys [
:channels,
:sample_rate,
:byte_rate,
:block_align,
:bits_per_sample
]
defstruct [
:channels,
:sample_rate,
:byte_rate,
:block_align,
:bits_per_sample
]
@type t :: %__MODULE__{
channels: pos_integer,
sample_rate: pos_integer,
byte_rate: pos_integer,
block_align: pos_integer,
bits_per_sample: pos_integer
}
@four_cc "fmt "
@spec four_cc :: FourCC.t()
def four_cc, do: @four_cc
@spec verify_size(non_neg_integer) :: :ok | {:error, UnexpectedFormatSize.t()}
defp verify_size(16), do: :ok
defp verify_size(actual), do: {:error, %UnexpectedFormatSize{actual: actual}}
@spec verify_format(non_neg_integer) :: :ok | {:error, UnsupportedFormat.t()}
defp verify_format(1), do: :ok
defp verify_format(actual), do: {:error, %UnsupportedFormat{actual: actual}}
@spec verify_bits_per_sample(non_neg_integer) :: :ok | {:error, UnsupportedBitrate.t()}
defp verify_bits_per_sample(actual) when actual in [8, 16, 24], do: :ok
defp verify_bits_per_sample(actual), do: {:error, %UnsupportedBitrate{actual: actual}}
@spec verify_channels(non_neg_integer) :: :ok | {:error, ZeroChannels.t()}
defp verify_channels(0), do: {:error, %ZeroChannels{}}
defp verify_channels(_), do: :ok
@spec verify_block_align(non_neg_integer, non_neg_integer) ::
:ok | {:error, BlockAlignMismatch.t()}
defp verify_block_align(expected, expected), do: :ok
defp verify_block_align(expected, actual) do
{:error, %BlockAlignMismatch{expected: expected, actual: actual}}
end
@spec verify_byte_rate(non_neg_integer, non_neg_integer) :: :ok | {:error, ByteRateMismatch.t()}
defp verify_byte_rate(expected, expected), do: :ok
defp verify_byte_rate(expected, actual) do
{:error, %ByteRateMismatch{expected: expected, actual: actual}}
end
@doc ~S"""
Read a format chunk.
"""
@spec read(binary) ::
{:ok, t, binary}
| {:error,
BlockAlignMismatch.t()
| ByteRateMismatch.t()
| UnexpectedEOF.t()
| UnexpectedFormatSize.t()
| UnexpectedFourCC.t()
| UnsupportedBitrate.t()
| UnsupportedFormat.t()
| ZeroChannels.t()}
def read(<<
fmt_id::binary-size(4),
size::32-little,
format::16-little,
channels::16-little,
sample_rate::32-little,
byte_rate::32-little,
block_align::16-little,
bits_per_sample::16-little,
etc::binary
>>) do
with :ok <- FourCC.verify(fmt_id, @four_cc),
:ok <- verify_size(size),
:ok <- verify_format(format),
:ok <- verify_channels(channels),
:ok <- verify_bits_per_sample(bits_per_sample),
:ok <- verify_block_align(channels * div(bits_per_sample, 8), block_align),
:ok <- verify_byte_rate(sample_rate * block_align, byte_rate) do
{:ok,
%__MODULE__{
bits_per_sample: bits_per_sample,
block_align: block_align,
byte_rate: byte_rate,
channels: channels,
sample_rate: sample_rate
}, etc}
end
end
def read(binary) when is_binary(binary), do: {:error, %UnexpectedEOF{}}
end