coreaudio 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +4 -1
- data/README.rdoc +2 -2
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/coreaudio.gemspec +11 -3
- data/examples/convert_wav_to_m4a.rb +19 -0
- data/ext/audiofile.m +214 -57
- data/ext/coreaudio.h +16 -1
- data/ext/coreaudio.m +1 -1
- data/ext/coreaudio_missing.c +24 -0
- data/ext/extconf.rb +9 -0
- metadata +32 -8
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -9,10 +9,10 @@ CoreAudio (Audio Framework of Mac OS X) wrapper library for ruby 1.9
|
|
9
9
|
* Output audio data (Loop buffer, Stream buffer)
|
10
10
|
* Input audio data (Stream buffer)
|
11
11
|
* Save audio data to WAV/M4A file (wrapper for ExtAudioFile)
|
12
|
+
* Ream audio file (WAV/M4A)
|
12
13
|
|
13
14
|
== ToDo
|
14
|
-
* Switch input/output audio sample type (signed 16bit integer,
|
15
|
-
* Read audio file (wrapper for ExtAudioFile)
|
15
|
+
* Switch input/output audio sample type (signed 16bit integer, packed String)
|
16
16
|
* Wrapper for AudioUnit/AudioGraph
|
17
17
|
|
18
18
|
== Contributing to coreaudio
|
data/Rakefile
CHANGED
@@ -15,7 +15,7 @@ require 'jeweler'
|
|
15
15
|
Jeweler::Tasks.new do |gem|
|
16
16
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
17
|
gem.name = "coreaudio"
|
18
|
-
gem.homepage = "
|
18
|
+
gem.homepage = "https://github.com/nagachika/ruby-coreaudio"
|
19
19
|
gem.license = "BSDL"
|
20
20
|
gem.summary = %Q{Mac OS X CoreAudio wrapper library}
|
21
21
|
gem.description = %Q{Mac OS X CoreAudio wrapper library}
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/coreaudio.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "coreaudio"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["CHIKANAGA Tomoyuki"]
|
12
|
-
s.date = "2011-10-
|
12
|
+
s.date = "2011-10-16"
|
13
13
|
s.description = "Mac OS X CoreAudio wrapper library"
|
14
14
|
s.email = "nagachika00@gmail.com"
|
15
15
|
s.extensions = ["ext/extconf.rb"]
|
@@ -26,17 +26,19 @@ Gem::Specification.new do |s|
|
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
28
|
"coreaudio.gemspec",
|
29
|
+
"examples/convert_wav_to_m4a.rb",
|
29
30
|
"examples/outbuffer_sine.rb",
|
30
31
|
"examples/outloop_sine.rb",
|
31
32
|
"examples/record_to_wave.rb",
|
32
33
|
"ext/audiofile.m",
|
33
34
|
"ext/coreaudio.h",
|
34
35
|
"ext/coreaudio.m",
|
36
|
+
"ext/coreaudio_missing.c",
|
35
37
|
"ext/depend",
|
36
38
|
"ext/extconf.rb",
|
37
39
|
"lib/coreaudio.rb"
|
38
40
|
]
|
39
|
-
s.homepage = "
|
41
|
+
s.homepage = "https://github.com/nagachika/ruby-coreaudio"
|
40
42
|
s.licenses = ["BSDL"]
|
41
43
|
s.require_paths = ["lib"]
|
42
44
|
s.rubygems_version = "1.8.11"
|
@@ -48,13 +50,19 @@ Gem::Specification.new do |s|
|
|
48
50
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
51
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
50
52
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
53
|
+
s.add_development_dependency(%q<rake>, ["~> 0.9.2"])
|
54
|
+
s.add_development_dependency(%q<rdoc>, [">= 0"])
|
51
55
|
else
|
52
56
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
53
57
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
58
|
+
s.add_dependency(%q<rake>, ["~> 0.9.2"])
|
59
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
54
60
|
end
|
55
61
|
else
|
56
62
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
57
63
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
64
|
+
s.add_dependency(%q<rake>, ["~> 0.9.2"])
|
65
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
58
66
|
end
|
59
67
|
end
|
60
68
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "coreaudio"
|
4
|
+
|
5
|
+
wav = CoreAudio::AudioFile.new("sample.wav", :read)
|
6
|
+
|
7
|
+
m4a = CoreAudio::AudioFile.new("sample.m4a", :write, :format => :m4a,
|
8
|
+
:rate => wav.rate,
|
9
|
+
:channel => wav.channel)
|
10
|
+
|
11
|
+
loop do
|
12
|
+
buf = wav.read(1024)
|
13
|
+
break if buf.empty?
|
14
|
+
m4a.write(buf)
|
15
|
+
end
|
16
|
+
|
17
|
+
wav.close
|
18
|
+
m4a.close
|
19
|
+
|
data/ext/audiofile.m
CHANGED
@@ -49,7 +49,7 @@ ca_audio_file_free(void *ptr)
|
|
49
49
|
ca_audio_file_t *data = ptr;
|
50
50
|
|
51
51
|
if ( data->file ) {
|
52
|
-
|
52
|
+
ExtAudioFileDispose(data->file);
|
53
53
|
data->file = NULL;
|
54
54
|
}
|
55
55
|
}
|
@@ -77,6 +77,42 @@ ca_audio_file_alloc(VALUE klass)
|
|
77
77
|
return obj;
|
78
78
|
}
|
79
79
|
|
80
|
+
static void
|
81
|
+
parse_audio_file_options(VALUE opt, Boolean for_write,
|
82
|
+
Float64 *rate, Float64 *file_rate,
|
83
|
+
UInt32 *channel, UInt32 *file_channel)
|
84
|
+
{
|
85
|
+
if (NIL_P(opt) || NIL_P(rb_hash_aref(opt, sym_rate))) {
|
86
|
+
if (for_write)
|
87
|
+
*rate = 44100.0;
|
88
|
+
else
|
89
|
+
*rate = *file_rate;
|
90
|
+
} else {
|
91
|
+
*rate = NUM2DBL(rb_hash_aref(opt, sym_rate));
|
92
|
+
}
|
93
|
+
if (NIL_P(opt) || NIL_P(rb_hash_aref(opt, sym_channel))) {
|
94
|
+
if (for_write)
|
95
|
+
*channel = 2;
|
96
|
+
else
|
97
|
+
*channel = *file_channel;
|
98
|
+
} else {
|
99
|
+
*channel = NUM2UINT(rb_hash_aref(opt, sym_channel));
|
100
|
+
}
|
101
|
+
|
102
|
+
if (for_write) {
|
103
|
+
if (NIL_P(opt) || NIL_P(rb_hash_aref(opt, sym_file_rate))) {
|
104
|
+
*file_rate = *rate;
|
105
|
+
} else {
|
106
|
+
*file_rate = NUM2DBL(rb_hash_aref(opt, sym_file_rate));
|
107
|
+
}
|
108
|
+
if (NIL_P(opt) || NIL_P(rb_hash_aref(opt, sym_file_channel))) {
|
109
|
+
*file_channel = *channel;
|
110
|
+
} else {
|
111
|
+
*file_channel = NUM2UINT(rb_hash_aref(opt, sym_file_channel));
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
80
116
|
/*
|
81
117
|
* call-seq:
|
82
118
|
* AudioFile.new(filepath, mode, opt)
|
@@ -88,11 +124,11 @@ ca_audio_file_alloc(VALUE klass)
|
|
88
124
|
* 'client data' means audio data pass to AudioFile#write or from
|
89
125
|
* AudioFile#read method.
|
90
126
|
*
|
91
|
-
* :format :: audio file format. currently audio file format and
|
127
|
+
* :format :: audio file format. currently audio file format and
|
92
128
|
* codec type is hardcoded. (:wav, :m4a)
|
93
129
|
* :rate :: sample rate of data pass from AudioFile#read or to AudioFile#write
|
94
130
|
* If not specified, :file_rate value is used. (Float)
|
95
|
-
* :channel :: number of channels
|
131
|
+
* :channel :: number of channels
|
96
132
|
* :file_rate :: file data sample rate. only work when open for output. (Float)
|
97
133
|
* :file_channel :: file data number of channels. only work when open for
|
98
134
|
* output.
|
@@ -104,9 +140,8 @@ ca_audio_file_initialize(int argc, VALUE *argv, VALUE self)
|
|
104
140
|
VALUE path, mode, opt, format;
|
105
141
|
Float64 rate, file_rate;
|
106
142
|
UInt32 channel, file_channel;
|
107
|
-
CFURLRef
|
108
|
-
AudioFileTypeID filetype;
|
109
|
-
UInt32 flags = kAudioFileFlags_EraseFile;
|
143
|
+
CFURLRef url = NULL;
|
144
|
+
AudioFileTypeID filetype = 0;
|
110
145
|
OSStatus err = noErr;
|
111
146
|
|
112
147
|
TypedData_Get_Struct(self, ca_audio_file_t, &ca_audio_file_type, data);
|
@@ -117,65 +152,70 @@ ca_audio_file_initialize(int argc, VALUE *argv, VALUE self)
|
|
117
152
|
if (NIL_P(mode) || mode == sym_read)
|
118
153
|
data->for_write = FALSE;
|
119
154
|
else if (mode == sym_write)
|
120
|
-
|
155
|
+
data->for_write = TRUE;
|
121
156
|
else
|
122
157
|
rb_raise(rb_eArgError, "coreaudio: mode should be :read or :write");
|
123
158
|
|
124
|
-
|
125
|
-
|
126
|
-
rate
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
if (format == sym_wav) {
|
151
|
-
filetype = kAudioFileWAVEType;
|
152
|
-
setASBD(&data->file_desc, file_rate, kAudioFormatLinearPCM,
|
153
|
-
kLinearPCMFormatFlagIsSignedInteger |
|
154
|
-
kAudioFormatFlagIsPacked,
|
155
|
-
file_channel, 16, 1);
|
156
|
-
} else if (format == sym_m4a) {
|
157
|
-
filetype = kAudioFileM4AType;
|
158
|
-
setASBD(&data->file_desc, file_rate, kAudioFormatMPEG4AAC,
|
159
|
-
0, file_channel, 0, 0);
|
160
|
-
} else {
|
161
|
-
volatile VALUE str = rb_inspect(format);
|
162
|
-
RB_GC_GUARD(str);
|
163
|
-
rb_raise(rb_eArgError, "coreaudio: unsupported format (%s)",
|
164
|
-
RSTRING_PTR(str));
|
159
|
+
if (data->for_write) {
|
160
|
+
/* when open for write, parse options before open ExtAudioFile */
|
161
|
+
parse_audio_file_options(opt, data->for_write, &rate, &file_rate,
|
162
|
+
&channel, &file_channel);
|
163
|
+
|
164
|
+
format = rb_hash_aref(opt, sym_format);
|
165
|
+
if (NIL_P(format))
|
166
|
+
rb_raise(rb_eArgError, "coreaudio: :format option must be specified");
|
167
|
+
|
168
|
+
if (format == sym_wav) {
|
169
|
+
filetype = kAudioFileWAVEType;
|
170
|
+
setASBD(&data->file_desc, file_rate, kAudioFormatLinearPCM,
|
171
|
+
kLinearPCMFormatFlagIsSignedInteger |
|
172
|
+
kAudioFormatFlagIsPacked,
|
173
|
+
file_channel, 16, 1);
|
174
|
+
} else if (format == sym_m4a) {
|
175
|
+
filetype = kAudioFileM4AType;
|
176
|
+
setASBD(&data->file_desc, file_rate, kAudioFormatMPEG4AAC,
|
177
|
+
0, file_channel, 0, 0);
|
178
|
+
} else {
|
179
|
+
volatile VALUE str = rb_inspect(format);
|
180
|
+
RB_GC_GUARD(str);
|
181
|
+
rb_raise(rb_eArgError, "coreaudio: unsupported format (%s)",
|
182
|
+
RSTRING_PTR(str));
|
183
|
+
}
|
165
184
|
}
|
166
185
|
|
167
186
|
/* create URL represent the target filepath */
|
168
|
-
|
187
|
+
url = CFURLCreateFromFileSystemRepresentation(
|
169
188
|
NULL, StringValueCStr(path), (CFIndex)RSTRING_LEN(path), FALSE);
|
170
189
|
|
171
190
|
/* open ExtAudioFile */
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
191
|
+
if (data->for_write)
|
192
|
+
err = ExtAudioFileCreateWithURL(url, filetype, &data->file_desc,
|
193
|
+
NULL, kAudioFileFlags_EraseFile,
|
194
|
+
&data->file);
|
195
|
+
else
|
196
|
+
err = ExtAudioFileOpenURL(url, &data->file);
|
197
|
+
CFRelease(url);
|
198
|
+
url = NULL;
|
176
199
|
if (err != noErr) {
|
177
200
|
rb_raise(rb_eArgError,
|
178
|
-
"coreaudio:
|
201
|
+
"coreaudio: fail to open ExtAudioFile: %d", (int)err);
|
202
|
+
}
|
203
|
+
|
204
|
+
/* get Audio Stream Basic Description (ASBD) from input file */
|
205
|
+
if (!data->for_write) {
|
206
|
+
UInt32 size = sizeof(data->file_desc);
|
207
|
+
err = ExtAudioFileGetProperty(data->file,
|
208
|
+
kExtAudioFileProperty_FileDataFormat,
|
209
|
+
&size, &data->file_desc);
|
210
|
+
if (err != noErr)
|
211
|
+
rb_raise(rb_eRuntimeError,
|
212
|
+
"coreaudio: fail to Get ExtAudioFile Property %d", err);
|
213
|
+
|
214
|
+
/* parse options */
|
215
|
+
file_rate = data->file_desc.mSampleRate;
|
216
|
+
file_channel = data->file_desc.mChannelsPerFrame;
|
217
|
+
parse_audio_file_options(opt, data->for_write, &rate, &file_rate,
|
218
|
+
&channel, &file_channel);
|
179
219
|
}
|
180
220
|
|
181
221
|
setASBD(&data->inner_desc, rate, kAudioFormatLinearPCM,
|
@@ -217,6 +257,7 @@ ca_audio_file_write(VALUE self, VALUE data)
|
|
217
257
|
AudioBufferList buf_list;
|
218
258
|
UInt32 frames;
|
219
259
|
size_t alloc_size;
|
260
|
+
volatile VALUE tmpstr;
|
220
261
|
OSStatus err = noErr;
|
221
262
|
int i;
|
222
263
|
|
@@ -225,6 +266,12 @@ ca_audio_file_write(VALUE self, VALUE data)
|
|
225
266
|
|
226
267
|
TypedData_Get_Struct(self, ca_audio_file_t, &ca_audio_file_type, file);
|
227
268
|
|
269
|
+
if (file->file == NULL)
|
270
|
+
rb_raise(rb_eIOError, "coreaudio: already closend file");
|
271
|
+
|
272
|
+
if (!file->for_write)
|
273
|
+
rb_raise(rb_eRuntimeError, "coreaudio: audio file opened for reading");
|
274
|
+
|
228
275
|
frames = RARRAY_LENINT(data) / file->inner_desc.mChannelsPerFrame;
|
229
276
|
alloc_size = (file->inner_desc.mBitsPerChannel/8) * RARRAY_LEN(data);
|
230
277
|
|
@@ -232,7 +279,7 @@ ca_audio_file_write(VALUE self, VALUE data)
|
|
232
279
|
buf_list.mNumberBuffers = 1;
|
233
280
|
buf_list.mBuffers[0].mNumberChannels = file->inner_desc.mChannelsPerFrame;
|
234
281
|
buf_list.mBuffers[0].mDataByteSize = (UInt32)alloc_size;
|
235
|
-
buf_list.mBuffers[0].mData =
|
282
|
+
buf_list.mBuffers[0].mData = rb_alloc_tmp_buffer(&tmpstr, alloc_size);
|
236
283
|
buf = buf_list.mBuffers[0].mData;
|
237
284
|
|
238
285
|
for (i = 0; i < RARRAY_LEN(data); i++) {
|
@@ -241,7 +288,7 @@ ca_audio_file_write(VALUE self, VALUE data)
|
|
241
288
|
|
242
289
|
err = ExtAudioFileWrite(file->file, frames, &buf_list);
|
243
290
|
|
244
|
-
|
291
|
+
rb_free_tmp_buffer(&tmpstr);
|
245
292
|
|
246
293
|
if (err != noErr) {
|
247
294
|
rb_raise(rb_eRuntimeError,
|
@@ -251,6 +298,112 @@ ca_audio_file_write(VALUE self, VALUE data)
|
|
251
298
|
return self;
|
252
299
|
}
|
253
300
|
|
301
|
+
static VALUE
|
302
|
+
ca_audio_file_read(int argc, VALUE *argv, VALUE self)
|
303
|
+
{
|
304
|
+
ca_audio_file_t *file;
|
305
|
+
VALUE frame_val;
|
306
|
+
UInt32 frames, chunk, total, read_frames;
|
307
|
+
AudioBufferList buf_list;
|
308
|
+
short *buf;
|
309
|
+
size_t alloc_size;
|
310
|
+
volatile VALUE tmpstr;
|
311
|
+
VALUE ary;
|
312
|
+
UInt32 i;
|
313
|
+
OSStatus err = noErr;
|
314
|
+
|
315
|
+
TypedData_Get_Struct(self, ca_audio_file_t, &ca_audio_file_type, file);
|
316
|
+
|
317
|
+
if (file->file == NULL)
|
318
|
+
rb_raise(rb_eIOError, "coreaudio: already closend file");
|
319
|
+
|
320
|
+
if (file->for_write)
|
321
|
+
rb_raise(rb_eRuntimeError, "coreaudio: audio file open for writing");
|
322
|
+
|
323
|
+
rb_scan_args(argc, argv, "01", &frame_val);
|
324
|
+
|
325
|
+
if (NIL_P(frame_val)) {
|
326
|
+
frames = 0;
|
327
|
+
chunk = 1024;
|
328
|
+
} else {
|
329
|
+
frames = chunk = NUM2UINT(frame_val);
|
330
|
+
}
|
331
|
+
|
332
|
+
alloc_size = (file->inner_desc.mBitsPerChannel/8) *
|
333
|
+
file->inner_desc.mChannelsPerFrame * chunk;
|
334
|
+
|
335
|
+
/* prepare interleaved audio buffer */
|
336
|
+
buf_list.mNumberBuffers = 1;
|
337
|
+
buf_list.mBuffers[0].mNumberChannels = file->inner_desc.mChannelsPerFrame;
|
338
|
+
buf_list.mBuffers[0].mDataByteSize = (UInt32)alloc_size;
|
339
|
+
buf_list.mBuffers[0].mData = rb_alloc_tmp_buffer(&tmpstr, alloc_size);
|
340
|
+
buf = buf_list.mBuffers[0].mData;
|
341
|
+
|
342
|
+
ary = rb_ary_new2(chunk*file->inner_desc.mChannelsPerFrame);
|
343
|
+
|
344
|
+
for (total = 0; total < frames || frames == 0; total += read_frames) {
|
345
|
+
read_frames = chunk;
|
346
|
+
err = ExtAudioFileRead(file->file, &read_frames, &buf_list);
|
347
|
+
|
348
|
+
if (err != noErr) {
|
349
|
+
rb_free_tmp_buffer(&tmpstr);
|
350
|
+
rb_raise(rb_eRuntimeError,
|
351
|
+
"coreaudio: ExtAudioFileRead() fails: %d", (int)err);
|
352
|
+
}
|
353
|
+
|
354
|
+
if (read_frames == 0)
|
355
|
+
break;
|
356
|
+
|
357
|
+
for (i = 0; i < read_frames * file->inner_desc.mChannelsPerFrame; i++) {
|
358
|
+
rb_ary_push(ary, INT2NUM((int)buf[i]));
|
359
|
+
}
|
360
|
+
}
|
361
|
+
|
362
|
+
rb_free_tmp_buffer(&tmpstr);
|
363
|
+
|
364
|
+
return ary;
|
365
|
+
}
|
366
|
+
|
367
|
+
static VALUE
|
368
|
+
ca_audio_file_rate(VALUE self)
|
369
|
+
{
|
370
|
+
ca_audio_file_t *data;
|
371
|
+
|
372
|
+
TypedData_Get_Struct(self, ca_audio_file_t, &ca_audio_file_type, data);
|
373
|
+
|
374
|
+
return DBL2NUM(data->file_desc.mSampleRate);
|
375
|
+
}
|
376
|
+
|
377
|
+
static VALUE
|
378
|
+
ca_audio_file_channel(VALUE self)
|
379
|
+
{
|
380
|
+
ca_audio_file_t *data;
|
381
|
+
|
382
|
+
TypedData_Get_Struct(self, ca_audio_file_t, &ca_audio_file_type, data);
|
383
|
+
|
384
|
+
return UINT2NUM((unsigned int)data->file_desc.mChannelsPerFrame);
|
385
|
+
}
|
386
|
+
|
387
|
+
static VALUE
|
388
|
+
ca_audio_file_inner_rate(VALUE self)
|
389
|
+
{
|
390
|
+
ca_audio_file_t *data;
|
391
|
+
|
392
|
+
TypedData_Get_Struct(self, ca_audio_file_t, &ca_audio_file_type, data);
|
393
|
+
|
394
|
+
return DBL2NUM(data->inner_desc.mSampleRate);
|
395
|
+
}
|
396
|
+
|
397
|
+
static VALUE
|
398
|
+
ca_audio_file_inner_channel(VALUE self)
|
399
|
+
{
|
400
|
+
ca_audio_file_t *data;
|
401
|
+
|
402
|
+
TypedData_Get_Struct(self, ca_audio_file_t, &ca_audio_file_type, data);
|
403
|
+
|
404
|
+
return UINT2NUM((unsigned int)data->inner_desc.mChannelsPerFrame);
|
405
|
+
}
|
406
|
+
|
254
407
|
void
|
255
408
|
Init_coreaudio_audiofile(void)
|
256
409
|
{
|
@@ -266,10 +419,14 @@ Init_coreaudio_audiofile(void)
|
|
266
419
|
|
267
420
|
rb_cAudioFile = rb_define_class_under(rb_mCoreAudio, "AudioFile",
|
268
421
|
rb_cObject);
|
269
|
-
rb_global_variable(&rb_cAudioFile);
|
270
422
|
|
271
423
|
rb_define_alloc_func(rb_cAudioFile, ca_audio_file_alloc);
|
272
424
|
rb_define_method(rb_cAudioFile, "initialize", ca_audio_file_initialize, -1);
|
273
425
|
rb_define_method(rb_cAudioFile, "close", ca_audio_file_close, 0);
|
274
426
|
rb_define_method(rb_cAudioFile, "write", ca_audio_file_write, 1);
|
427
|
+
rb_define_method(rb_cAudioFile, "read", ca_audio_file_read, -1);
|
428
|
+
rb_define_method(rb_cAudioFile, "rate", ca_audio_file_rate, 0);
|
429
|
+
rb_define_method(rb_cAudioFile, "channel", ca_audio_file_channel, 0);
|
430
|
+
rb_define_method(rb_cAudioFile, "inner_rate", ca_audio_file_inner_rate, 0);
|
431
|
+
rb_define_method(rb_cAudioFile, "inner_channel", ca_audio_file_inner_channel, 0);
|
275
432
|
}
|
data/ext/coreaudio.h
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
#ifndef COREAUDIO_H
|
2
2
|
#define COREAUDIO_H 1
|
3
3
|
|
4
|
+
#include <ruby.h>
|
5
|
+
|
6
|
+
#include "extconf.h"
|
7
|
+
|
4
8
|
extern VALUE rb_mCoreAudio;
|
5
9
|
extern VALUE rb_mAudioFile;
|
6
10
|
|
@@ -9,6 +13,17 @@ extern void Init_coreaudio_audiofile(void);
|
|
9
13
|
/*-- Utility Macros --*/
|
10
14
|
#define CROPF(F) ((F) > 1.0 ? 1.0 : (((F) < -1.0) ? -1.0 : (F)))
|
11
15
|
#define FLOAT2SHORT(F) ((short)(CROPF(F)*0x7FFF))
|
12
|
-
#define SHORT2FLOAT(S) ((
|
16
|
+
#define SHORT2FLOAT(S) ((float)(S) / (float)32767.0)
|
17
|
+
|
18
|
+
/*-- prototypes for missing functions --*/
|
19
|
+
|
20
|
+
#ifndef HAVE_RB_ALLOC_TMP_BUFFER
|
21
|
+
extern void *rb_alloc_tmp_buffer(volatile VALUE *store, long len);
|
22
|
+
#endif
|
23
|
+
|
24
|
+
#ifndef HAVE_RB_FREE_TMP_BUFFER
|
25
|
+
extern void rb_free_tmp_buffer(volatile VALUE *store);
|
26
|
+
#endif
|
27
|
+
|
13
28
|
|
14
29
|
#endif
|
data/ext/coreaudio.m
CHANGED
@@ -422,7 +422,7 @@ ca_out_loop_proc(
|
|
422
422
|
float *ptr = outOutputData->mBuffers[i].mData;
|
423
423
|
UInt32 size = outOutputData->mBuffers[i].mDataByteSize / (UInt32)sizeof(float) / channel;
|
424
424
|
UInt32 offset = (UInt32)inOutputTime->mSampleTime % loop_data->frame;
|
425
|
-
|
425
|
+
UInt32 copied = 0;
|
426
426
|
|
427
427
|
if (outOutputData->mBuffers[i].mNumberChannels != channel) {
|
428
428
|
memset(ptr, 0, size * channel * sizeof(float));
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "coreaudio.h"
|
4
|
+
|
5
|
+
#ifndef HAVE_RB_ALLOC_TMP_BUFFER
|
6
|
+
void *
|
7
|
+
rb_alloc_tmp_buffer(volatile VALUE *store, long len)
|
8
|
+
{
|
9
|
+
VALUE s = rb_str_tmp_new(len);
|
10
|
+
*store = s;
|
11
|
+
return RSTRING_PTR(s);
|
12
|
+
}
|
13
|
+
#endif
|
14
|
+
|
15
|
+
#ifndef HAVE_RB_FREE_TMP_BUFFER
|
16
|
+
void
|
17
|
+
rb_free_tmp_buffer(volatile VALUE *store)
|
18
|
+
{
|
19
|
+
VALUE s = *store;
|
20
|
+
*store = 0;
|
21
|
+
if (s) rb_str_clear(s);
|
22
|
+
}
|
23
|
+
#endif
|
24
|
+
|
data/ext/extconf.rb
CHANGED
@@ -22,7 +22,16 @@ if have_framework("CoreAudio") and
|
|
22
22
|
have_framework("AudioToolBox") and
|
23
23
|
have_framework("CoreFoundation") and
|
24
24
|
have_framework("Cocoa")
|
25
|
+
|
26
|
+
# check ruby API
|
27
|
+
have_func("rb_alloc_tmp_buffer", "ruby.h")
|
28
|
+
have_func("rb_free_tmp_buffer", "ruby.h")
|
29
|
+
|
30
|
+
create_header
|
31
|
+
|
32
|
+
# create Makefile
|
25
33
|
create_makefile("coreaudio/coreaudio_ext")
|
34
|
+
|
26
35
|
# workaround for mkmf.rb in 1.9.2
|
27
36
|
if RUBY_VERSION < "1.9.3"
|
28
37
|
open("Makefile", "a") do |f|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coreaudio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
16
|
-
requirement: &
|
16
|
+
requirement: &2152377300 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.0.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2152377300
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: jeweler
|
27
|
-
requirement: &
|
27
|
+
requirement: &2152375220 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,29 @@ dependencies:
|
|
32
32
|
version: 1.6.4
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2152375220
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &2152373440 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.9.2
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2152373440
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rdoc
|
49
|
+
requirement: &2152387460 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2152387460
|
36
58
|
description: Mac OS X CoreAudio wrapper library
|
37
59
|
email: nagachika00@gmail.com
|
38
60
|
executables: []
|
@@ -50,16 +72,18 @@ files:
|
|
50
72
|
- Rakefile
|
51
73
|
- VERSION
|
52
74
|
- coreaudio.gemspec
|
75
|
+
- examples/convert_wav_to_m4a.rb
|
53
76
|
- examples/outbuffer_sine.rb
|
54
77
|
- examples/outloop_sine.rb
|
55
78
|
- examples/record_to_wave.rb
|
56
79
|
- ext/audiofile.m
|
57
80
|
- ext/coreaudio.h
|
58
81
|
- ext/coreaudio.m
|
82
|
+
- ext/coreaudio_missing.c
|
59
83
|
- ext/depend
|
60
84
|
- ext/extconf.rb
|
61
85
|
- lib/coreaudio.rb
|
62
|
-
homepage:
|
86
|
+
homepage: https://github.com/nagachika/ruby-coreaudio
|
63
87
|
licenses:
|
64
88
|
- BSDL
|
65
89
|
post_install_message:
|
@@ -74,7 +98,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
98
|
version: '0'
|
75
99
|
segments:
|
76
100
|
- 0
|
77
|
-
hash:
|
101
|
+
hash: -1259507067134800519
|
78
102
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
103
|
none: false
|
80
104
|
requirements:
|