Packages
wavex
0.3.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.ex
defmodule Wavex do
@moduledoc """
Read PCM WAVE data.
"""
alias Wavex.{DataChunk, Error, FormatChunk, RIFFHeader}
alias Wavex.Error.{DataSizeMismatch}
defstruct [:riff_header, :format_chunk, :data_chunk]
@type t :: %__MODULE__{
riff_header: RIFFHeader.t(),
format_chunk: FormatChunk.t(),
data_chunk: DataChunk.t()
}
@riff_header_size 12
@format_chunk_size 24
@non_data_size @riff_header_size + @format_chunk_size + 8
@spec verify_data_size(non_neg_integer, non_neg_integer) ::
:ok | {:error, UnexpectedDataSize.t()}
defp verify_data_size(data_size, data_size), do: :ok
defp verify_data_size(expected_data_size, actual_data_size) do
{:error, %DataSizeMismatch{expected: expected_data_size, actual: actual_data_size}}
end
@doc ~S"""
Read PCM WAVE data.
For more details, see `Wavex.RIFFHeader.read/1`, `Wavex.FormatChunk.read/1`,
and `Wavex.DataChunk.read/2`.
## Examples
iex Wavex.read(<<
...> 0x52, 0x49, 0x46, 0x46, # R I F F
...> 0x34, 0x00, 0x00, 0x00, # 52
...> 0x57, 0x41, 0x56, 0x45, # W A V E
...> 0x66, 0x6D, 0x74, 0x20, # f m t \s
...> 0x10, 0x00, 0x00, 0x00, # 16
...> 0x01, 0x00, 0x02, 0x00, # 1 2
...> 0x22, 0x56, 0x00, 0x00, # 22050
...> 0x88, 0x58, 0x01, 0x00, # 88200
...> 0x04, 0x00, 0x10, 0x00, # 4 16
...> 0x64, 0x61, 0x74, 0x61, # d a t a
...> 0x02, 0x00, 0x00, 0x00, # 2
...> 0x00, 0x00, 0x00, 0x00, # 0
...> 0x00, 0x00, 0x00, 0x00 # 0
...> >>)
{:ok,
%Wavex{
data_chunk: %Wavex.DataChunk{
data: <<0, 0, 0, 0, 0, 0, 0, 0>>,
size: 6
},
format_chunk: %Wavex.FormatChunk{
bits_per_sample: 16,
block_align: 4,
byte_rate: 88_200,
channels: 2,
sample_rate: 22_050
},
riff_header: %Wavex.RIFFHeader{size: 52}
}}
iex> Wavex.read(<<
...> 0x52, 0x49, 0x46, 0x46, # R I F F
...> 0x30, 0x00, 0x00, 0x00, # 48
...> 0x57, 0x41, 0x56, 0x45, # W A V E
...> 0x66, 0x6D, 0x74, 0x20, # f m t \s
...> 0x10, 0x00, 0x00, 0x00, # 16
...> 0x01, 0x00, 0x01, 0x00, # 1 1
...> 0x11, 0x2B, 0x00, 0x00, # 11025
...> 0x22, 0x56, 0x00, 0x00, # 22050
...> 0x02, 0x00, 0x10, 0x00, # 2 16
...> 0x64, 0x61, 0x74, 0x61, # d a t a
...> 0x02, 0x00, 0x00, 0x00, # 2
...> 0x00, 0x00, 0xFE, 0xFF # 0 0 254 255
...> >>)
{:ok,
%Wavex{
data_chunk: %Wavex.DataChunk{data: <<0, 0, 254, 255>>, size: 2},
format_chunk: %Wavex.FormatChunk{
bits_per_sample: 16,
block_align: 2,
byte_rate: 22050,
channels: 1,
sample_rate: 11025
},
riff_header: %Wavex.RIFFHeader{size: 48}
}}
"""
@spec read(binary) :: {:ok, t} | {:error, Error.t()}
def read(binary) when is_binary(binary) do
with {:ok, %RIFFHeader{size: size} = riff_header, etc} <- RIFFHeader.read(binary),
{:ok, %FormatChunk{block_align: block_align} = format_chunk, etc} <-
FormatChunk.read(etc),
{:ok, %DataChunk{size: data_size} = data_chunk} <- DataChunk.read(etc, block_align),
:ok <- verify_data_size(size - @non_data_size, block_align * data_size) do
{:ok, %Wavex{riff_header: riff_header, format_chunk: format_chunk, data_chunk: data_chunk}}
else
{:error, _} = error -> error
end
end
end