256 lines
7.9 KiB
Racket
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
|