Coverage report: /home/ellis/comp/core/ffi/sndfile/pkg.lisp

KindCoveredAll%
expression1999 19.2
branch00nil
Key
Not instrumented
Conditionalized out
Executed
Not executed
 
Both branches taken
One branch taken
Neither branch taken
1
 ;;; sndfile.lisp --- low-level bindings to SNDFILE
2
 
3
 ;;; Commentary:
4
 
5
 ;; see http://www.mega-nerd.com/libsndfile/api.html
6
 
7
 ;;; Code:
8
 (defpackage :sndfile
9
   (:use :cl :std :sb-alien)
10
   (:export :sf-version-string :load-sndfile :sndfile 
11
    :sf-chunk-iterator :sf-info :samplerate :channels 
12
    :frames :format :sections :seekable
13
    :sf-format-info :extension :sf-seek-mode :sf-dither
14
    :sf-cue-point :sf-loop :sf-instrument :sf-loop-info
15
    :sf-format :sf-format-subtype :sf-flag :sf-flag*
16
    :sf-err :sf-err* :sf-command-op :sf-command
17
    :sf-open
18
    :sf-open-fd
19
    :sf-error
20
    :sf-strerror
21
    :sf-error-number
22
    :sf-perror
23
    :sf-error-str
24
    :sf-format-check
25
    :sf-seek
26
    :sf-set-string
27
    :sf-get-string
28
    :sf-current-byterate
29
    :sf-read-raw
30
    :sf-write-raw
31
    :sf-close
32
    :sf-write-sync
33
    :sf-chunk-info
34
    :sf-set-chunk
35
    :sf-get-chunk-iterator
36
    :sf-next-chunk-iterator
37
    :sf-get-chunk-size
38
    :sf-get-chunk-data
39
    :decode-sf-format
40
    :encode-sf-format
41
    :sf-str
42
    :sf-format-mask
43
    :with-sndfile
44
    :with-sf-info
45
    :sf-readf-float
46
    :sf-writef-float
47
    :sf-writef-double
48
    :sf-readf-double
49
    :sf-writef-short
50
    :sf-readf-short))
51
 
52
 (in-package :sndfile)
53
 
54
 (define-alien-loader sndfile "/usr/lib/")
55
 
56
 (define-opaque sndfile)
57
 (define-opaque sf-chunk-iterator)
58
 
59
 (define-alien-type sf-count long)
60
 
61
 (define-alien-type sf-info
62
     (struct sf-info
63
       (frames sf-count)
64
       (samplerate int)
65
       (channels int)
66
       (format int)
67
       (sections int)
68
       (seekable int)))
69
 
70
 (define-alien-type sf-format-info
71
     (struct sf-format-info
72
       (format int)
73
       (name c-string)
74
       (extension c-string)))
75
 
76
 ;; SF_SEEK_*
77
 (define-alien-enum (sf-seek-mode int)
78
   :set 0
79
   :cur 1
80
   :end 2)
81
 
82
 ;; SFD_*
83
 (define-alien-enum (sf-dither int)
84
   :default-level 0
85
   :custom-level #x40000000
86
   :no-dither 500
87
   :white 501
88
   :triangular-pdf 502)
89
 
90
 (define-alien-type sf-dither-info
91
     (struct sf-dither-info
92
       (type int)
93
       (level double)
94
       (name c-string)))
95
 
96
 (define-alien-type sf-embed-file-info
97
     (struct sf-embed-file-info
98
       (offset sf-count)
99
       (length sf-count)))
100
 
101
 (define-alien-type sf-cue-point
102
     (struct sf-cue-point
103
       (indx int)
104
       (position unsigned-int)
105
       (fcc-chunk int)
106
       (chunk-start int)
107
       (block-start int)
108
       (sample-offset unsigned-int)
109
       (name (array char 256))))
110
 
111
 (define-alien-enum (sf-loop int)
112
   :none 800
113
   :forward 801
114
   :backward 802
115
   :alternating 803)
116
 
117
 (define-alien-type sf-instrument
118
     (struct sf-instrument
119
       (gain int)
120
       (detune char)
121
       (basenote char)
122
       (velocity-lo char)
123
       (velocity-hi char)
124
       (key-lo char)
125
       (key-hi char)
126
       (loop-count int)
127
       (loops (array
128
               (struct nil
129
                 (mode int)
130
                 (start unsigned-int)
131
                 (end unsigned-int)
132
                 (count unsigned-int))
133
               16))))
134
 
