Files
2026-06-10 01:42:08 +02:00

102 lines
4.0 KiB
Racket

#lang scribble/manual
@title{PCM resampling with SoXR}
@defmodule[racket-audio/resampler]
This module provides a small Racket wrapper around @tt{libsoxr}. It is meant
for interleaved PCM buffers such as stereo @tt{L R L R ...} data. It supports
sample-rate conversion and the PCM datatypes that SoXR can process directly:
@racket['s16], @racket['s32], @racket['float32] and @racket['float64]. Packed
24-bit PCM is supported by the wrapper by expanding @racket['s24] input to
@racket['s32] before calling SoXR and packing @racket['s32] output back to
@racket['s24] afterwards.
SoXR does not perform general channel-layout conversion in this wrapper. Use it
for unchanged channel counts, for example mono-to-mono or stereo-to-stereo.
@defproc[(resampler-available?) boolean?]{
Returns @racket[#t] when @tt{libsoxr} was loaded.
}
@defproc[(resampler-version) string?]{
Returns the version string reported by @tt{libsoxr}.
}
@defproc[(make-resampler
[input-rate exact-positive-integer?]
[output-rate exact-positive-integer?]
[channels exact-positive-integer?]
[#:input-format input-format symbol? 's32]
[#:output-format output-format symbol? 's32]
[#:quality quality symbol? 'hq]
[#:phase phase symbol? 'linear]
[#:steep-filter? steep-filter? boolean? #f]
[#:scale scale real? 1.0]
[#:no-dither? no-dither? boolean? #f]
[#:num-threads num-threads exact-positive-integer? 1])
resampler?]{
Creates a streaming resampler. The supported PCM formats are @racket['s16],
@racket['s24], @racket['s32], @racket['float32] and @racket['float64].
The quality value selects a SoXR resampling recipe. Useful values are
@racket['qq], @racket['lq], @racket['mq], @racket['hq], @racket['vhq],
@racket['16-bit], @racket['20-bit], @racket['24-bit], @racket['28-bit] and
@racket['32-bit]. The @racket['24-bit] quality recipe is a filter precision
setting; it is not the same thing as 24-bit PCM output. Use
@racket[#:output-format 's24] for packed 24-bit output.
}
@defproc[(resampler-convert
[r resampler?]
[buffer bytes?]
[size exact-nonnegative-integer? (bytes-length buffer)])
(values bytes? exact-nonnegative-integer?)]{
Feeds interleaved PCM bytes to the resampler and returns converted PCM bytes and
the number of output frames. A frame contains one sample for each channel.
}
@defproc[(resampler-drain [r resampler?])
(values bytes? exact-nonnegative-integer?)]{
Flushes delayed output after the last input block and returns converted bytes and
frames.
}
@defproc[(resampler-clear! [r resampler?]) boolean?]{
Clears the resampler state so the same instance can be reused for a fresh signal
with the same configuration.
}
@defproc[(resampler-close! [r resampler?]) boolean?]{
Releases the native SoXR resampler. Calling this more than once is harmless.
}
@defproc[(resample-bytes
[buffer bytes?]
[input-rate exact-positive-integer?]
[output-rate exact-positive-integer?]
[channels exact-positive-integer?]
[#:size size exact-nonnegative-integer? (bytes-length buffer)]
[#:input-format input-format symbol? 's32]
[#:output-format output-format symbol? 's32]
[#:quality quality symbol? 'hq]
[#:phase phase symbol? 'linear]
[#:steep-filter? steep-filter? boolean? #f]
[#:scale scale real? 1.0]
[#:no-dither? no-dither? boolean? #f]
[#:num-threads num-threads exact-positive-integer? 1])
(values bytes? exact-nonnegative-integer?)]{
Convenience function for one buffer. It creates a resampler, processes the
input, drains delayed samples and closes the native state.
}
@defproc[(pcm-format? [v any/c]) boolean?]{
Returns whether @racket[v] is one of the supported PCM format symbols.
}
@defproc[(pcm-format-sample-bytes [fmt symbol?]) exact-positive-integer?]{
Returns the packed sample size in bytes for @racket[fmt]. For @racket['s24]
this is @racket[3], even though the wrapper internally expands to 32-bit samples
for SoXR.
}