ruby-audio 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/ext/ra_buffer.c +53 -23
- data/ext/ra_buffer.h +1 -0
- data/ext/ra_sound.c +244 -16
- data/spec/buffer_spec.rb +12 -0
- data/spec/sound_spec.rb +38 -3
- metadata +2 -2
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'spec/rake/spectask'
|
|
6
6
|
|
7
7
|
spec = Gem::Specification.new do |s|
|
8
8
|
s.name = 'ruby-audio'
|
9
|
-
s.version = '1.
|
9
|
+
s.version = '1.1.0'
|
10
10
|
s.summary = 'ruby-audio wraps around libsndfile to provide simplified sound reading and writing support to ruby programs'
|
11
11
|
s.authors = ['Stephen Augenstein']
|
12
12
|
s.email = 'perl.programmer@gmail.com'
|
data/ext/ra_buffer.c
CHANGED
@@ -16,14 +16,15 @@ void Init_ra_buffer() {
|
|
16
16
|
VALUE mRubyAudio = rb_define_module("RubyAudio");
|
17
17
|
VALUE cRABuffer = rb_define_class_under(mRubyAudio, "CBuffer", rb_cObject);
|
18
18
|
rb_define_alloc_func(cRABuffer, ra_buffer_allocate);
|
19
|
-
rb_define_method(cRABuffer, "initialize",
|
20
|
-
rb_define_method(cRABuffer, "
|
21
|
-
rb_define_method(cRABuffer, "
|
22
|
-
rb_define_method(cRABuffer, "
|
23
|
-
rb_define_method(cRABuffer, "real_size
|
24
|
-
rb_define_method(cRABuffer, "
|
25
|
-
rb_define_method(cRABuffer, "
|
26
|
-
rb_define_method(cRABuffer, "[]
|
19
|
+
rb_define_method(cRABuffer, "initialize", ra_buffer_init, -1);
|
20
|
+
rb_define_method(cRABuffer, "initialize_copy", ra_buffer_init_copy, 1);
|
21
|
+
rb_define_method(cRABuffer, "channels", ra_buffer_channels, 0);
|
22
|
+
rb_define_method(cRABuffer, "size", ra_buffer_size, 0);
|
23
|
+
rb_define_method(cRABuffer, "real_size", ra_buffer_real_size, 0);
|
24
|
+
rb_define_method(cRABuffer, "real_size=", ra_buffer_real_size_set, 1);
|
25
|
+
rb_define_method(cRABuffer, "type", ra_buffer_type, 0);
|
26
|
+
rb_define_method(cRABuffer, "[]", ra_buffer_aref, 1);
|
27
|
+
rb_define_method(cRABuffer, "[]=", ra_buffer_aset, 2);
|
27
28
|
|
28
29
|
ra_short_sym = rb_intern("short");
|
29
30
|
ra_int_sym = rb_intern("int");
|
@@ -43,6 +44,22 @@ static void ra_buffer_free(RA_BUFFER *buf) {
|
|
43
44
|
xfree(buf);
|
44
45
|
}
|
45
46
|
|
47
|
+
/*
|
48
|
+
* Uses size, channels, and type to allocate a properly sized array and set data
|
49
|
+
* to the pointer for that data. Returns size.
|
50
|
+
*/
|
51
|
+
static int ra_buffer_alloc_data(RA_BUFFER *buf) {
|
52
|
+
int size;
|
53
|
+
switch(buf->type) {
|
54
|
+
case RA_BUFFER_TYPE_SHORT: size = sizeof(short)*buf->size*buf->channels; break;
|
55
|
+
case RA_BUFFER_TYPE_INT: size = sizeof(int)*buf->size*buf->channels; break;
|
56
|
+
case RA_BUFFER_TYPE_FLOAT: size = sizeof(float)*buf->size*buf->channels; break;
|
57
|
+
case RA_BUFFER_TYPE_DOUBLE: size = sizeof(double)*buf->size*buf->channels; break;
|
58
|
+
}
|
59
|
+
buf->data = (void*)xmalloc(size);
|
60
|
+
return size;
|
61
|
+
}
|
62
|
+
|
46
63
|
/*
|
47
64
|
* call-seq:
|
48
65
|
* RubyAudio::CBuffer.new(type, size, channels=1) => buf
|
@@ -80,26 +97,39 @@ static VALUE ra_buffer_init(int argc, VALUE *argv, VALUE self) {
|
|
80
97
|
// Allocate data array based on type
|
81
98
|
buf->size = FIX2INT(argv[1]);
|
82
99
|
buf->real_size = 0;
|
83
|
-
if(strcmp(buf_type, "short") == 0)
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
} else if(strcmp(buf_type, "float") == 0) {
|
90
|
-
buf->type = RA_BUFFER_TYPE_FLOAT;
|
91
|
-
buf->data = ALLOC_N(float, buf->size * buf->channels);
|
92
|
-
} else if(strcmp(buf_type, "double") == 0) {
|
93
|
-
buf->type = RA_BUFFER_TYPE_DOUBLE;
|
94
|
-
buf->data = ALLOC_N(double, buf->size * buf->channels);
|
95
|
-
} else {
|
96
|
-
rb_raise(rb_eArgError, "Invalid type: %s", buf_type);
|
97
|
-
}
|
100
|
+
if(strcmp(buf_type, "short") == 0) buf->type = RA_BUFFER_TYPE_SHORT;
|
101
|
+
else if(strcmp(buf_type, "int") == 0) buf->type = RA_BUFFER_TYPE_INT;
|
102
|
+
else if(strcmp(buf_type, "float") == 0) buf->type = RA_BUFFER_TYPE_FLOAT;
|
103
|
+
else if(strcmp(buf_type, "double") == 0) buf->type = RA_BUFFER_TYPE_DOUBLE;
|
104
|
+
else rb_raise(rb_eArgError, "Invalid type: %s", buf_type);
|
105
|
+
ra_buffer_alloc_data(buf);
|
98
106
|
|
99
107
|
// Return self
|
100
108
|
return self;
|
101
109
|
}
|
102
110
|
|
111
|
+
/* :nodoc: */
|
112
|
+
static VALUE ra_buffer_init_copy(VALUE copy, VALUE buf) {
|
113
|
+
if (copy == buf) return copy;
|
114
|
+
|
115
|
+
// Checks
|
116
|
+
rb_check_frozen(copy);
|
117
|
+
if (!rb_obj_is_instance_of(buf, rb_obj_class(copy))) {
|
118
|
+
rb_raise(rb_eTypeError, "wrong argument class");
|
119
|
+
}
|
120
|
+
|
121
|
+
RA_BUFFER *copy_struct, *buf_struct;
|
122
|
+
Data_Get_Struct(copy, RA_BUFFER, copy_struct);
|
123
|
+
Data_Get_Struct(buf, RA_BUFFER, buf_struct);
|
124
|
+
|
125
|
+
// Clone data
|
126
|
+
memcpy(copy_struct, buf_struct, sizeof(RA_BUFFER));
|
127
|
+
int size = ra_buffer_alloc_data(copy_struct);
|
128
|
+
memcpy(copy_struct->data, buf_struct->data, size);
|
129
|
+
|
130
|
+
return copy;
|
131
|
+
}
|
132
|
+
|
103
133
|
/*
|
104
134
|
* call-seq:
|
105
135
|
* buf.channels => integer
|
data/ext/ra_buffer.h
CHANGED
@@ -26,6 +26,7 @@ static void ra_buffer_free(RA_BUFFER *buf);
|
|
26
26
|
|
27
27
|
/*** Instance Methods ***/
|
28
28
|
static VALUE ra_buffer_init(int argc, VALUE *argv, VALUE self);
|
29
|
+
static VALUE ra_buffer_init_copy(VALUE copy, VALUE buf);
|
29
30
|
static VALUE ra_buffer_channels(VALUE self);
|
30
31
|
static VALUE ra_buffer_size(VALUE self);
|
31
32
|
static VALUE ra_buffer_real_size(VALUE self);
|
data/ext/ra_sound.c
CHANGED
@@ -127,6 +127,238 @@ static VALUE ra_sound_seek(VALUE self, VALUE frames, VALUE whence) {
|
|
127
127
|
return INT2FIX(0);
|
128
128
|
}
|
129
129
|
|
130
|
+
static void ra_sound_read_short(RA_SOUND *snd, RA_BUFFER *buf, sf_count_t frames) {
|
131
|
+
static short temp[1024];
|
132
|
+
int temp_len = 1024;
|
133
|
+
short *data = (short*)buf->data;
|
134
|
+
|
135
|
+
// Get info struct
|
136
|
+
SF_INFO *info;
|
137
|
+
Data_Get_Struct(snd->info, SF_INFO, info);
|
138
|
+
|
139
|
+
// Up/Downmix based on channel matching
|
140
|
+
sf_count_t read = 0, r, amount;
|
141
|
+
int i, k;
|
142
|
+
if(buf->channels == info->channels) { // Simply read data without mix
|
143
|
+
read = sf_readf_short(snd->snd, data, frames);
|
144
|
+
} else if(buf->channels == 1) { // Downmix to mono
|
145
|
+
sf_count_t max = temp_len / info->channels;
|
146
|
+
int channels, mix_sum;
|
147
|
+
|
148
|
+
while(read < frames) {
|
149
|
+
// Calculate # of frames to read
|
150
|
+
amount = frames - read;
|
151
|
+
if(amount > max) amount = max;
|
152
|
+
|
153
|
+
r = sf_readf_short(snd->snd, temp, amount);
|
154
|
+
if(r == 0) break;
|
155
|
+
|
156
|
+
// Mix channels together by averaging all channels and store to buffer
|
157
|
+
for(i = 0; i < r; i++) {
|
158
|
+
mix_sum = 0;
|
159
|
+
for(k = 0; k < info->channels; k++) mix_sum += temp[i * info->channels + k];
|
160
|
+
data[read] = mix_sum/info->channels;
|
161
|
+
read++;
|
162
|
+
}
|
163
|
+
}
|
164
|
+
} else if(info->channels == 1) { // Upmix from mono by copying channel
|
165
|
+
while(read < frames) {
|
166
|
+
// Calculate # of frames to read
|
167
|
+
amount = frames - read;
|
168
|
+
if(amount > temp_len) amount = temp_len;
|
169
|
+
|
170
|
+
r = sf_readf_short(snd->snd, temp, amount);
|
171
|
+
if(r == 0) break;
|
172
|
+
|
173
|
+
// Write every frame channel times to the buffer
|
174
|
+
for(i = 0; i < r; i++) {
|
175
|
+
for(k = 0; k < buf->channels; k++) {
|
176
|
+
data[read * buf->channels + k] = temp[i];
|
177
|
+
}
|
178
|
+
read++;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
} else {
|
182
|
+
rb_raise(eRubyAudioError, "unsupported mix from %d to %d", buf->channels, info->channels);
|
183
|
+
}
|
184
|
+
|
185
|
+
buf->real_size = read;
|
186
|
+
}
|
187
|
+
|
188
|
+
static void ra_sound_read_int(RA_SOUND *snd, RA_BUFFER *buf, sf_count_t frames) {
|
189
|
+
static int temp[1024];
|
190
|
+
int temp_len = 1024;
|
191
|
+
int *data = (int*)buf->data;
|
192
|
+
|
193
|
+
// Get info struct
|
194
|
+
SF_INFO *info;
|
195
|
+
Data_Get_Struct(snd->info, SF_INFO, info);
|
196
|
+
|
197
|
+
// Up/Downmix based on channel matching
|
198
|
+
sf_count_t read = 0, r, amount;
|
199
|
+
int i, k;
|
200
|
+
if(buf->channels == info->channels) { // Simply read data without mix
|
201
|
+
read = sf_readf_int(snd->snd, data, frames);
|
202
|
+
} else if(buf->channels == 1) { // Downmix to mono
|
203
|
+
sf_count_t max = temp_len / info->channels;
|
204
|
+
int channels, mix_sum;
|
205
|
+
|
206
|
+
while(read < frames) {
|
207
|
+
// Calculate # of frames to read
|
208
|
+
amount = frames - read;
|
209
|
+
if(amount > max) amount = max;
|
210
|
+
|
211
|
+
r = sf_readf_int(snd->snd, temp, amount);
|
212
|
+
if(r == 0) break;
|
213
|
+
|
214
|
+
// Mix channels together by averaging all channels and store to buffer
|
215
|
+
for(i = 0; i < r; i++) {
|
216
|
+
mix_sum = 0;
|
217
|
+
for(k = 0; k < info->channels; k++) mix_sum += temp[i * info->channels + k];
|
218
|
+
data[read] = mix_sum/info->channels;
|
219
|
+
read++;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
} else if(info->channels == 1) { // Upmix from mono by copying channel
|
223
|
+
while(read < frames) {
|
224
|
+
// Calculate # of frames to read
|
225
|
+
amount = frames - read;
|
226
|
+
if(amount > temp_len) amount = temp_len;
|
227
|
+
|
228
|
+
r = sf_readf_int(snd->snd, temp, amount);
|
229
|
+
if(r == 0) break;
|
230
|
+
|
231
|
+
// Write every frame channel times to the buffer
|
232
|
+
for(i = 0; i < r; i++) {
|
233
|
+
for(k = 0; k < buf->channels; k++) {
|
234
|
+
data[read * buf->channels + k] = temp[i];
|
235
|
+
}
|
236
|
+
read++;
|
237
|
+
}
|
238
|
+
}
|
239
|
+
} else {
|
240
|
+
rb_raise(eRubyAudioError, "unsupported mix from %d to %d", buf->channels, info->channels);
|
241
|
+
}
|
242
|
+
|
243
|
+
buf->real_size = read;
|
244
|
+
}
|
245
|
+
|
246
|
+
static void ra_sound_read_float(RA_SOUND *snd, RA_BUFFER *buf, sf_count_t frames) {
|
247
|
+
static float temp[1024];
|
248
|
+
int temp_len = 1024;
|
249
|
+
float *data = (float*)buf->data;
|
250
|
+
|
251
|
+
// Get info struct
|
252
|
+
SF_INFO *info;
|
253
|
+
Data_Get_Struct(snd->info, SF_INFO, info);
|
254
|
+
|
255
|
+
// Up/Downmix based on channel matching
|
256
|
+
sf_count_t read = 0, r, amount;
|
257
|
+
int i, k;
|
258
|
+
if(buf->channels == info->channels) { // Simply read data without mix
|
259
|
+
read = sf_readf_float(snd->snd, data, frames);
|
260
|
+
} else if(buf->channels == 1) { // Downmix to mono
|
261
|
+
sf_count_t max = temp_len / info->channels;
|
262
|
+
int channels, mix_sum;
|
263
|
+
|
264
|
+
while(read < frames) {
|
265
|
+
// Calculate # of frames to read
|
266
|
+
amount = frames - read;
|
267
|
+
if(amount > max) amount = max;
|
268
|
+
|
269
|
+
r = sf_readf_float(snd->snd, temp, amount);
|
270
|
+
if(r == 0) break;
|
271
|
+
|
272
|
+
// Mix channels together by averaging all channels and store to buffer
|
273
|
+
for(i = 0; i < r; i++) {
|
274
|
+
mix_sum = 0;
|
275
|
+
for(k = 0; k < info->channels; k++) mix_sum += temp[i * info->channels + k];
|
276
|
+
data[read] = mix_sum/info->channels;
|
277
|
+
read++;
|
278
|
+
}
|
279
|
+
}
|
280
|
+
} else if(info->channels == 1) { // Upmix from mono by copying channel
|
281
|
+
while(read < frames) {
|
282
|
+
// Calculate # of frames to read
|
283
|
+
amount = frames - read;
|
284
|
+
if(amount > temp_len) amount = temp_len;
|
285
|
+
|
286
|
+
r = sf_readf_float(snd->snd, temp, amount);
|
287
|
+
if(r == 0) break;
|
288
|
+
|
289
|
+
// Write every frame channel times to the buffer
|
290
|
+
for(i = 0; i < r; i++) {
|
291
|
+
for(k = 0; k < buf->channels; k++) {
|
292
|
+
data[read * buf->channels + k] = temp[i];
|
293
|
+
}
|
294
|
+
read++;
|
295
|
+
}
|
296
|
+
}
|
297
|
+
} else {
|
298
|
+
rb_raise(eRubyAudioError, "unsupported mix from %d to %d", buf->channels, info->channels);
|
299
|
+
}
|
300
|
+
|
301
|
+
buf->real_size = read;
|
302
|
+
}
|
303
|
+
|
304
|
+
static void ra_sound_read_double(RA_SOUND *snd, RA_BUFFER *buf, sf_count_t frames) {
|
305
|
+
static double temp[1024];
|
306
|
+
int temp_len = 1024;
|
307
|
+
double *data = (double*)buf->data;
|
308
|
+
|
309
|
+
// Get info struct
|
310
|
+
SF_INFO *info;
|
311
|
+
Data_Get_Struct(snd->info, SF_INFO, info);
|
312
|
+
|
313
|
+
// Up/Downmix based on channel matching
|
314
|
+
sf_count_t read = 0, r, amount;
|
315
|
+
int i, k;
|
316
|
+
if(buf->channels == info->channels) { // Simply read data without mix
|
317
|
+
read = sf_readf_double(snd->snd, data, frames);
|
318
|
+
} else if(buf->channels == 1) { // Downmix to mono
|
319
|
+
sf_count_t max = temp_len / info->channels;
|
320
|
+
int channels, mix_sum;
|
321
|
+
|
322
|
+
while(read < frames) {
|
323
|
+
// Calculate # of frames to read
|
324
|
+
amount = frames - read;
|
325
|
+
if(amount > max) amount = max;
|
326
|
+
|
327
|
+
r = sf_readf_double(snd->snd, temp, amount);
|
328
|
+
if(r == 0) break;
|
329
|
+
|
330
|
+
// Mix channels together by averaging all channels and store to buffer
|
331
|
+
for(i = 0; i < r; i++) {
|
332
|
+
mix_sum = 0;
|
333
|
+
for(k = 0; k < info->channels; k++) mix_sum += temp[i * info->channels + k];
|
334
|
+
data[read] = mix_sum/info->channels;
|
335
|
+
read++;
|
336
|
+
}
|
337
|
+
}
|
338
|
+
} else if(info->channels == 1) { // Upmix from mono by copying channel
|
339
|
+
while(read < frames) {
|
340
|
+
// Calculate # of frames to read
|
341
|
+
amount = frames - read;
|
342
|
+
if(amount > temp_len) amount = temp_len;
|
343
|
+
|
344
|
+
r = sf_readf_double(snd->snd, temp, amount);
|
345
|
+
if(r == 0) break;
|
346
|
+
|
347
|
+
// Write every frame channel times to the buffer
|
348
|
+
for(i = 0; i < r; i++) {
|
349
|
+
for(k = 0; k < buf->channels; k++) {
|
350
|
+
data[read * buf->channels + k] = temp[i];
|
351
|
+
}
|
352
|
+
read++;
|
353
|
+
}
|
354
|
+
}
|
355
|
+
} else {
|
356
|
+
rb_raise(eRubyAudioError, "unsupported mix from %d to %d", buf->channels, info->channels);
|
357
|
+
}
|
358
|
+
|
359
|
+
buf->real_size = read;
|
360
|
+
}
|
361
|
+
|
130
362
|
/*
|
131
363
|
* call-seq:
|
132
364
|
* snd.read(buf, frames) => integer
|
@@ -143,39 +375,35 @@ static VALUE ra_sound_read(VALUE self, VALUE buf, VALUE frames) {
|
|
143
375
|
RA_BUFFER *b;
|
144
376
|
Data_Get_Struct(buf, RA_BUFFER, b);
|
145
377
|
|
146
|
-
// Get info struct
|
147
|
-
SF_INFO *info;
|
148
|
-
Data_Get_Struct(snd->info, SF_INFO, info);
|
149
|
-
|
150
|
-
// Check buffer channels matches actual channels
|
151
|
-
if(b->channels != info->channels) {
|
152
|
-
rb_raise(eRubyAudioError, "channel count mismatch: %d vs %d", b->channels, info->channels);
|
153
|
-
}
|
154
|
-
|
155
378
|
// Double-check frame count against buffer size
|
156
379
|
sf_count_t f = (sf_count_t)NUM2OFFT(frames);
|
157
380
|
if(f < 0 || f > b->size) {
|
158
381
|
rb_raise(eRubyAudioError, "frame count invalid");
|
159
382
|
}
|
160
383
|
|
161
|
-
//
|
162
|
-
|
384
|
+
// Shortcut for 0 frame reads
|
385
|
+
if(f == 0) {
|
386
|
+
b->real_size = 0;
|
387
|
+
return INT2FIX(b->real_size);;
|
388
|
+
}
|
389
|
+
|
390
|
+
// Read based on type
|
163
391
|
switch(b->type) {
|
164
392
|
case RA_BUFFER_TYPE_SHORT:
|
165
|
-
|
393
|
+
ra_sound_read_short(snd, b, f);
|
166
394
|
break;
|
167
395
|
case RA_BUFFER_TYPE_INT:
|
168
|
-
|
396
|
+
ra_sound_read_int(snd, b, f);
|
169
397
|
break;
|
170
398
|
case RA_BUFFER_TYPE_FLOAT:
|
171
|
-
|
399
|
+
ra_sound_read_float(snd, b, f);
|
172
400
|
break;
|
173
401
|
case RA_BUFFER_TYPE_DOUBLE:
|
174
|
-
|
402
|
+
ra_sound_read_double(snd, b, f);
|
175
403
|
break;
|
176
404
|
}
|
177
|
-
b->real_size = read;
|
178
405
|
|
406
|
+
// Return read
|
179
407
|
return INT2FIX(b->real_size);
|
180
408
|
}
|
181
409
|
|
data/spec/buffer_spec.rb
CHANGED
@@ -47,4 +47,16 @@ describe RubyAudio::Buffer do
|
|
47
47
|
buf.real_size = 101
|
48
48
|
buf.real_size.should == 100
|
49
49
|
end
|
50
|
+
|
51
|
+
it "should support cloning/duping" do
|
52
|
+
buf = RubyAudio::Buffer.int(100)
|
53
|
+
buf[4] = 100
|
54
|
+
|
55
|
+
buf2 = buf.dup
|
56
|
+
buf2.size.should == buf.size
|
57
|
+
buf2[4].should == 100
|
58
|
+
|
59
|
+
buf[4] = 140
|
60
|
+
buf2[4].should == 100
|
61
|
+
end
|
50
62
|
end
|
data/spec/sound_spec.rb
CHANGED
@@ -100,13 +100,38 @@ describe RubyAudio::Sound do
|
|
100
100
|
buf[100].should == nil
|
101
101
|
end
|
102
102
|
|
103
|
-
it "should
|
104
|
-
buf = RubyAudio::Buffer.
|
103
|
+
it "should allow downmixing to mono on read" do
|
104
|
+
buf = RubyAudio::Buffer.int(100, 1)
|
105
|
+
buf2 = RubyAudio::Buffer.int(100, 2)
|
106
|
+
RubyAudio::Sound.open(STEREO_TEST_WAV, 'r') do |snd|
|
107
|
+
snd.read(buf)
|
108
|
+
snd.seek(0)
|
109
|
+
snd.read(buf2)
|
110
|
+
|
111
|
+
f = buf2[99]
|
112
|
+
buf[99].should == (f[0] + f[1]) / 2
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should allow upmixing from mono on read" do
|
117
|
+
buf = RubyAudio::Buffer.int(100, 1)
|
118
|
+
buf2 = RubyAudio::Buffer.int(100, 2)
|
119
|
+
RubyAudio::Sound.open(STEREO_TEST_WAV, 'r') do |snd|
|
120
|
+
snd.read(buf2)
|
121
|
+
snd.seek(0)
|
122
|
+
snd.read(buf)
|
123
|
+
|
124
|
+
buf2[99].should == [buf[99], buf[99]]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should fail read on unsupported up/downmixing" do
|
129
|
+
buf = RubyAudio::Buffer.float(100, 5)
|
105
130
|
lambda {
|
106
131
|
RubyAudio::Sound.open(STEREO_TEST_WAV) do |snd|
|
107
132
|
snd.read(buf)
|
108
133
|
end
|
109
|
-
}.should raise_error(RubyAudio::Error, "
|
134
|
+
}.should raise_error(RubyAudio::Error, "unsupported mix from 5 to 2")
|
110
135
|
end
|
111
136
|
|
112
137
|
it "should allow writing to a new sound" do
|
@@ -144,4 +169,14 @@ describe RubyAudio::Sound do
|
|
144
169
|
|
145
170
|
out_buf[50].should == in_buf[50]
|
146
171
|
end
|
172
|
+
|
173
|
+
it "should fail write on channel mismatch" do
|
174
|
+
buf = RubyAudio::Buffer.float(100, 5)
|
175
|
+
info = RubyAudio::SoundInfo.new :channels => 2, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
|
176
|
+
lambda {
|
177
|
+
RubyAudio::Sound.open(OUT_WAV, 'w', info) do |snd|
|
178
|
+
snd.write(buf)
|
179
|
+
end
|
180
|
+
}.should raise_error(RubyAudio::Error, "channel count mismatch: 5 vs 2")
|
181
|
+
end
|
147
182
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-audio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Augenstein
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-03-
|
12
|
+
date: 2010-03-24 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|