Sums signed 16-bit little-endian PCM buffers, clipping at full scale, and pans mono sound.
Summary
Functions
Bytes one frame occupies: two per channel.
Copy a mono buffer to both channels, at the same constant-power level as pan/3.
How many samples sit at full scale.
Cut pcm to frames frames, mixing whatever ran past the end back over the start.
How loud a buffer is overall, as RMS in sample units. An empty buffer is 0.0.
Sum a list of buffers, passing over the silent ones. An empty list gives an empty buffer.
Sum two buffers, sample by sample, clipping at full scale. The result is as long as the longer buffer.
Mix buffer into base starting offset frames in; a frame is one sample per channels.
Scale a buffer so its loudness/1 is target.
Place a mono buffer in the stereo field, from -1.0 hard left to 1.0 hard right.
The largest absolute sample value in a buffer.
Scale a buffer's amplitude by gain, clipping at full scale.
A buffer of silence, frames frames long. A negative frames gives an empty buffer.
Whether every sample of pcm is zero.
Round off a buffer's peaks instead of flattening them.
Take frames frames from the front of a buffer.
Fold a stereo buffer down to mono by averaging each frame's two samples.
Functions
@spec bytes_per_frame(pos_integer()) :: pos_integer()
Bytes one frame occupies: two per channel.
Copy a mono buffer to both channels, at the same constant-power level as pan/3.
@spec clipped(binary()) :: non_neg_integer()
How many samples sit at full scale.
@spec fold(binary(), non_neg_integer(), pos_integer()) :: binary()
Cut pcm to frames frames, mixing whatever ran past the end back over the start.
iex> pcm = <<1, 0, 1, 0>> <> <<2, 0, 2, 0>>
iex> TuningFork.Mixer.fold(pcm, 1, 2)
<<3, 0, 3, 0>>A buffer already frames long or shorter comes back as it is.
How loud a buffer is overall, as RMS in sample units. An empty buffer is 0.0.
Sum a list of buffers, passing over the silent ones. An empty list gives an empty buffer.
Sum two buffers, sample by sample, clipping at full scale. The result is as long as the longer buffer.
@spec mix_at(binary(), binary(), non_neg_integer(), pos_integer()) :: {binary(), binary()}
Mix buffer into base starting offset frames in; a frame is one sample per channels.
Returns {result, overflow}. result is always exactly as long as base; overflow is
whatever ran off the end, ready to be mixed in somewhere else. An offset at or past the
end of base returns base unchanged with the whole of buffer as overflow.
Scale a buffer so its loudness/1 is target.
The scaling is limited so that the loudest sample lands no higher than :ceiling of full
scale, default 0.85, which means a very quiet buffer may come back below target. A silent
buffer is returned unchanged.
@spec pan(binary(), float(), pos_integer()) :: binary()
Place a mono buffer in the stereo field, from -1.0 hard left to 1.0 hard right.
pan outside that range is clamped to it. Panning is constant power, so a centred sound
sits about 3 dB below its mono render. A channels of 1 returns the buffer unchanged.
@spec peak(binary()) :: non_neg_integer()
The largest absolute sample value in a buffer.
Scale a buffer's amplitude by gain, clipping at full scale.
A gain of 1.0 returns the buffer unchanged; a gain at or below 0.0 gives silence of the same length.
@spec silence(non_neg_integer(), pos_integer()) :: binary()
A buffer of silence, frames frames long. A negative frames gives an empty buffer.
Whether every sample of pcm is zero.
Round off a buffer's peaks instead of flattening them.
Samples quieter than threshold of full scale pass through untouched; louder ones are bent
smoothly towards full scale and never reach it, so clipped/1 on the result is zero.
threshold runs 0.0 to 1.0 and defaults to 0.7; at 1.0 the buffer is returned unchanged.
iex> loud = for _ <- 1..4, into: <<>>, do: <<32_767::16-signed-little>>
iex> TuningFork.Mixer.clipped(TuningFork.Mixer.soft_clip(loud))
0
@spec take(binary(), pos_integer(), pos_integer()) :: {binary(), binary()}
Take frames frames from the front of a buffer.
Returns {chunk, rest}. chunk is always exactly frames frames, padded with silence if
the buffer is shorter, in which case rest is empty.
Fold a stereo buffer down to mono by averaging each frame's two samples.