ruby-audio-heroku 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,342 @@
1
+ #include "ra_buffer.h"
2
+
3
+ ID ra_short_sym, ra_int_sym, ra_float_sym, ra_double_sym;
4
+ extern VALUE eRubyAudioError;
5
+
6
+ // Before RFLOAT_VALUE, value was in a different place in the struct
7
+ #ifndef RFLOAT_VALUE
8
+ #define RFLOAT_VALUE(v) (RFLOAT(v)->value)
9
+ #endif
10
+
11
+ /*
12
+ * Class <code>CBuffer</code> is a very light wrapper around a standard C array
13
+ * that can be read from and written to by libsndfile.
14
+ */
15
+ void Init_ra_buffer() {
16
+ VALUE mRubyAudio = rb_define_module("RubyAudio");
17
+ VALUE cRABuffer = rb_define_class_under(mRubyAudio, "CBuffer", rb_cObject);
18
+ rb_include_module(cRABuffer, rb_mEnumerable);
19
+ rb_define_alloc_func(cRABuffer, ra_buffer_allocate);
20
+ rb_define_method(cRABuffer, "initialize", ra_buffer_init, -1);
21
+ rb_define_method(cRABuffer, "initialize_copy", ra_buffer_init_copy, 1);
22
+ rb_define_method(cRABuffer, "channels", ra_buffer_channels, 0);
23
+ rb_define_method(cRABuffer, "size", ra_buffer_size, 0);
24
+ rb_define_method(cRABuffer, "real_size", ra_buffer_real_size, 0);
25
+ rb_define_method(cRABuffer, "real_size=", ra_buffer_real_size_set, 1);
26
+ rb_define_method(cRABuffer, "type", ra_buffer_type, 0);
27
+ rb_define_method(cRABuffer, "each", ra_buffer_each, 0);
28
+ rb_define_method(cRABuffer, "[]", ra_buffer_aref, 1);
29
+ rb_define_method(cRABuffer, "[]=", ra_buffer_aset, 2);
30
+
31
+ ra_short_sym = rb_intern("short");
32
+ ra_int_sym = rb_intern("int");
33
+ ra_float_sym = rb_intern("float");
34
+ ra_double_sym = rb_intern("double");
35
+ }
36
+
37
+ static VALUE ra_buffer_allocate(VALUE klass) {
38
+ RA_BUFFER *buf = ALLOC(RA_BUFFER);
39
+ memset(buf, 0, sizeof(RA_BUFFER));
40
+ VALUE self = Data_Wrap_Struct(klass, NULL, ra_buffer_free, buf);
41
+ return self;
42
+ }
43
+
44
+ static void ra_buffer_free(RA_BUFFER *buf) {
45
+ if(buf->data != NULL) xfree(buf->data);
46
+ xfree(buf);
47
+ }
48
+
49
+ /*
50
+ * Uses size, channels, and type to allocate a properly sized array and set data
51
+ * to the pointer for that data. Returns size.
52
+ */
53
+ static long ra_buffer_alloc_data(RA_BUFFER *buf) {
54
+ long size = 0;
55
+ switch(buf->type) {
56
+ case RA_BUFFER_TYPE_SHORT:
57
+ size = sizeof(short) * buf->size * buf->channels;
58
+ break;
59
+ case RA_BUFFER_TYPE_INT:
60
+ size = sizeof(int) * buf->size * buf->channels;
61
+ break;
62
+ case RA_BUFFER_TYPE_FLOAT:
63
+ size = sizeof(float) * buf->size * buf->channels;
64
+ break;
65
+ case RA_BUFFER_TYPE_DOUBLE:
66
+ size = sizeof(double) * buf->size * buf->channels;
67
+ break;
68
+ }
69
+ buf->data = (void*)xmalloc(size);
70
+ memset(buf->data, 0, size);
71
+ return size;
72
+ }
73
+
74
+ /*
75
+ * call-seq:
76
+ * RubyAudio::CBuffer.new(type, size, channels=1) => buf
77
+ *
78
+ * Returns a new <code>CBuffer</code> object which can contain the given number
79
+ * of audio frames of the given data type.
80
+ *
81
+ * buf = RubyAudio::CBuffer.new("float", 1000)
82
+ */
83
+ static VALUE ra_buffer_init(int argc, VALUE *argv, VALUE self) {
84
+ RA_BUFFER *buf;
85
+ Data_Get_Struct(self, RA_BUFFER, buf);
86
+
87
+ // Check args
88
+ if(argc < 2) rb_raise(rb_eArgError, "At least 2 arguments required");
89
+
90
+ // Get type of object
91
+ const char *buf_type;
92
+ switch(TYPE(argv[0])) {
93
+ case T_SYMBOL:
94
+ buf_type = rb_id2name(SYM2ID(argv[0]));
95
+ if(!buf_type) rb_raise(rb_eArgError, "bad type");
96
+ break;
97
+ case T_STRING:
98
+ buf_type = RSTRING_PTR(argv[0]);
99
+ break;
100
+ default:
101
+ rb_raise(rb_eArgError, "bad type");
102
+ break;
103
+ }
104
+
105
+ // Populate channels
106
+ buf->channels = (argc == 3) ? FIX2INT(argv[2]) : 1;
107
+
108
+ // Allocate data array based on type
109
+ buf->size = FIX2LONG(argv[1]);
110
+ buf->real_size = 0;
111
+ if(strcmp(buf_type, "short") == 0) buf->type = RA_BUFFER_TYPE_SHORT;
112
+ else if(strcmp(buf_type, "int") == 0) buf->type = RA_BUFFER_TYPE_INT;
113
+ else if(strcmp(buf_type, "float") == 0) buf->type = RA_BUFFER_TYPE_FLOAT;
114
+ else if(strcmp(buf_type, "double") == 0) buf->type = RA_BUFFER_TYPE_DOUBLE;
115
+ else rb_raise(rb_eArgError, "Invalid type: %s", buf_type);
116
+ ra_buffer_alloc_data(buf);
117
+
118
+ // Return self
119
+ return self;
120
+ }
121
+
122
+ /* :nodoc: */
123
+ static VALUE ra_buffer_init_copy(VALUE copy, VALUE buf) {
124
+ if (copy == buf) return copy;
125
+
126
+ // Checks
127
+ rb_check_frozen(copy);
128
+ if (!rb_obj_is_instance_of(buf, rb_obj_class(copy))) {
129
+ rb_raise(rb_eTypeError, "wrong argument class");
130
+ }
131
+
132
+ RA_BUFFER *copy_struct, *buf_struct;
133
+ Data_Get_Struct(copy, RA_BUFFER, copy_struct);
134
+ Data_Get_Struct(buf, RA_BUFFER, buf_struct);
135
+
136
+ // Clone data
137
+ memcpy(copy_struct, buf_struct, sizeof(RA_BUFFER));
138
+ long size = ra_buffer_alloc_data(copy_struct);
139
+ memcpy(copy_struct->data, buf_struct->data, size);
140
+
141
+ return copy;
142
+ }
143
+
144
+ /*
145
+ * call-seq:
146
+ * buf.channels => integer
147
+ *
148
+ * Returns the number of channels in a frame of the buffer.
149
+ */
150
+ static VALUE ra_buffer_channels(VALUE self) {
151
+ RA_BUFFER *buf;
152
+ Data_Get_Struct(self, RA_BUFFER, buf);
153
+ return INT2FIX(buf->channels);
154
+ }
155
+
156
+ /*
157
+ * call-seq:
158
+ * buf.size => integer
159
+ *
160
+ * Returns the number of frames the buffer can store.
161
+ */
162
+ static VALUE ra_buffer_size(VALUE self) {
163
+ RA_BUFFER *buf;
164
+ Data_Get_Struct(self, RA_BUFFER, buf);
165
+ return LONG2FIX(buf->size);
166
+ }
167
+
168
+ /*
169
+ * call-seq:
170
+ * buf.real_size => integer
171
+ *
172
+ * Returns the number of frames of actual data are currently stored in the
173
+ * buffer.
174
+ */
175
+ static VALUE ra_buffer_real_size(VALUE self) {
176
+ RA_BUFFER *buf;
177
+ Data_Get_Struct(self, RA_BUFFER, buf);
178
+ return LONG2FIX(buf->real_size);
179
+ }
180
+
181
+ /*:nodoc:*/
182
+ static VALUE ra_buffer_real_size_set(VALUE self, VALUE real_size) {
183
+ RA_BUFFER *buf;
184
+ Data_Get_Struct(self, RA_BUFFER, buf);
185
+
186
+ long new_real_size = FIX2LONG(real_size);
187
+ if(new_real_size > buf->size) {
188
+ buf->real_size = buf->size;
189
+ } else if(new_real_size < 0) {
190
+ buf->real_size = 0;
191
+ } else {
192
+ buf->real_size = new_real_size;
193
+ }
194
+
195
+ return LONG2FIX(buf->real_size);
196
+ }
197
+
198
+ /*
199
+ * call-seq:
200
+ * buf.type => symbol
201
+ *
202
+ * Returns the type of audio data being stored. <code>:short</code>,
203
+ * <code>:int</code>, <code>:float</code>, or <code>:double</code>.
204
+ */
205
+ static VALUE ra_buffer_type(VALUE self) {
206
+ RA_BUFFER *buf;
207
+ Data_Get_Struct(self, RA_BUFFER, buf);
208
+ switch(buf->type) {
209
+ case RA_BUFFER_TYPE_SHORT: return ID2SYM(ra_short_sym);
210
+ case RA_BUFFER_TYPE_INT: return ID2SYM(ra_int_sym);
211
+ case RA_BUFFER_TYPE_FLOAT: return ID2SYM(ra_float_sym);
212
+ case RA_BUFFER_TYPE_DOUBLE: return ID2SYM(ra_double_sym);
213
+ }
214
+ }
215
+
216
+ /*
217
+ * call-seq:
218
+ * buf.each {|frame| block } => buf
219
+ * buf.each => anEnumerator
220
+ *
221
+ * Iterates through each frame in the buffer. Each frame is either a number or
222
+ * an array of numbers if there are multiple channels.
223
+ */
224
+ static VALUE ra_buffer_each(VALUE self) {
225
+ RA_BUFFER *buf;
226
+ Data_Get_Struct(self, RA_BUFFER, buf);
227
+
228
+ RETURN_ENUMERATOR(self, 0, 0);
229
+
230
+ long i;
231
+ for(i = 0; i < buf->real_size; i++) {
232
+ rb_yield(ra_buffer_aref(self, LONG2FIX(i)));
233
+ }
234
+ return self;
235
+ }
236
+
237
+ /*
238
+ * call-seq:
239
+ * buf[integer] => frame
240
+ *
241
+ * Returns a frame of audio data at the given offset.
242
+ *
243
+ * buf = snd.read(:float, 100) # Mono sound
244
+ * buf[5] #=> 0.4
245
+ *
246
+ * buf2 = snd2.read(:float, 100) # Stereo sound
247
+ * buf[5] #=> [0.4, 0.3]
248
+ */
249
+ static VALUE ra_buffer_aref(VALUE self, VALUE index) {
250
+ RA_BUFFER *buf;
251
+ Data_Get_Struct(self, RA_BUFFER, buf);
252
+
253
+ // Bounds check
254
+ long f = FIX2LONG(index);
255
+ if(f < 0 || f >= buf->real_size) return Qnil;
256
+ long i = f * buf->channels;
257
+
258
+ if(buf->channels == 1) {
259
+ return ra_buffer_index_get(buf, i);
260
+ } else {
261
+ VALUE frame = rb_ary_new();
262
+ long j;
263
+ for(j = 0; j < buf->channels; j++) {
264
+ rb_ary_push(frame, ra_buffer_index_get(buf, i+j));
265
+ }
266
+ return frame;
267
+ }
268
+ }
269
+
270
+ static VALUE ra_buffer_index_get(RA_BUFFER *buf, long i) {
271
+ switch(buf->type) {
272
+ case RA_BUFFER_TYPE_SHORT: return INT2FIX((int)((short*)buf->data)[i]);
273
+ case RA_BUFFER_TYPE_INT: return INT2FIX(((int*)buf->data)[i]);
274
+ case RA_BUFFER_TYPE_FLOAT: return rb_float_new((double)((float*)buf->data)[i]);
275
+ case RA_BUFFER_TYPE_DOUBLE: return rb_float_new(((double*)buf->data)[i]);
276
+ }
277
+ }
278
+
279
+ /*
280
+ * call-seq:
281
+ * buf[integer] = numeric => numeric
282
+ * buf[integer] = array => array
283
+ *
284
+ * Sets the frame of audio data at the given offset to the value. For
285
+ * multi-channel audio, pass in an array of values.
286
+ *
287
+ * buf = RubyAudio::Buffer.int(100, 1)
288
+ * buf[0] = 5
289
+ *
290
+ * buf = RubyAudio::Buffer.double(100, 2)
291
+ * buf[0] = [0.5, 0.3]
292
+ */
293
+ static VALUE ra_buffer_aset(VALUE self, VALUE index, VALUE val) {
294
+ RA_BUFFER *buf;
295
+ Data_Get_Struct(self, RA_BUFFER, buf);
296
+
297
+ // Bounds check
298
+ long f = FIX2LONG(index);
299
+ if(f < 0 || f >= buf->size) rb_raise(eRubyAudioError, "setting frame out of bounds");
300
+ long i = f * buf->channels;
301
+
302
+ // Set data
303
+ if(buf->channels == 1) {
304
+ ra_buffer_index_set(buf, i, val);
305
+ } else {
306
+ if(TYPE(val) != T_ARRAY) rb_raise(eRubyAudioError, "must pass in array for multi-channel buffer");
307
+ long length = RARRAY_LEN(val);
308
+ if(length != buf->channels) rb_raise(eRubyAudioError, "array length must match channel count");
309
+
310
+ long j;
311
+ for(j = 0; j < length; j++) {
312
+ ra_buffer_index_set(buf, i+j, rb_ary_entry(val, j));
313
+ }
314
+ }
315
+
316
+ // Bump real_size
317
+ if(f + 1 > buf->real_size) {
318
+ buf->real_size = f + 1;
319
+ }
320
+
321
+ return val;
322
+ }
323
+
324
+ static void ra_buffer_index_set(RA_BUFFER *buf, long i, VALUE val) {
325
+ if(buf->type == RA_BUFFER_TYPE_SHORT || buf->type == RA_BUFFER_TYPE_INT) {
326
+ // Convert val to an integer
327
+ VALUE int_obj = rb_Integer(val);
328
+ if(TYPE(int_obj) != T_FIXNUM) rb_raise(eRubyAudioError, "could not convert frame value to an integer");
329
+ long int_val = FIX2LONG(int_obj);
330
+
331
+ // Set it
332
+ if(buf->type == RA_BUFFER_TYPE_SHORT) ((short*)buf->data)[i] = (short)int_val;
333
+ else ((int*)buf->data)[i] = (int)int_val;
334
+ } else {
335
+ // Convert val to a float
336
+ double float_val = RFLOAT_VALUE(rb_Float(val));
337
+
338
+ // Set it
339
+ if(buf->type == RA_BUFFER_TYPE_FLOAT) ((float*)buf->data)[i] = (float)float_val;
340
+ else ((double*)buf->data)[i] = float_val;
341
+ }
342
+ }
@@ -0,0 +1,41 @@
1
+ #ifndef RA_BUFFER_H
2
+ #define RA_BUFFER_H
3
+
4
+ #include <ruby.h>
5
+
6
+ typedef enum {
7
+ RA_BUFFER_TYPE_SHORT,
8
+ RA_BUFFER_TYPE_INT,
9
+ RA_BUFFER_TYPE_FLOAT,
10
+ RA_BUFFER_TYPE_DOUBLE
11
+ } BUFFER_TYPE;
12
+
13
+ typedef struct {
14
+ BUFFER_TYPE type;
15
+ void *data;
16
+ long size;
17
+ long real_size;
18
+ int channels;
19
+ } RA_BUFFER;
20
+
21
+ void Init_ra_buffer();
22
+
23
+ /*** Initialization and Memory Manangement ***/
24
+ static VALUE ra_buffer_allocate(VALUE klass);
25
+ static void ra_buffer_free(RA_BUFFER *buf);
26
+
27
+ /*** Instance Methods ***/
28
+ static VALUE ra_buffer_init(int argc, VALUE *argv, VALUE self);
29
+ static VALUE ra_buffer_init_copy(VALUE copy, VALUE buf);
30
+ static VALUE ra_buffer_channels(VALUE self);
31
+ static VALUE ra_buffer_size(VALUE self);
32
+ static VALUE ra_buffer_real_size(VALUE self);
33
+ static VALUE ra_buffer_real_size_set(VALUE self, VALUE new_real_size);
34
+ static VALUE ra_buffer_type(VALUE self);
35
+ static VALUE ra_buffer_each(VALUE self);
36
+ static VALUE ra_buffer_aref(VALUE self, VALUE index);
37
+ static VALUE ra_buffer_index_get(RA_BUFFER *buf, long i);
38
+ static VALUE ra_buffer_aset(VALUE self, VALUE index, VALUE val);
39
+ static void ra_buffer_index_set(RA_BUFFER *buf, long i, VALUE val);
40
+
41
+ #endif // #ifndef RA_BUFFER_H