Documentation
¶
Overview ¶
Package resample converts interleaved S16LE PCM audio between sample rates, preserving the channel count. It reconciles service sample rates (for example 24 kHz TTS audio) with the 48 kHz the WebRTC/Opus output path needs.
There are two ways to convert, and which one is right depends on whether the audio keeps coming:
- A Resampler is for a stream. It is stateful, carrying filter state across calls so a continuous stream converts cleanly across chunk boundaries, and it holds back the filter delay at the end of every call because more audio is expected. Create one per stream with New; it is not safe for concurrent use, and Close must be called when finished.
- Resample is for a buffer that is complete on its own: a sound effect, a recorded utterance, one turn of audio handed to a model. It converts in a single pass and flushes the filter delay, so nothing is clipped off the end. Running a complete buffer through a Resampler instead loses a millisecond or two of its tail.
Two builds are selected by the `libsoxr` build tag, both exposing the same API:
- Default (pure Go, see resample_purego.go): a no-cgo converter from github.com/gojargo/go-resample. It cross-compiles and links into static binaries with no native dependency.
- `-tags libsoxr` (see resample_soxr.go): links libsoxr (the SoX Resampler) via cgo for its high-quality polyphase conversion. Requires libsoxr at build and run time (libsoxr-dev to build, libsoxr0 to run).
Index ¶
Constants ¶
const DefaultClearAfter = 200 * time.Millisecond
DefaultClearAfter is how long a Resampler may sit idle before the next chunk is treated as the start of a fresh signal rather than the continuation of the last one.
Variables ¶
This section is empty.
Functions ¶
func Resample ¶ added in v0.1.0
Resample converts a complete buffer of interleaved S16LE PCM from inRate to outRate at the default quality, in a single pass. Unlike Resampler.Process it flushes the converter's filter delay, so the returned audio holds the whole signal rather than stopping a filter length short of it. Use it for audio that arrives whole; use a Resampler for audio that keeps coming.
It returns the input unchanged when the rates match, and nil for an empty buffer.
Types ¶
type Config ¶ added in v0.1.0
type Config struct {
// Quality selects the conversion filter; the zero value is QualityVHQ.
Quality Quality
// ClearAfter is how long the resampler may sit idle before its filter
// history is discarded. A resampler carries the tail of the audio it last
// saw so that a continuous stream converts cleanly across chunk boundaries,
// but after a gap that tail is no longer what came before: it is the end of
// the previous utterance bleeding into the start of the next one, which is
// heard as a click. 0 uses DefaultClearAfter; a negative value never clears,
// which is what a telephony leg wants, since its chunks arrive at irregular
// intervals that are gaps in delivery rather than gaps in the audio.
ClearAfter time.Duration
}
Config configures a Resampler.
type Quality ¶ added in v0.1.0
type Quality int
Quality selects the conversion filter, trading audio quality against CPU cost. The zero value is the highest quality, which is what a pipeline gets unless it asks for something cheaper.
The names are the five standard SoX Resampler recipes. Both builds understand all five: the libsoxr build passes them straight through, and the pure-Go build maps them onto the converters its library offers (see converterFor).
const ( // QualityVHQ is very high quality. It is the zero value, and so the default. QualityVHQ Quality = iota // QualityHQ is high quality: a shorter filter than VHQ, and audibly // transparent for speech. QualityHQ // QualityMQ is medium quality. QualityMQ // QualityLQ is low quality. QualityLQ // QualityQQ is "quick": interpolation rather than a windowed filter, for // paths that care more about cost than about the stopband. QualityQQ )
type Resampler ¶
type Resampler struct {
// contains filtered or unexported fields
}
Resampler converts a stream of interleaved S16LE PCM from one sample rate to another using the pure-Go github.com/gojargo/go-resample converter (no cgo). This is the default build; `-tags libsoxr` swaps in libsoxr (see resample_soxr.go). Create one per audio stream with New; it is not safe for concurrent use. Close is a no-op kept for API parity with the libsoxr build.
func New ¶
New returns a Resampler from inRate to outRate for the given channel count, at the default quality and idle window. When inRate equals outRate the Resampler passes audio through unchanged and allocates no converter.
func NewWithConfig ¶ added in v0.1.0
NewWithConfig returns a Resampler configured by cfg. See New.
func (*Resampler) Clear ¶ added in v0.1.0
func (r *Resampler) Clear()
Clear discards the filter history, so the next chunk is converted as the start of a fresh signal rather than the continuation of the last one. The rate and quality are unchanged.
func (*Resampler) Close ¶
func (r *Resampler) Close()
Close releases converter resources. The pure-Go converter holds none, so this is a no-op; it is safe to call more than once and exists for API parity with the libsoxr build.
func (*Resampler) Process ¶
Process resamples one buffer of interleaved S16LE PCM and returns the resampled audio. When the input and output rates match it returns the input unchanged; otherwise the returned slice is freshly allocated and owned by the caller. Because the converter has filter delay, the first calls of a stream emit slightly fewer frames than the rate ratio implies, which later calls make up. Use Resample instead for a buffer that is complete on its own.
A gap longer than the configured idle window clears the filter history first, so the tail of what came before is not mixed into what comes next.