* flac support
* taglib support It is possible to play some music already.
This commit is contained in:
BIN
libflac/capr24.flac
Normal file
BIN
libflac/capr24.flac
Normal file
Binary file not shown.
131
libflac/flac-decoder.rkt
Normal file
131
libflac/flac-decoder.rkt
Normal file
@@ -0,0 +1,131 @@
|
||||
(module flac-decoder racket/base
|
||||
|
||||
(require ffi/unsafe
|
||||
"libflac-ffi.rkt"
|
||||
"flac-definitions.rkt"
|
||||
"../utils/utils.rkt")
|
||||
|
||||
(provide flac-open
|
||||
flac-read
|
||||
flac-read-meta
|
||||
flac-stream-state
|
||||
(all-from-out "flac-definitions.rkt")
|
||||
test-file test-file2 test-file3
|
||||
kinds
|
||||
last-buffer last-buf-len
|
||||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Functions to do the good stuff
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define (flac-open flac-file cb-stream-info cb-audio)
|
||||
(if (file-exists? flac-file)
|
||||
(let ((handler (flac-ffi-decoder-handler)))
|
||||
(handler 'new)
|
||||
(handler 'init flac-file)
|
||||
(let ((h (make-flac-handle handler)))
|
||||
(set-flac-handle-cb-stream-info! h cb-stream-info)
|
||||
(set-flac-handle-cb-audio! h cb-audio)
|
||||
h))
|
||||
#f))
|
||||
|
||||
(define (flac-stream-state handle)
|
||||
((flac-handle-ffi-decoder-handler handle) 'state))
|
||||
|
||||
|
||||
(define kinds (make-hash))
|
||||
(define last-buffer #f)
|
||||
(define last-buf-len #f)
|
||||
(define (process-frame handle frame buffer)
|
||||
(let* ((h (flac-ffi-frame-header frame))
|
||||
(cb-audio (flac-handle-cb-audio handle))
|
||||
(ffi (flac-handle-ffi-decoder-handler handle))
|
||||
(type (hash-ref h 'number-type))
|
||||
(channels (hash-ref h 'channels))
|
||||
(block-size (hash-ref h 'blocksize)))
|
||||
(let ((buffers (ffi 'get-buffers buffer channels block-size)))
|
||||
(set! last-buffer buffers)
|
||||
(set! last-buf-len (hash-ref h 'blocksize))
|
||||
(hash-set! kinds type #t)
|
||||
(when (procedure? cb-audio)
|
||||
(cb-audio h buffers))
|
||||
))
|
||||
;(displayln "Processing frame"))
|
||||
#t
|
||||
)
|
||||
|
||||
(define (process-meta handle meta)
|
||||
(let ((type (FLAC__StreamMetadata-type meta)))
|
||||
(display (format " Got metadata type: ~a\n" type))
|
||||
(cond
|
||||
([eq? type 'streaminfo]
|
||||
(let ((mh (flac-ffi-meta meta)))
|
||||
(let ((si (make-flac-stream-info
|
||||
(hash-ref mh 'min-blocksize) (hash-ref mh 'max-blocksize)
|
||||
(hash-ref mh 'min-framesize) (hash-ref mh 'max-framesize)
|
||||
(hash-ref mh 'sample-rate)
|
||||
(hash-ref mh 'channels)
|
||||
(hash-ref mh 'bits-per-sample)
|
||||
(hash-ref mh 'total-samples))))
|
||||
(set-flac-handle-stream-info! handle si)
|
||||
(let ((cb (flac-handle-cb-stream-info handle)))
|
||||
(when (procedure? cb)
|
||||
(cb si))))))
|
||||
)
|
||||
))
|
||||
|
||||
(define (flac-read handle)
|
||||
(let* ((ffi-handler (flac-handle-ffi-decoder-handler handle))
|
||||
(state (ffi-handler 'state)))
|
||||
(letrec ((reader (lambda (frame-nr)
|
||||
(let* ((st (ffi-handler 'state)))
|
||||
(ffi-handler 'process-single)
|
||||
(unless (eq? state st)
|
||||
(set! state st)
|
||||
(displayln
|
||||
(format "Now in state ~a (frame-nr = ~a) (int-state = ~a)"
|
||||
st frame-nr (ffi-handler 'int-state)))
|
||||
)
|
||||
(when (ffi-handler 'has-errno?)
|
||||
(displayln
|
||||
(format "Error in stream: ~a" (ffi-handler 'errno)))
|
||||
)
|
||||
(when (ffi-handler 'has-meta-data?)
|
||||
(ffi-handler 'process-meta-data
|
||||
(lambda (meta) (process-meta handle meta)))
|
||||
)
|
||||
(when (ffi-handler 'has-write-data?)
|
||||
(ffi-handler 'process-write-data
|
||||
(lambda (frame buffer)
|
||||
(process-frame handle frame buffer)))
|
||||
)
|
||||
(if (eq? st 'end-of-stream)
|
||||
'end-of-stream
|
||||
(reader (+ frame-nr 1)))))
|
||||
))
|
||||
(reader 0))))
|
||||
|
||||
(define (flac-read-meta handle)
|
||||
(let* ((ffi-handler (flac-handle-ffi-decoder-handler handle))
|
||||
(state (ffi-handler 'state)))
|
||||
(while (not (or (eq? state 'read-metadata)
|
||||
(eq? state 'end-of-stream)
|
||||
(eq? state 'aborted)
|
||||
(eq? state 'memory-allocation-error)
|
||||
(eq? state 'uninitialized)))
|
||||
(ffi-handler 'process-single)
|
||||
(set! state (ffi-handler 'state))
|
||||
state)
|
||||
(if (eq? state 'read-metadata)
|
||||
(begin
|
||||
(ffi-handler 'process-meta-data
|
||||
(lambda (meta) (process-meta handle meta)))
|
||||
(flac-handle-stream-info handle))
|
||||
#f)))
|
||||
|
||||
(define test-file "C:/devel/racket/racket-sound/libflac/capr24.flac")
|
||||
(define test-file2 "C:/Muziek/Klassiek-Kamermuziek/Beethoven/Rachel Podger/01 Violin Sonata No. 1 in D Major, Op. 12 No. 1- I. Allegro con brio.flac")
|
||||
(define test-file3 "c:/Muziek/Pop/Radiohead/The Best of Radiohead (2008)/02. Paranoid Android.flac")
|
||||
|
||||
); end of module
|
||||
99
libflac/flac-definitions.rkt
Normal file
99
libflac/flac-definitions.rkt
Normal file
@@ -0,0 +1,99 @@
|
||||
(module flac-definitions racket/base
|
||||
|
||||
(provide flac-stream-info
|
||||
make-flac-stream-info
|
||||
flac-stream-info->string
|
||||
|
||||
flac-handle
|
||||
make-flac-handle
|
||||
flac-handle-ffi-decoder-handler
|
||||
flac-handle-stream-info
|
||||
set-flac-handle-stream-info!
|
||||
flac-handle-cb-stream-info
|
||||
set-flac-handle-cb-stream-info!
|
||||
flac-handle-cb-audio
|
||||
set-flac-handle-cb-audio!
|
||||
|
||||
flac-handle->string
|
||||
|
||||
flac-sample-rate
|
||||
flac-channels
|
||||
flac-bits-per-sample
|
||||
flac-total-samples
|
||||
flac-duration
|
||||
)
|
||||
|
||||
(define-struct flac-stream-info
|
||||
(min-blocksize max-blocksize
|
||||
min-framesize max-framesize
|
||||
sample-rate
|
||||
channels
|
||||
bits-per-sample
|
||||
total-samples
|
||||
))
|
||||
|
||||
(define (flac-stream-info->string si)
|
||||
(format "sample-rate: ~a, channels: ~a, bits-per-sample: ~a, total-samples: ~a"
|
||||
(flac-stream-info-sample-rate si)
|
||||
(flac-stream-info-channels si)
|
||||
(flac-stream-info-bits-per-sample si)
|
||||
(flac-stream-info-total-samples si)))
|
||||
|
||||
(define (flac-sample-rate h)
|
||||
(let ((si (flac-handle-stream-info h)))
|
||||
(if (eq? si #f)
|
||||
#f
|
||||
(flac-stream-info-sample-rate si))))
|
||||
|
||||
(define (flac-channels h)
|
||||
(let ((si (flac-handle-stream-info h)))
|
||||
(if (eq? si #f)
|
||||
#f
|
||||
(flac-stream-info-channels si))))
|
||||
|
||||
(define (flac-bits-per-sample h)
|
||||
(let ((si (flac-handle-stream-info h)))
|
||||
(if (eq? si #f)
|
||||
#f
|
||||
(flac-stream-info-bits-per-sample si))))
|
||||
|
||||
(define (flac-total-samples h)
|
||||
(let ((si (flac-handle-stream-info h)))
|
||||
(if (eq? si #f)
|
||||
#f
|
||||
(flac-stream-info-total-samples si))))
|
||||
|
||||
(define (flac-handle->string h)
|
||||
(let* ((si (flac-handle-stream-info h))
|
||||
(ffi (flac-handle-ffi-decoder-handler h))
|
||||
(ff (ffi 'file)))
|
||||
(string-append
|
||||
(if (eq? ff #f)
|
||||
"no flac file available\n"
|
||||
(format "Flac File: ~a\n" ff))
|
||||
(if (eq? si #f)
|
||||
"no stream info available\n"
|
||||
(string-append
|
||||
(format "Stream Info: ~a\n" (flac-stream-info->string si))
|
||||
(format "Duration in seconds: ~a\n" (flac-duration h))))
|
||||
)))
|
||||
|
||||
(define (flac-duration h)
|
||||
(let* ((si (flac-handle-stream-info h)))
|
||||
(if (eq? si #f)
|
||||
#f
|
||||
(let* ((total-samples (flac-stream-info-total-samples si))
|
||||
(sample-rate (flac-stream-info-sample-rate si)))
|
||||
(inexact->exact (round (/ total-samples sample-rate)))))))
|
||||
|
||||
(define-struct flac-handle
|
||||
(
|
||||
ffi-decoder-handler
|
||||
[cb-stream-info #:auto #:mutable]
|
||||
[cb-audio #:auto #:mutable]
|
||||
[stream-info #:auto #:mutable]
|
||||
)
|
||||
#:auto-value #f
|
||||
)
|
||||
|
||||
); end of module
|
||||
BIN
libflac/flac.exe
Normal file
BIN
libflac/flac.exe
Normal file
Binary file not shown.
@@ -1 +1,591 @@
|
||||
#lang racket/base
|
||||
;#lang racket/base
|
||||
(module libflac-ffi racket/base
|
||||
|
||||
(require ffi/unsafe
|
||||
ffi/unsafe/define
|
||||
setup/dirs
|
||||
"../utils/utils.rkt"
|
||||
)
|
||||
|
||||
(provide flac-ffi-decoder-handler
|
||||
_FLAC__StreamMetadata
|
||||
FLAC__StreamMetadata-type
|
||||
flac-ffi-meta
|
||||
flac-ffi-frame-header
|
||||
FLAC__uint32-pointer
|
||||
FLAC__int32**
|
||||
)
|
||||
|
||||
(define-ffi-definer define-libflac
|
||||
(ffi-lib "libFLAC" '(#f)
|
||||
#:get-lib-dirs (lambda ()
|
||||
(cons (build-path ".") (get-lib-search-dirs)))
|
||||
#:fail (lambda ()
|
||||
(ffi-lib (get-lib-path "libFLAC.dll")))
|
||||
))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Some FLAC Constants
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define FLAC__MAX_CHANNELS 8)
|
||||
(define FLAC__MAX_FIXED_ORDER 4)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; FLAC Integer types
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define _uint32_t _uint32)
|
||||
(define _uint64_t _uint64)
|
||||
(define FLAC__uint8 _uint8)
|
||||
(define FLAC__uint16 _uint16)
|
||||
(define FLAC__int64 _int64)
|
||||
(define FLAC__uint64 _uint64)
|
||||
(define FLAC__uint32 _uint32)
|
||||
(define FLAC__int32-pointer (_ptr i _int32))
|
||||
(define FLAC__int32** (_ptr i (_ptr i _int32)))
|
||||
(define FLAC__uint32-pointer (_ptr i _uint32))
|
||||
(define FLAC__int64-pointer (_ptr i _int64))
|
||||
(define FLAC__uint64-pointer (_ptr i _uint64))
|
||||
(define FLAC__bool _int)
|
||||
(define FLAC__byte _uint8)
|
||||
(define FLAC__byte-pointer (_ptr i FLAC__byte))
|
||||
(define _uint32_1bit_t _uint32)
|
||||
(define _char _int8)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; FLAC enumerations
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define _FLAC__ChannelAssignment
|
||||
(_enum '(independent = 0
|
||||
left-side = 1
|
||||
right-side = 2
|
||||
mid-side = 3
|
||||
)))
|
||||
|
||||
(define _FLAC__FrameNumberType
|
||||
(_enum '(frame-number
|
||||
sample-number
|
||||
)))
|
||||
|
||||
(define _FLAC__SubframeType
|
||||
(_enum '(constant = 0
|
||||
verbatim = 1
|
||||
fixed = 2
|
||||
lpc = 3
|
||||
)))
|
||||
|
||||
(define _FLAC__MetadataType
|
||||
(_enum '(streaminfo = 0
|
||||
padding = 1
|
||||
application = 2
|
||||
seektable = 3
|
||||
vorbis-comment = 4
|
||||
cuesheet = 5
|
||||
picture = 6
|
||||
undefined = 7
|
||||
max--metadata-type-code = 126
|
||||
)))
|
||||
|
||||
(define _FLAC_StreamMetadata_Picture_Type
|
||||
(_enum '(other = 0
|
||||
file-icon-standard = 1
|
||||
file-icon = 2
|
||||
front-cover = 3
|
||||
back-cover = 4
|
||||
leaflet-page = 5
|
||||
media = 6
|
||||
lead-artist = 7
|
||||
artist = 8
|
||||
conductor = 9
|
||||
band = 10
|
||||
composer = 11
|
||||
lyricist = 12
|
||||
recording-location = 13
|
||||
during-recording = 14
|
||||
during-performance = 15
|
||||
video-screen-capture = 16
|
||||
fish = 17
|
||||
illustration = 18
|
||||
band-logotype = 19
|
||||
publisher-logotype = 20
|
||||
undefined
|
||||
)))
|
||||
|
||||
|
||||
;typedef enum {
|
||||
; FLAC__STREAM_DECODER_SEARCH_FOR_METADATA = 0,
|
||||
; FLAC__STREAM_DECODER_READ_METADATA,
|
||||
; FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC,
|
||||
; FLAC__STREAM_DECODER_READ_FRAME,
|
||||
; FLAC__STREAM_DECODER_END_OF_STREAM,
|
||||
; FLAC__STREAM_DECODER_OGG_ERROR,
|
||||
; FLAC__STREAM_DECODER_SEEK_ERROR,
|
||||
; FLAC__STREAM_DECODER_ABORTED,
|
||||
; FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
|
||||
; FLAC__STREAM_DECODER_UNINITIALIZED,
|
||||
; FLAC__STREAM_DECODER_END_OF_LINK
|
||||
;} FLAC__StreamDecoderState;
|
||||
|
||||
(define _FLAC_StreamDecoderState
|
||||
(_enum '(search-for-metadata = 0
|
||||
read-metadata
|
||||
search-for-frame-sync
|
||||
read-frames
|
||||
end-of-stream
|
||||
ogg-error
|
||||
seek-error
|
||||
aborted
|
||||
memory-allocation-error
|
||||
uninitialized
|
||||
end-of-link
|
||||
)))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; FLAC Frames
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-cstruct _FLAC__FrameHeader (
|
||||
[blocksize _uint32_t]
|
||||
[sample_rate _uint32_t]
|
||||
[channels _uint32_t]
|
||||
[channel_assignment _FLAC__ChannelAssignment]
|
||||
[bits_per_sample _uint32_t]
|
||||
[number_type _FLAC__FrameNumberType]
|
||||
[number (_union _uint32_t _uint64_t)]
|
||||
[crc FLAC__uint8]
|
||||
))
|
||||
|
||||
(define (flac-ffi-frame-header frame)
|
||||
(let* ((hdr (FLAC__Frame-header frame))
|
||||
(h (make-hash)))
|
||||
(for-each
|
||||
(lambda (e)
|
||||
(hash-set! h (car e) (cdr e)))
|
||||
(list
|
||||
(cons 'blocksize (FLAC__FrameHeader-blocksize hdr))
|
||||
(cons 'sample-rate (FLAC__FrameHeader-sample_rate hdr))
|
||||
(cons 'channels (FLAC__FrameHeader-channels hdr))
|
||||
(cons 'channel-assignment (FLAC__FrameHeader-channel_assignment hdr))
|
||||
(cons 'bits-per-sample (FLAC__FrameHeader-bits_per_sample hdr))
|
||||
(cons 'number-type (FLAC__FrameHeader-number_type hdr))
|
||||
(cons 'number (if (eq? (FLAC__FrameHeader-number_type hdr) 'frame-number)
|
||||
(union-ref (FLAC__FrameHeader-number hdr) 0)
|
||||
(union-ref (FLAC__FrameHeader-number hdr) 1)))
|
||||
(cons 'crc (FLAC__FrameHeader-crc hdr)))
|
||||
)
|
||||
h))
|
||||
|
||||
(define-cstruct _FLAC__FrameFooter (
|
||||
[crc FLAC__uint16]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__Subframe_Constant (
|
||||
[value FLAC__int64]
|
||||
))
|
||||
|
||||
(define _FLAC__VerbatimSubframeDataType
|
||||
(_enum '(int32
|
||||
int64)))
|
||||
|
||||
(define-cstruct _FLAC__Subframe_Verbatim (
|
||||
[data (_union
|
||||
FLAC__int32-pointer
|
||||
FLAC__int64-pointer
|
||||
)]
|
||||
[data_type _FLAC__VerbatimSubframeDataType]
|
||||
))
|
||||
|
||||
|
||||
(define FLAC__EntropyCodingMethodType
|
||||
(_enum '(partitioned-rice = 0
|
||||
partitioned-rice2 = 1)))
|
||||
|
||||
(define-cstruct _FLAC__EntropyCodingMethod_PartitionedRiceContents
|
||||
(
|
||||
[parameters FLAC__uint32-pointer]
|
||||
[raw_bits FLAC__uint32-pointer]
|
||||
[capacity_by_order FLAC__uint32-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__EntropyCodingMethod_PartitionedRice
|
||||
(
|
||||
[order _uint32_t]
|
||||
[contents _FLAC__EntropyCodingMethod_PartitionedRiceContents-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__EntropyCodingMethod
|
||||
(
|
||||
[type FLAC__EntropyCodingMethodType]
|
||||
[data (_union _FLAC__EntropyCodingMethod_PartitionedRice)]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__Subframe_Fixed (
|
||||
[entropy_coding_method _FLAC__EntropyCodingMethod]
|
||||
[order _uint32_t]
|
||||
[warmup (_array FLAC__int64 FLAC__MAX_FIXED_ORDER)]
|
||||
[residual FLAC__int32-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__Subframe_LPC (
|
||||
[jaja _int]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__Subframe (
|
||||
[type _FLAC__SubframeType]
|
||||
[data (_union
|
||||
_FLAC__Subframe_Constant
|
||||
_FLAC__Subframe_Fixed
|
||||
_FLAC__Subframe_LPC
|
||||
_FLAC__Subframe_Verbatim
|
||||
)]
|
||||
[wated_bits _uint32_t]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__Frame (
|
||||
[header _FLAC__FrameHeader]
|
||||
[subframes (_array _FLAC__Subframe FLAC__MAX_CHANNELS)]
|
||||
[footer _FLAC__FrameFooter]
|
||||
))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; FLAC Metadata
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;typedef struct FLAC__StreamMetadata {
|
||||
; FLAC__MetadataType type;
|
||||
; FLAC__bool is_last;
|
||||
; uint32_t length;
|
||||
; union {
|
||||
; FLAC__StreamMetadata_StreamInfo stream_info;
|
||||
; FLAC__StreamMetadata_Padding padding;
|
||||
; FLAC__StreamMetadata_Application application;
|
||||
; FLAC__StreamMetadata_SeekTable seek_table;
|
||||
; FLAC__StreamMetadata_VorbisComment vorbis_comment;
|
||||
; FLAC__StreamMetadata_CueSheet cue_sheet;
|
||||
; FLAC__StreamMetadata_Picture picture;
|
||||
; FLAC__StreamMetadata_Unknown unknown;
|
||||
; } data;
|
||||
;} FLAC__StreamMetadata;
|
||||
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_StreamInfo
|
||||
(
|
||||
[min_blocksize _uint32_t]
|
||||
[max_blocksize _uint32_t]
|
||||
[min_framesize _uint32_t]
|
||||
[max_framesize _uint32_t]
|
||||
[sample_rate _uint32_t]
|
||||
[channels _uint32_t]
|
||||
[bits_per_sample _uint32_t]
|
||||
[total_samples FLAC__uint64]
|
||||
[md5sum (_array FLAC__byte 16)]
|
||||
))
|
||||
|
||||
(define (meta-stream-info si . hash)
|
||||
(let ((h (if (null? hash) (make-hash) (car hash))))
|
||||
(hash-set! h 'min-blocksize (FLAC__StreamMetadata_StreamInfo-min_blocksize si))
|
||||
(hash-set! h 'max-blocksize (FLAC__StreamMetadata_StreamInfo-max_blocksize si))
|
||||
(hash-set! h 'min-framesize (FLAC__StreamMetadata_StreamInfo-min_framesize si))
|
||||
(hash-set! h 'max-framesize (FLAC__StreamMetadata_StreamInfo-max_framesize si))
|
||||
(hash-set! h 'sample-rate (FLAC__StreamMetadata_StreamInfo-sample_rate si))
|
||||
(hash-set! h 'channels (FLAC__StreamMetadata_StreamInfo-channels si))
|
||||
(hash-set! h 'bits-per-sample (FLAC__StreamMetadata_StreamInfo-bits_per_sample si))
|
||||
(hash-set! h 'total-samples (FLAC__StreamMetadata_StreamInfo-total_samples si))
|
||||
h))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_Padding
|
||||
(
|
||||
[dummy _int]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_Application
|
||||
(
|
||||
[id (_array FLAC__byte 4)]
|
||||
[data FLAC__byte-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_SeekPoint
|
||||
(
|
||||
[sample_number FLAC__uint64]
|
||||
[stream_offset FLAC__uint64]
|
||||
[frame_samples _uint32_t]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_SeekTable
|
||||
(
|
||||
[num_points _uint32_t]
|
||||
[points _FLAC__StreamMetadata_SeekPoint-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_VorbisComment_Entry
|
||||
(
|
||||
[length FLAC__uint32]
|
||||
[entry FLAC__byte-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_VorbisComment
|
||||
(
|
||||
[vendor_string _FLAC__StreamMetadata_VorbisComment_Entry]
|
||||
[num_comments FLAC__uint32]
|
||||
[comments _FLAC__StreamMetadata_VorbisComment_Entry-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_CueSheet_Index
|
||||
(
|
||||
[offset FLAC__uint64]
|
||||
[number FLAC__byte]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_CueSheet_Track
|
||||
(
|
||||
[offset FLAC__uint64]
|
||||
[number FLAC__byte]
|
||||
[isrc (_array _char 13)]
|
||||
[type _uint32_1bit_t]
|
||||
[pre_emphasis _uint32_1bit_t]
|
||||
[num_indices FLAC__byte]
|
||||
[indices _FLAC__StreamMetadata_CueSheet_Index-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_CueSheet
|
||||
(
|
||||
[media_catalog_number (_array _char 129)]
|
||||
[lead_in FLAC__uint64]
|
||||
[is_cd FLAC__bool]
|
||||
[num_tracks _uint32_t]
|
||||
[tracks _FLAC__StreamMetadata_CueSheet_Track-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_Picture
|
||||
(
|
||||
[type _FLAC_StreamMetadata_Picture_Type]
|
||||
[mime_type _string/utf-8]
|
||||
[description FLAC__byte-pointer]
|
||||
[width FLAC__uint32]
|
||||
[height FLAC__uint32]
|
||||
[depth FLAC__uint32]
|
||||
[colors FLAC__uint32]
|
||||
[data_length FLAC__uint32]
|
||||
[date FLAC__byte-pointer]
|
||||
))
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata_Unknown
|
||||
(
|
||||
[data FLAC__byte-pointer]
|
||||
))
|
||||
|
||||
|
||||
(define-cstruct _FLAC__StreamMetadata
|
||||
(
|
||||
[type _FLAC__MetadataType]
|
||||
[is_last FLAC__bool]
|
||||
[length _uint32_t]
|
||||
[data (_union
|
||||
_FLAC__StreamMetadata_StreamInfo
|
||||
_FLAC__StreamMetadata_Padding
|
||||
_FLAC__StreamMetadata_Application
|
||||
_FLAC__StreamMetadata_SeekTable
|
||||
_FLAC__StreamMetadata_VorbisComment
|
||||
_FLAC__StreamMetadata_CueSheet
|
||||
_FLAC__StreamMetadata_Picture
|
||||
_FLAC__StreamMetadata_Unknown
|
||||
)]
|
||||
))
|
||||
|
||||
(define (flac-ffi-meta meta)
|
||||
(let ((type (FLAC__StreamMetadata-type meta))
|
||||
(h (make-hash)))
|
||||
(cond
|
||||
([eq? type 'streaminfo]
|
||||
(meta-stream-info (union-ref (FLAC__StreamMetadata-data meta) 0) h))
|
||||
(else (error (format "Cannot process metadata: ~a" type)))
|
||||
)
|
||||
h))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; FLAC Generic Pointer Definitions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define _FLAC__StreamDecoder-pointer (_cpointer 'flac-streamdecoder))
|
||||
(define _FLAC__Data-pointer (_cpointer 'flac-client-data))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; FLAC Callback function definitions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
;typedef FLAC__StreamDecoderWriteStatus(* FLAC__StreamDecoderWriteCallback) (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
|
||||
(define _FLAC__StreamDecoderWriteCallback
|
||||
(_fun _FLAC__StreamDecoder-pointer
|
||||
_FLAC__Frame-pointer
|
||||
FLAC__int32**
|
||||
_FLAC__Data-pointer -> _int))
|
||||
|
||||
;typedef void(* FLAC__StreamDecoderMetadataCallback) (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
||||
(define _FLAC__StreamDecoderMetadataCallback
|
||||
(_fun _FLAC__StreamDecoder-pointer
|
||||
_FLAC__StreamMetadata-pointer
|
||||
_FLAC__Data-pointer -> _void))
|
||||
|
||||
(define _FLAC__StreamDecoderErrorCallback
|
||||
(_fun _FLAC__StreamDecoder-pointer
|
||||
_int
|
||||
_FLAC__Data-pointer -> _void))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Exported FLAC functions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-libflac FLAC__stream_decoder_new
|
||||
(_fun -> _FLAC__StreamDecoder-pointer))
|
||||
|
||||
(define-libflac FLAC__stream_decoder_delete
|
||||
(_fun _FLAC__StreamDecoder-pointer -> _void))
|
||||
|
||||
(define-libflac FLAC__stream_decoder_get_state
|
||||
(_fun _FLAC__StreamDecoder-pointer -> _int))
|
||||
|
||||
(define states (make-hash))
|
||||
(hash-set! states 0 'search-for-metadata)
|
||||
(hash-set! states 1 'read-metadata)
|
||||
(hash-set! states 2 'search-for-frame-sync)
|
||||
(hash-set! states 3 'read-frames)
|
||||
(hash-set! states 4 'end-of-stream)
|
||||
(hash-set! states 5 'ogg-error)
|
||||
(hash-set! states 6 'seek-error)
|
||||
(hash-set! states 7 'aborted)
|
||||
(hash-set! states 8 'memory-allocation-error)
|
||||
(hash-set! states 9 'uninitialized)
|
||||
(hash-set! states 10 'end-of-link)
|
||||
|
||||
(define (decoder-state int-st)
|
||||
(hash-ref states int-st #f))
|
||||
|
||||
|
||||
(define-libflac FLAC__stream_decoder_init_file
|
||||
(_fun _FLAC__StreamDecoder-pointer
|
||||
_string/utf-8
|
||||
_FLAC__StreamDecoderWriteCallback
|
||||
_FLAC__StreamDecoderMetadataCallback
|
||||
_FLAC__StreamDecoderErrorCallback
|
||||
-> _int))
|
||||
|
||||
(define-libflac FLAC__stream_decoder_process_single
|
||||
(_fun _FLAC__StreamDecoder-pointer
|
||||
-> _bool))
|
||||
|
||||
(define-libflac FLAC__stream_decoder_process_until_end_of_metadata
|
||||
(_fun _FLAC__StreamDecoder-pointer
|
||||
-> _bool))
|
||||
|
||||
(define-libflac FLAC__stream_decoder_seek_absolute
|
||||
(_fun _FLAC__StreamDecoder-pointer FLAC__uint64
|
||||
-> _bool))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Our interface for decoding to racket
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define (flac-ffi-decoder-handler)
|
||||
(define write-data '())
|
||||
(define meta-data '())
|
||||
(define error-no -1)
|
||||
(define fl #f)
|
||||
(define flac-file #f)
|
||||
|
||||
(define (write-callback fl frame buffer data)
|
||||
(set! write-data (append write-data (list (cons frame buffer))))
|
||||
0)
|
||||
|
||||
(define (meta-callback fl meta data)
|
||||
(set! meta-data (append meta-data (list meta))))
|
||||
|
||||
(define (error-callback fl errno data)
|
||||
(set! error-no errno)
|
||||
)
|
||||
|
||||
(define (new)
|
||||
(set! fl (FLAC__stream_decoder_new))
|
||||
fl)
|
||||
|
||||
(define (init file)
|
||||
(let ((r (FLAC__stream_decoder_init_file
|
||||
fl
|
||||
file
|
||||
write-callback
|
||||
meta-callback
|
||||
error-callback)))
|
||||
(set! flac-file file)
|
||||
r))
|
||||
|
||||
(define (process-single)
|
||||
(FLAC__stream_decoder_process_single fl))
|
||||
|
||||
(define (int-state)
|
||||
(FLAC__stream_decoder_get_state fl))
|
||||
|
||||
(define (state)
|
||||
(decoder-state (int-state)))
|
||||
|
||||
(define (process-meta-data cb)
|
||||
(for-each cb meta-data)
|
||||
(set! meta-data '()))
|
||||
|
||||
(define (process-write-data cb)
|
||||
(for-each (lambda (d)
|
||||
(cb (car d) (cdr d)))
|
||||
write-data)
|
||||
(set! write-data '()))
|
||||
|
||||
(define (buffer->vectorlist buffer channels size)
|
||||
(letrec ((for-channels
|
||||
(lambda (channel)
|
||||
(if (< channel channels)
|
||||
(letrec ((v (make-vector size 0))
|
||||
(p (ptr-ref buffer FLAC__int32-pointer channel))
|
||||
(to-vec (lambda (i)
|
||||
(when (< i size)
|
||||
(vector-set! v i (ptr-ref p _int32 i))
|
||||
(to-vec (+ i 1)))))
|
||||
)
|
||||
(to-vec 0)
|
||||
(cons v (for-channels (+ channel 1))))
|
||||
'())))
|
||||
)
|
||||
(for-channels 0)))
|
||||
|
||||
(define (seek-to-sample sample)
|
||||
(FLAC__stream_decoder_seek_absolute fl sample))
|
||||
|
||||
(lambda (cmd . args)
|
||||
(cond
|
||||
[(eq? cmd 'write-data) write-data]
|
||||
[(eq? cmd 'meta-data) meta-data]
|
||||
|
||||
[(eq? cmd 'new) (new)]
|
||||
[(eq? cmd 'init) (init (car args))]
|
||||
[(eq? cmd 'process-single) (process-single)]
|
||||
[(eq? cmd 'get-buffers) (buffer->vectorlist (car args) (cadr args) (caddr args))]
|
||||
|
||||
[(eq? cmd 'int-state) (int-state)]
|
||||
[(eq? cmd 'state) (state)]
|
||||
|
||||
[(eq? cmd 'has-write-data?) (not (null? write-data))]
|
||||
[(eq? cmd 'has-meta-data?) (not (null? meta-data))]
|
||||
[(eq? cmd 'has-errno?) (not (= error-no -1))]
|
||||
|
||||
[(eq? cmd 'process-meta-data) (process-meta-data (car args))]
|
||||
[(eq? cmd 'process-write-data) (process-write-data (car args))]
|
||||
[(eq? cmd 'errno) error-no]
|
||||
|
||||
[(eq? cmd 'seek-to-sample) (seek-to-sample (car args))]
|
||||
[(eq? cmd 'file) flac-file]
|
||||
|
||||
[else (error (format "unknown command ~a" cmd))]
|
||||
))
|
||||
)
|
||||
|
||||
); end of module
|
||||
BIN
libflac/metaflac.exe
Normal file
BIN
libflac/metaflac.exe
Normal file
Binary file not shown.
Reference in New Issue
Block a user