3 docCopyright("Steve Dekorte", 2004)
4 docLicense("BSD revised")
6 docDescription("""An object for encoding and decoding audio and video streams.""")
9 #include "IoLibSndFile.h"
17 #define DATA(self) ((IoLibSndFileData *)IoObject_dataPointer(self))
19 IoTag
*IoLibSndFile_newTag(void *state
)
21 IoTag
*tag
= IoTag_newWithName_("LibSndFile");
22 IoTag_state_(tag
, state
);
23 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoLibSndFile_rawClone
);
24 IoTag_markFunc_(tag
, (IoTagMarkFunc
*)IoLibSndFile_mark
);
25 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoLibSndFile_free
);
29 IoLibSndFile
*IoLibSndFile_proto(void *state
)
31 IoObject
*self
= IoObject_new(state
);
32 IoObject_tag_(self
, IoLibSndFile_newTag(state
));
34 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoLibSndFileData
)));
36 DATA(self
)->outputBuffer
= IoSeq_new(state
);
37 DATA(self
)->sfinfo
= calloc(1, sizeof(SF_INFO
));
39 IoState_registerProtoWithFunc_(state
, self
, IoLibSndFile_proto
);
42 IoMethodTable methodTable
[] = {
43 {"outputBuffer", IoLibSndFile_outputBuffer
},
44 {"formatNames", IoLibSndFile_formatNames
},
45 {"openForReading", IoLibSndFile_openForReading
},
46 {"openForWriting", IoLibSndFile_openForWriting
},
47 {"read", IoLibSndFile_read
},
48 {"write", IoLibSndFile_write
},
49 {"close", IoLibSndFile_close
},
52 IoObject_addMethodTable_(self
, methodTable
);
57 IoLibSndFile
*IoLibSndFile_rawClone(IoLibSndFile
*proto
)
59 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
60 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoLibSndFileData
)));
62 DATA(self
)->outputBuffer
= IOCLONE(DATA(proto
)->outputBuffer
);
63 DATA(self
)->sfinfo
= calloc(1, sizeof(SF_INFO
));
68 IoLibSndFile
*IoLibSndFile_new(void *state
)
70 IoObject
*proto
= IoState_protoWithInitFunction_(state
, IoLibSndFile_proto
);
71 return IOCLONE(proto
);
74 // -----------------------------------------------------------
76 void IoLibSndFile_free(IoLibSndFile
*self
)
78 free(DATA(self
)->sfinfo
);
79 free(IoObject_dataPointer(self
));
82 void IoLibSndFile_mark(IoLibSndFile
*self
)
84 IoObject_shouldMark(DATA(self
)->outputBuffer
);
87 // -----------------------------------------------------------
89 IoObject
*IoLibSndFile_outputBuffer(IoLibSndFile
*self
, IoObject
*locals
, IoMessage
*m
)
92 docSlot("outputBuffer", "Returns the output buffer.")
94 return DATA(self
)->outputBuffer
;
97 IoObject
*IoLibSndFile_stop(IoLibSndFile
*self
, IoObject
*locals
, IoMessage
*m
)
100 docSlot("stop", "Stops processing data.")
102 DATA(self
)->isRunning
= 0;
106 IoObject
*IoLibSndFile_isRunning(IoLibSndFile
*self
, IoObject
*locals
, IoMessage
*m
)
109 docSlot("isRunning", "Returns true if it's running, false otherwise.")
111 return IOBOOL(self
, DATA(self
)->isRunning
);
114 IoObject
*IoLibSndFile_formatNames(IoLibSndFile
*self
, IoObject
*locals
, IoMessage
*m
)
117 docSlot("formatNames", "Returns a list of strings with the names of the supported codecs.")
119 IoList
*names
= IoList_new(IOSTATE
);
122 SF_FORMAT_INFO format_info;
125 sf_command(DATA(self)->sndfile, SFC_GET_SIMPLE_FORMAT_COUNT, &count, sizeof(int));
127 for (k = 0 ; k < count ; k++)
129 format_info.format = k ;
130 sf_command (sndfile, SFC_GET_SIMPLE_FORMAT, &format_info, sizeof(format_info));
131 printf ("%08x %s %s\n", format_info.format, format_info.name, format_info.extension);
132 IoList_rawAppend_(names, IOSYMBOL(format_info.name));
139 int IoLibSndFile_IdOfFormat(char *f
)
141 char *r
= strrchr(f
, '.');
142 // add code to deal with case
149 if (!strcmp(f
, "wav")) return SF_FORMAT_WAV
| SF_FORMAT_FLOAT
;
150 if (!strcmp(f
, "aiff")) return SF_FORMAT_AIFF
;
151 if (!strcmp(f
, "au")) return SF_FORMAT_AU
;
152 if (!strcmp(f
, "raw")) return SF_FORMAT_RAW
;
153 if (!strcmp(f
, "paf")) return SF_FORMAT_PAF
;
154 if (!strcmp(f
, "svx")) return SF_FORMAT_SVX
;
155 if (!strcmp(f
, "nist")) return SF_FORMAT_NIST
;
156 if (!strcmp(f
, "voc")) return SF_FORMAT_VOC
;
157 if (!strcmp(f
, "ircam")) return SF_FORMAT_IRCAM
;
158 if (!strcmp(f
, "w64")) return SF_FORMAT_W64
;
159 if (!strcmp(f
, "mat4")) return SF_FORMAT_MAT4
;
160 if (!strcmp(f
, "mat5")) return SF_FORMAT_MAT5
;
166 // -----------------------------------------------------------
168 IoObject
*IoLibSndFile_openForReading(IoLibSndFile
*self
, IoObject
*locals
, IoMessage
*m
)
170 if (!DATA(self
)->sndfile
)
172 IoSeq
*path
= IoObject_symbolGetSlot_(self
, IOSYMBOL("path"));
173 IOASSERT(path
, "missing path slot");
174 DATA(self
)->sndfile
= sf_open(CSTRING(path
), SFM_READ
, DATA(self
)->sfinfo
);
175 IOASSERT(DATA(self
)->sndfile
, sf_strerror(NULL
));
178 IoObject_setSlot_to_(self
, IOSYMBOL("frames"), IONUMBER(DATA(self
)->sfinfo
->frames
));
179 IoObject_setSlot_to_(self
, IOSYMBOL("sampleRate"), IONUMBER(DATA(self
)->sfinfo
->samplerate
));
180 IoObject_setSlot_to_(self
, IOSYMBOL("channels"), IONUMBER(DATA(self
)->sfinfo
->channels
));
181 IoObject_setSlot_to_(self
, IOSYMBOL("format"), IONUMBER(DATA(self
)->sfinfo
->format
));
182 IoObject_setSlot_to_(self
, IOSYMBOL("seekable"), IONUMBER(DATA(self
)->sfinfo
->seekable
));
183 //IoObject_setSlot_to_(self, IOSYMBOL("size"), IONUMBER(DATA(self)->sfinfo->size));
187 IoObject
*IoLibSndFile_openForWriting(IoLibSndFile
*self
, IoObject
*locals
, IoMessage
*m
)
189 if (!DATA(self
)->sndfile
)
191 IoSeq
*path
= IoObject_symbolGetSlot_(self
, IOSYMBOL("path"));
192 IOASSERT(path
, "missing path slot");
194 //DATA(self)->sfinfo->frames = (sf_count_t)IoObject_doubleGetSlot_(self, IOSYMBOL("frames"));
195 DATA(self
)->sfinfo
->samplerate
= (sf_count_t
)IoObject_doubleGetSlot_(self
, IOSYMBOL("sampleRate"));
196 DATA(self
)->sfinfo
->channels
= (sf_count_t
)IoObject_doubleGetSlot_(self
, IOSYMBOL("channels"));
197 DATA(self
)->sfinfo
->format
= IoLibSndFile_IdOfFormat(CSTRING(path
));
199 DATA(self
)->sndfile
= sf_open(CSTRING(path
), SFM_READ
, DATA(self
)->sfinfo
);
200 IOASSERT(DATA(self
)->sndfile
, sf_strerror(NULL
));
206 IoObject
*IoLibSndFile_close(IoLibSndFile
*self
, IoObject
*locals
, IoMessage
*m
)
208 if (DATA(self
)->sndfile
)
210 sf_close(DATA(self
)->sndfile
);
216 IoObject
*IoLibSndFile_read(IoLibSndFile
*self
, IoObject
*locals
, IoMessage
*m
)
219 docSlot("read(numberOfFrames)", "Read a given number of frames (sample pairs).")
222 sf_count_t framesToRead
= IoMessage_locals_intArgAt_(m
, locals
, 0);
223 sf_count_t samplesRead
= 0;
225 IoLibSndFile_openForReading(self
, locals
, m
);
229 UArray
*outba
= IoSeq_rawUArray(DATA(self
)->outputBuffer
);
230 size_t samplesToRead
= framesToRead
* DATA(self
)->sfinfo
->channels
;
231 size_t bytesToRead
= samplesToRead
* sizeof(float);
233 size_t oldSize
= UArray_size(outba
);
235 UArray_setSize_(outba
, oldSize
+ bytesToRead
);
236 buf
= (float *)(UArray_bytes(outba
) + oldSize
);
238 samplesRead
= sf_read_float(DATA(self
)->sndfile
, buf
, samplesToRead
);
240 UArray_setSize_(outba
, oldSize
+ (samplesRead
* sizeof(float)));
242 if (samplesRead
!= samplesToRead
) return IONIL(self
);
249 IoObject
*IoLibSndFile_write(IoLibSndFile
*self
, IoObject
*locals
, IoMessage
*m
)
251 size_t channels
= IoObject_doubleGetSlot_(self
, IOSYMBOL("channels"));
252 UArray
*inba
= IoSeq_rawUArray(IoMessage_locals_seqArgAt_(m
, locals
, 0));
253 sf_count_t framesToWrite
= UArray_size(inba
) / (channels
* sizeof(float));
254 sf_count_t framesWritten
;
256 IoLibSndFile_openForWriting(self
, locals
, m
);
258 framesWritten
= sf_writef_float(DATA(self
)->sndfile
, (float *)UArray_bytes(inba
), framesToWrite
);
260 return IONUMBER(framesWritten
);