135
 (define-alien-type sf-loop-info
136
     (struct sf-loop-info
137
       (time-sig-num short)
138
       (time-sig-den short)
139
       (loop-mode int)
140
       (num-beats int)
141
       (bpm float)
142
       (root-key int)
143
       (future (array int 6))))
144
 
145
 (define-alien-enum (sf-format int)
146
   :wav #x010000               ; Microsoft WAV format (little endian default). 
147
   :aiff #x020000               ; Apple/SGI AIFF format (big endian). 
148
   :au #x030000               ; Sun/NeXT AU format (big endian). 
149
   :raw #x040000               ; RAW PCM data. 
150
   :paf #x050000               ; Ensoniq PARIS file format. 
151
   :svx #x060000               ; Amiga IFF / SVX8 / SV16 format. 
152
   :nist #x070000               ; Sphere NIST format. 
153
   :voc #x080000               ; VOC files. 
154
   :ircam #x0A0000               ; Berkeley/IRCAM/CARL 
155
   :w64 #x0B0000               ; Sonic Foundry's 64 bit RIFF/WAV 
156
   :mat4 #x0C0000               ; Matlab (tm) V4.2 / GNU Octave 2.0 
157
   :mat5 #x0D0000               ; Matlab (tm) V5.0 / GNU Octave 2.1 
158
   :pvf #x0E0000               ; Portable Voice Format 
159
   :xi #x0F0000               ; Fasttracker 2 Extended Instrument 
160
   :htk #x100000               ; HMM Tool Kit format 
161
   :sds #x110000               ; Midi Sample Dump Standard 
162
   :avr #x120000               ; Audio Visual Research 
163
   :wavex #x130000               ; MS WAVE with WAVEFORMATEX 
164
   :sd2 #x160000               ; Sound Designer 2 
165
   :flac #x170000               ; FLAC lossless file format 
166
   :caf #x180000)               ; Core Audio File format 
167
 
168
 (define-alien-enum (sf-format-subtype int)
169
   ;; subtypes
170
   :pcm-s8 #x0001                 ; Signed 8 bit data 
171
   :pcm-16 #x0002                 ; Signed 16 bit data 
172
   :pcm-24 #x0003                 ; Signed 24 bit data 
173
   :pcm-32 #x0004                 ; Signed 32 bit data 
174
   :pcm-u8 #x0005                 ; Unsigned 8 bit data (WAV and RAW only) 
175
 
176
   :float #x0006                 ; 32 bit float data 
177
   :double #x0007                 ; 64 bit float data 
178
 
179
   :ulaw #x0010                 ; U-Law encoded. 
180
   :alaw #x0011                 ; A-Law encoded. 
181
   :ima-adpcm #x0012                 ; IMA ADPCM. 
182
   :ms-adpcm #x0013                 ; Microsoft ADPCM. 
183
 
184
   :gsm610 #x0020                 ; GSM 6.10 encoding. 
185
   :vox-adpcm #x0021                 ; OKI / Dialogix ADPCM 
186
 
187
   :g721-32 #x0030                 ; 32kbs G721 ADPCM encoding. 
188
   :g723-24 #x0031                 ; 24kbs G723 ADPCM encoding. 
189
   :g723-40 #x0032                 ; 40kbs G723 ADPCM encoding. 
190
   :-dwvw-12 #x0040                 ; 12 bit Delta Width Variable Word encoding. 
191
   :dwvw-16 #x0041                 ; 16 bit Delta Width Variable Word encoding. 
192
   :dwvw-24 #x0042                 ; 24 bit Delta Width Variable Word encoding. 
193
   :dwvw-n #x0043                 ; N bit Delta Width Variable Word encoding. 
194
 
195
   :dpcm-8 #x0050                 ; 8 bit differential PCM (XI only)
196
   :dpcm-16 #x0051)                 ; 16 bit differential PCM (XI only)
197
 
198
 ;;;; Endian-ness options. 
199
 (define-alien-enum (sf-endian int)
200
   :file #x00000000     ; Default file endian-ness. 
201
   :little #x10000000     ; Force little endian-ness. 
202
   :big #x20000000     ; Force big endian-ness. 
203
   :cpu #x30000000)     ; Force CPU endian-ness. 
204
 
205
 (define-alien-enum (sf-format-mask int)
206
   :sub #x0000FFFF
207
   :type #x0FFF0000
208
   :end #x30000000)
209
 
210
 (define-alien-enum (sf-str int)
211
   :title 1
212
   :copyright 2
213
   :software 3
214
   :artist 4
215
   :comment 5
216
   :date 6)
217
 
218
 (define-alien-enum (sf-flag int)
219
   :false 0
220
   :true 1
221
   :read #x10
222
   :write #x20
223
   :rdwr #x30
224
   :ambisonic-none #x40
225
   :ambisonic-b-format #x41)
226
 
227
 ;;;; Public error numbers
228
 (define-alien-enum (sf-err int)
229
   :no-error 0
230
   :unrecognized-format 1
231
   :system 2
232
   :malformed-file 3
233
   :unsupported-encoding 4)
234
 
235
 ;;;; SF commands
236
 (define-alien-enum (sf-command-op int)
237
   :get-lib-version #x1000
238
   :get-log-info #x1001
239
   :get-current-sf-info #x1002
240
   :get-norm-double #x1010
241
   :get-norm-float #x1011
242
   :set-norm-double #x1012
243
   :set-norm-float #x1013
244
   :set-scale-float-int-read #x1014
245
   :set-scale-int-float-write #x1015
246
   :get-simple-format-count #x1020
247
   :get-simple-format #x1021
248
   :get-format-info #x1028
249
   :get-format-major-count #x1030
250
   :get-format-major #x1031
251
   :get-format-subtype-count #x1032
252
   :get-format-subtype #x1033
253
   :calc-signal-max #x1040
254
   :calc-norm-signal-max #x1041
255
   :calc-max-all-channels #x1042
256
   :calc-norm-max-all-channels #x1043
257
   :get-signal-max #x1044
258
   :get-max-all-channels #x1045
259
   :set-add-peak-chunk #x1050
260
   :update-header-now #x1060
261
   :set-update-header-auto #x1061
262
   :file-truncate #x1080
263
   :set-raw-start-offset #x1090
264
   ;; /* Commands reserved for dithering, which is not implemented. */
265
   :set-dither-on-write #x10A0
266
   :set-dither-on-read #x10A1
267
   :get-dither-info-count #x10A2
268
   :get-dither-info #x10A3
269
   :get-embed-file-info #x10B0
270
   :set-clipping #x10C0
271
   :get-clipping #x10C1
272
   :get-cue-count #x10CD
273
   :get-cue #x10CE
274
   :set-cue #x10CF
275
   :get-instrument #x10D0
276
   :set-instrument #x10D1
277
   :get-loop-info #x10E0
278
   :get-broadcast-info #x10F0
279
   :set-broadcast-info #x10F1
280
   :get-channel-map-info #x1100
281
   :set-channel-map-info #x1101
282
   :raw-data-needs-endswap #x1110
283
   ;; /* Support for Wavex Ambisonics Format */
284
   :wavex-set-ambisonic #x1200
285
   :wavex-get-ambisonic #x1201
286
   ;; RF64 files can be set so that on-close, writable files
287
   ;; that have less than 4GB of data in them are converted to
288
   ;; RIFF/WAV, as per EBU recommendations.
289
   :rf64-auto-downgrade #x1210
290
   :set-vbr-encoding-quality #x1300
291
   :set-compression-level #x1301
292
   ;; /* Ogg format commands */
293
   :set-ogg-page-latency-ms #x1302
294
   :set-ogg-page-latency #x1303
295
   :get-ogg-stream-serialno #x1306
296
   :get-bitrate-mode #x1304
297
   :set-bitrate-mode #x1305
298
   ;; /* Cart Chunk support */
299
   :set-cart-info #x1400
300
   :get-cart-info #x1401
301
   ;; /* Opus files original samplerate metadata */
302
   :set-original-samplerate #x1500
303
   :get-original-samplerate #x1501
304
   ;; /* Following commands for testing only. */
305
   :test-ieee-float-replace #x6001
306
   ;; These SFC_SET_ADD_* values are deprecated and will
307
   ;; disappear at some time in the future. They are
308
   ;; guaranteed to be here up to and including version 1.0.8
309
   ;; to avoid breakage of existing software.  They currently
310
   ;; do nothing and will continue to do nothing.
311
   :set-add-header-pad-chunk #x1051
312
   :set-add-dither-on-write #x1070
313
   :set-add-dither-on-read #x1071)
314
 
315
 ;;; Functions
316
 (defar sf-open (* sndfile) (path c-string) (mode int) (sfinfo (* sf-info)))
317
 (defar sf-open-fd (* sndfile) (fd int) (mode int) (sfinfo (* sf-info)))
318
 (defar sf-error int (sndfile (* sndfile)))
319
 (defar sf-strerror c-string (sndfile (* sndfile)))
320
 (defar sf-error-number c-string (errnum int))
321
 (defar sf-perror int (sndfile (* sndfile)))
322
 (defar sf-error-str int (sndfile (* sndfile)) (str c-string) (len size-t))
323
 (defar sf-command int (sndfile (* sndfile)) (command int) (data (* t)) (datasize int))
324
 (defar sf-format-check int (info (* sf-info)))
325
 (defar sf-seek sf-count (sndfile (* sndfile)) (frames sf-count) (whence int))
326
 
327
 (defar sf-set-string int (sndfile (* sndfile)) (str-type int) (str c-string))
328
 (defar sf-get-string c-string (sndfile (* sndfile)) (str-type int))
329
 (defar sf-version-string c-string)
330
 (defar sf-current-byterate int (sndfile (* sndfile)))
331
 (defar sf-read-raw sf-count (sndfile (* sndfile)) (ptr (* t)) (bytes sf-count))
332
 (defar sf-write-raw sf-count (sndfile (* sndfile)) (ptr (* t)) (bytes sf-count))
333
 
334
 (defar sf-readf-float sf-count (sndfile (* sndfile)) (ptr (* float)) (frames sf-count))
335
 (defar sf-writef-float sf-count (sndfile (* sndfile)) (ptr (* float)) (frames sf-count))
336
 (defar sf-readf-short sf-count (sndfile (* sndfile)) (ptr (* short)) (frames sf-count))
337
 (defar sf-writef-short sf-count (sndfile (* sndfile)) (ptr (* short)) (frames sf-count))
338
 (defar sf-readf-double sf-count (sndfile (* sndfile)) (ptr (* double)) (frames sf-count))
339
 (defar sf-writef-double sf-count (sndfile (* sndfile)) (ptr (* double)) (frames sf-count))
340
 
341
 ;; ...
342
 (defar sf-close int (sndfile (* sndfile)))
343
 
344
 (defar sf-write-sync void
345
   (sndfile (* sndfile)))
346
 
347
 (define-alien-type sf-chunk-info
348
     (struct sf-chunk-info
349
       (id (array char 64))
350
       (id-size unsigned)
351
       (datalen unsigned)
352
       (data (* t))))
353
 
354
 (defar sf-set-chunk int
355
   (sndfile (* sndfile))
356
   (chunk-info (* sf-chunk-info)))
357
 
358
 (defar sf-get-chunk-iterator (* sf-chunk-iterator)
359
   (sndfile (* sndfile))
360
   (chunk-info (* sf-chunk-info)))
361
 
362
 (defar sf-next-chunk-iterator (* sf-chunk-iterator)
363
   (iterator (* sf-chunk-iterator)))
364
 
365
 (defar sf-get-chunk-size int
366
   (it (* sf-chunk-iterator))
367
   (chunk-info (* sf-chunk-info)))
368
 
369
 (defar sf-get-chunk-data int
370
   (it (* sf-chunk-iterator))
371
   (chunk-info (* sf-chunk-info)))
372
 
373
 ;;; Utils
374
 (defun decode-sf-format (i)
375
   "Decode an SF-FORMAT integer into a list of (TYPE SUB ENDIAN)."
376
   (list
377
    (sf-format* (logand i (sf-format-mask :type)))
378
    (sf-format-subtype* (logand i (sf-format-mask :sub)))
379
    (sf-endian* (logand i (sf-format-mask :end)))))
380
 
381
 (defun encode-sf-format (type sub &optional (end :file))
382
   "Encode an SF-FORMAT integer from TYPE SUB and optional ENDian."
383
   (logior (sf-format type) (sf-format-subtype sub) (sf-endian end)))
384
 
385
 (defmacro with-sf-info ((sym &key samplerate channels format sections seekable) &body body)
386
   `(with-alien ((,sym sf-info))
387
      ,@(when samplerate `((setf (slot ,sym 'samplerate) ,samplerate)))
388
      ,@(when channels `((setf (slot ,sym 'channels) ,channels)))
389
      ,@(when format 
390
          (etypecase format
391
            (list `((setf (slot ,sym 'format) (apply 'encode-sf-format ,format))))
392
            (integer `((setf (slot ,sym 'format) ,format)))))
393
      ,@(when sections `((setf (slot ,sym 'sections) ,sections)))
394
      ,@(when seekable `((setf (slot ,sym 'seekable) ,seekable)))
395
      ,@body))
396
 
397
 (defmacro with-sndfile ((sym info path &key close (mode (sf-flag :read))) &body body)
398
   `(let ((,sym (sf-open (namestring ,path) ,mode ,info)))
399
      (unwind-protect (progn ,@body)
400
        ,@(when close `((sf-close ,sym))))))