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

256 lines
7.9 KiB
Racket

(module soxr-ffi racket/base
(require ffi/unsafe
ffi/unsafe/define
"private/utils.rkt")
(provide soxr-available?
soxr-version
soxr-create
soxr-process
soxr-delay
soxr-clear
soxr-delete
soxr-error
soxr-engine
soxr-io-spec
soxr-quality-spec
soxr-runtime-spec
soxr-error-ptr->string
soxr-datatype-size
_soxr_t
_soxr_io_spec
_soxr_io_spec-pointer
soxr_io_spec?
soxr_io_spec-itype
soxr_io_spec-otype
soxr_io_spec-scale
soxr_io_spec-flags
set-soxr_io_spec-scale!
set-soxr_io_spec-flags!
_soxr_quality_spec
_soxr_quality_spec-pointer
soxr_quality_spec?
soxr_quality_spec-precision
soxr_quality_spec-phase_response
soxr_quality_spec-passband_end
soxr_quality_spec-stopband_begin
soxr_quality_spec-flags
set-soxr_quality_spec-precision!
set-soxr_quality_spec-phase_response!
set-soxr_quality_spec-passband_end!
set-soxr_quality_spec-stopband_begin!
set-soxr_quality_spec-flags!
_soxr_runtime_spec
_soxr_runtime_spec-pointer
soxr_runtime_spec?
soxr_runtime_spec-log2_min_dft_size
soxr_runtime_spec-log2_large_dft_size
soxr_runtime_spec-coef_size_kbytes
soxr_runtime_spec-num_threads
soxr_runtime_spec-flags
set-soxr_runtime_spec-num_threads!
set-soxr_runtime_spec-flags!
SOXR_FLOAT32
SOXR_FLOAT64
SOXR_INT32
SOXR_INT16
SOXR_SPLIT
SOXR_FLOAT32_I
SOXR_FLOAT64_I
SOXR_INT32_I
SOXR_INT16_I
SOXR_FLOAT32_S
SOXR_FLOAT64_S
SOXR_INT32_S
SOXR_INT16_S
SOXR_TPDF
SOXR_NO_DITHER
SOXR_QQ
SOXR_LQ
SOXR_MQ
SOXR_HQ
SOXR_VHQ
SOXR_16_BITQ
SOXR_20_BITQ
SOXR_24_BITQ
SOXR_28_BITQ
SOXR_32_BITQ
SOXR_LINEAR_PHASE
SOXR_INTERMEDIATE_PHASE
SOXR_MINIMUM_PHASE
SOXR_STEEP_FILTER
SOXR_ROLLOFF_SMALL
SOXR_ROLLOFF_MEDIUM
SOXR_ROLLOFF_NONE
SOXR_HI_PREC_CLOCK
SOXR_DOUBLE_PRECISION
SOXR_VR
SOXR_COEF_INTERP_AUTO
SOXR_COEF_INTERP_LOW
SOXR_COEF_INTERP_HIGH)
;; libsoxr is normally libsoxr.so.0 on Linux and libsoxr.dylib on macOS.
;; The Windows build supplied with racket-audio may be either soxr.dll or
;; libsoxr.dll, so both stems are tried through the existing get-lib helper.
(define libsoxr
(get-lib (case (system-type 'os)
[(windows) '("soxr" "libsoxr")]
[else '("soxr" "libsoxr")])
(case (system-type 'os*)
[(linux) '("0" #f)]
[else '(#f)])))
(define-ffi-definer def-soxr libsoxr #:default-make-fail make-not-available)
(define _soxr_t (_cpointer/null 'soxr))
;; soxr.h structs. These are passed by pointer to soxr_create, while the
;; constructor functions in the C API return initialized structs by value.
(define-cstruct _soxr_io_spec
([itype _int]
[otype _int]
[scale _double]
[e _pointer]
[flags _ulong]))
(define-cstruct _soxr_quality_spec
([precision _double]
[phase_response _double]
[passband_end _double]
[stopband_begin _double]
[e _pointer]
[flags _ulong]))
(define-cstruct _soxr_runtime_spec
([log2_min_dft_size _uint]
[log2_large_dft_size _uint]
[coef_size_kbytes _uint]
[num_threads _uint]
[e _pointer]
[flags _ulong]))
;; Datatypes supported by libsoxr. The *_I values are channel-interleaved;
;; those are what resampler.rkt uses for normal PCM byte strings.
(define SOXR_FLOAT32 0)
(define SOXR_FLOAT64 1)
(define SOXR_INT32 2)
(define SOXR_INT16 3)
(define SOXR_SPLIT 4)
(define SOXR_FLOAT32_I SOXR_FLOAT32)
(define SOXR_FLOAT64_I SOXR_FLOAT64)
(define SOXR_INT32_I SOXR_INT32)
(define SOXR_INT16_I SOXR_INT16)
(define SOXR_FLOAT32_S SOXR_SPLIT)
(define SOXR_FLOAT64_S 5)
(define SOXR_INT32_S 6)
(define SOXR_INT16_S 7)
(define SOXR_TPDF 0)
(define SOXR_NO_DITHER 8)
(define SOXR_QQ 0)
(define SOXR_LQ 1)
(define SOXR_MQ 2)
(define SOXR_16_BITQ 3)
(define SOXR_20_BITQ 4)
(define SOXR_24_BITQ 5)
(define SOXR_28_BITQ 6)
(define SOXR_32_BITQ 7)
(define SOXR_HQ SOXR_20_BITQ)
(define SOXR_VHQ SOXR_28_BITQ)
(define SOXR_LINEAR_PHASE #x00)
(define SOXR_INTERMEDIATE_PHASE #x10)
(define SOXR_MINIMUM_PHASE #x30)
(define SOXR_STEEP_FILTER #x40)
(define SOXR_ROLLOFF_SMALL 0)
(define SOXR_ROLLOFF_MEDIUM 1)
(define SOXR_ROLLOFF_NONE 2)
(define SOXR_HI_PREC_CLOCK 8)
(define SOXR_DOUBLE_PRECISION 16)
(define SOXR_VR 32)
(define SOXR_COEF_INTERP_AUTO 0)
(define SOXR_COEF_INTERP_LOW 2)
(define SOXR_COEF_INTERP_HIGH 3)
(define (soxr-datatype-size t)
(case (bitwise-and t 3)
[(0) 4]
[(1) 8]
[(2) 4]
[(3) 2]
[else (error 'soxr-datatype-size "invalid datatype ~a" t)]))
(define (soxr-error-ptr->string p)
(and p (cast p _pointer _string/utf-8)))
(def-soxr soxr_version/raw (_fun -> _string/utf-8) #:c-id soxr_version)
(def-soxr soxr_io_spec/raw (_fun _int _int -> _soxr_io_spec) #:c-id soxr_io_spec)
(def-soxr soxr_quality_spec/raw (_fun _ulong _ulong -> _soxr_quality_spec) #:c-id soxr_quality_spec)
(def-soxr soxr_runtime_spec/raw (_fun _uint -> _soxr_runtime_spec) #:c-id soxr_runtime_spec)
(def-soxr soxr_create/raw
(_fun _double _double _uint
(errp : (_ptr o _pointer))
_soxr_io_spec-pointer/null
_soxr_quality_spec-pointer/null
_soxr_runtime_spec-pointer/null
-> (ctx : _soxr_t)
-> (values ctx errp))
#:c-id soxr_create)
(def-soxr soxr_process/raw
(_fun _soxr_t
_pointer _size (idone : (_ptr o _size))
_pointer _size (odone : (_ptr o _size))
-> (err : _pointer)
-> (values err idone odone))
#:c-id soxr_process)
(def-soxr soxr-delay (_fun _soxr_t -> _double) #:c-id soxr_delay)
(def-soxr soxr-clear (_fun _soxr_t -> (err : _pointer) -> (soxr-error-ptr->string err)) #:c-id soxr_clear)
(def-soxr soxr-error (_fun _soxr_t -> (err : _pointer) -> (soxr-error-ptr->string err)) #:c-id soxr_error)
(def-soxr soxr-engine (_fun _soxr_t -> _string/utf-8) #:c-id soxr_engine)
(def-soxr soxr-delete (_fun _soxr_t -> _void) #:c-id soxr_delete)
(define (soxr-available?) (and libsoxr #t))
(define (soxr-version)
(soxr_version/raw))
(define (soxr-io-spec itype otype #:scale [scale 1.0] #:flags [flags 0])
(let ((s (soxr_io_spec/raw itype otype)))
(set-soxr_io_spec-scale! s scale)
(set-soxr_io_spec-flags! s flags)
s))
(define (soxr-quality-spec recipe #:flags [flags 0])
(soxr_quality_spec/raw recipe flags))
(define (soxr-runtime-spec #:num-threads [num-threads 1])
(soxr_runtime_spec/raw num-threads))
(define (soxr-create input-rate output-rate channels #:io-spec [io-spec #f]
#:quality-spec [quality-spec #f] #:runtime-spec [runtime-spec #f])
(let-values (((ctx err) (soxr_create/raw (exact->inexact input-rate)
(exact->inexact output-rate)
channels
io-spec
quality-spec
runtime-spec)))
(values ctx (soxr-error-ptr->string err))))
(define (soxr-process ctx in ilen out olen)
(let-values (((err idone odone) (soxr_process/raw ctx in ilen out olen)))
(values (soxr-error-ptr->string err) idone odone)))
) ; end of module