]> gitweb.factorcode.org Git - factor.git/blob - extra/audio/aiff/aiff.factor
549134003b628425087304faa368c20868bd0240
[factor.git] / extra / audio / aiff / aiff.factor
1 ! (c)2009 Joe Groff bsd license
2 USING: accessors alien alien.c-types alien.data audio
3 audio.chunked-file classes.struct combinators
4 combinators.short-circuit endian io io.binary
5 io.encodings.binary io.files kernel locals math sequences
6 audio.loader ;
7 IN: audio.aiff
8
9 CONSTANT: FORM-MAGIC "FORM"
10 CONSTANT: AIFF-MAGIC "AIFF"
11 CONSTANT: COMM-MAGIC "COMM"
12 CONSTANT: SSND-MAGIC "SSND"
13
14 STRUCT: aiff-chunk-header
15     { id char[4] }
16     { size char[4] } ;
17
18 STRUCT: form-chunk
19     { header aiff-chunk-header }
20     { form-type char[4] } ;
21
22 STRUCT: common-chunk
23     { header aiff-chunk-header }
24     { num-channels uchar[2] }
25     { num-sample-frames uchar[4] }
26     { sample-size uchar[2] }
27     { sample-rate uchar[10] } ;
28
29 STRUCT: sound-data-chunk
30     { header aiff-chunk-header }
31     { offset uchar[4] }
32     { block-size uchar[4] }
33     { waveform-data uchar[0] } ;
34
35 ! cheesy long-double>integer converter that assumes the long double is a positive integer
36 : sample-rate>integer ( byte[10] -- sample-rate )
37     [ 2 tail-slice be> ]
38     [ 2 head-slice be> 16383 - 63 - ] bi shift ;
39
40 : read-form-chunk ( -- byte-array/f )
41     form-chunk heap-size ensured-read* ;
42
43 : verify-aiff ( chunk -- )
44     {
45         [ FORM-MAGIC id= ]
46         [ form-chunk memory>struct form-type>> 4 memory>byte-array AIFF-MAGIC id= ] 
47     } 1&&
48     [ invalid-audio-file ] unless ;
49
50 :: read-aiff-chunks ( -- comm ssnd )
51     f :> comm! f :> ssnd!
52     [ { [ comm ssnd and not ] [ read-chunk ] } 0&& dup ]
53     [ {
54         {
55             [ dup COMM-MAGIC common-chunk check-chunk ]
56             [ common-chunk memory>struct comm! ]
57         }
58         {
59             [ dup SSND-MAGIC sound-data-chunk check-chunk ]
60             [ sound-data-chunk memory>struct ssnd! ]
61         }
62         [ drop ]
63     } cond ] while drop
64     comm ssnd 2dup and [ invalid-audio-file ] unless ;
65
66 : (read-aiff) ( -- audio )
67     read-aiff-chunks
68     [
69         [ num-channels>>    2 memory>byte-array be> ]
70         [ sample-size>>     2 memory>byte-array be> ]
71         [ sample-rate>>     sample-rate>integer ] tri
72     ] [
73         [ header>> size>> 4 memory>byte-array be> 8 - dup ]
74         [ waveform-data>> >c-ptr ] bi swap memory>byte-array
75     ] bi*
76     <audio> convert-data-endian ;
77
78 : read-aiff ( filename -- audio )
79     big-endian [
80         binary [
81             read-form-chunk verify-aiff (read-aiff)
82         ] with-file-reader
83     ] with-endianness ;
84
85 "aif"  [ read-aiff ] register-audio-extension
86 "aiff" [ read-aiff ] register-audio-extension